通过泛型方法省略其参数?

时间:2015-11-27 02:56:53

标签: c# generics lambda expression-trees

有没有办法以通用方式传递方法名称,而不传递其参数,因此可以通过传递参数调用方法?

考虑这个例子:

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

更新
我想避免指定参数。整个想法是从指定的行动中推断出来。

2 个答案:

答案 0 :(得分:2)

您希望传递给Invoke的表达式返回接受Func的{​​{1}}。在代码中:

TArg

然后您可以这样调用它:

public class Wrapper<TClient>
{
    TClient Client;

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

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

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

您可以这样调用,使用从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

答案 1 :(得分:2)

您非常接近让代码运行。有两种选择。

首先,你可以试试这个:

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);

但是,根据您对问题的描述,我不知道其中任何一个是如何帮助的,而我也不知道如何实施您的问题。也许你需要提供更多细节,说明你需要解决的潜在需求是什么?