传递省略其参数的泛型方法

本文关键字:泛型方法 参数 递省 | 更新日期: 2023-09-27 18:24:44

有没有一种方法可以以通用的方式传递方法名称,而不传递其参数,这样它就可以由方法调用,并传递参数?

考虑这个例子:

public class Client
{
  public string Convert(int value)
  {
    return value.ToString();
  }
}
public class Wrapper<TClient>
{
  TClient Client;
  public TResult Invoke<TArg, TResult>(Func<TClient, TArg, TResult> action, TArg arg)
  {
    return action(Client, arg);
  }
}

我希望能够将我想要调用的TClient的方法传递给包装器,并传递实际的参数,所有这些都是通用的:

var wrapper = new Wrapper<Client>();
wrapper.Invoke(c => c.Convert, 5);

有没有任何可能的方法可以实现这一点,而不必对方法名称进行硬编码,也不必失去其通用性(即使用Delegate)?

注:

Client是一个外部密封类,它公开了许多参数中的每个参数的大量方法。我想要包装它的行为,我不介意在包装器中编写所有必要的代码,但包装器的使用应该尽可能干净。

更新
我想避免指定参数的需要。整个想法是从指定的动作中推断出它们。

传递省略其参数的泛型方法

您的代码即将运行。有两种选择。

首先,你可以试试这个:

public class Wrapper<TClient>
{
    public TResult Invoke<TArg, TResult>(Func<TArg, TResult> action, TArg arg)
    {
        return action(arg);
    }
}

然后这样称呼它:

var wrapper = new Wrapper<Client>();    
wrapper.Invoke(wrapper.client.Convert, 5);

或者,你也可以这样做:

public class Wrapper<TClient>
{
    public Wrapper(TClient client)
    {
        this.Client = client;
    }
    private TClient Client;
    public TResult Invoke<TArg, TResult>(Func<TClient, TArg, TResult> action, TArg arg)
    {
        if (operation.Target != Client)
          throw new ArgumentException(nameof(operation));
        return action(this.Client, arg);
    }
}

这样称呼它:

var client = new Client();
var wrapper = new Wrapper<Client>(client);
wrapper.Invoke((c, a) => c.Convert(a), 5);

但是,从你对问题的描述来看,我看不出这两种方法有什么帮助,也不知道如何实现你的要求。也许你需要提供更多关于你试图解决的潜在需求的细节?

您希望传递给Invoke的表达式返回接受TArgFunc。代码中:

public class Wrapper<TClient>
{
    TClient Client;
    public TResult Invoke<TArg, TResult>(Func<TClient, Func<TArg, TResult>> action, TArg arg)
    {
        return action(Client)(arg);
    }
}

然后你可以这样调用它:

class Program
{
    static void Main(string[] args)
    {
        var wrapper = new Wrapper<Client>();
        string result = wrapper.Invoke<int, string>(c => c.Convert, 5);
    }
}

由于您不喜欢必须显式指定类型参数的方法,因此可以使用稍微不同的API(它有自己的烦恼):

public class Wrapper<TClient>
{
    TClient Client;
    public void Invoke<TArg, TResult>(Func<TClient, Func<TArg, TResult>> action, TArg arg, out TResult result)
    {
        return action(Client)(arg);
    }
}

您可以这样调用它,返回类型由out参数推断:

class Program
{
    static void Main(string[] args)
    {
        var wrapper = new Wrapper<Client>();
        string result;
        wrapper.Invoke(c => c.Convert, 5, out result);
    }
}