Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否传递忽略其参数的泛型方法?_C#_Generics_Lambda_Expression Trees - Fatal编程技术网

C# 是否传递忽略其参数的泛型方法?

C# 是否传递忽略其参数的泛型方法?,c#,generics,lambda,expression-trees,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

有没有一种方法可以在不传递参数的情况下以通用方式传递方法名,这样方法就可以使用传递的参数调用它

考虑这个例子:

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);
  }
}
是否有任何可能的方法来实现这一点,而不必硬编码方法名称或丢失其通用性(即使用
委托

注:

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

更新

我希望避免需要指定参数。整个想法是从指定的操作中推断它们。

您希望将表达式传递到
Invoke
以返回接受
target
Func
。代码:

public class Wrapper<TClient>
{
    TClient Client;

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

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

public class Wrapper<TClient>
{
    TClient Client;

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

您很快就可以运行代码了。有两种选择

首先,您可以尝试以下方法:

public class Wrapper<TClient>
{
    public TResult Invoke<TArg, TResult>(Func<TArg, TResult> action, TArg arg)
    {
        return action(arg);
    }
}
公共类包装器
{
公共TResult调用(函数操作,目标参数)
{
返回动作(arg);
}
}
那么就这样称呼它:

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

wrapper.Invoke((c, a) => c.Convert(a), 5);
var wrapper=new 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);
    }
}
公共类包装器
{
公共包装器(TClient客户端)
{
this.Client=Client;
}
私人客户;
公共TResult调用(函数操作,目标参数)
{
if(operation.Target!=客户端)
抛出新ArgumentException(nameof(operation));
返回操作(this.Client,arg);
}
}
这样称呼它:

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

wrapper.Invoke((c, a) => c.Convert(a), 5);
var client=new client();
var wrapper=新的包装器(客户端);
调用((c,a)=>c.Convert(a),5);

但是,从你对问题的描述来看,我看不出这两种方法有什么帮助,也看不到如何实现你的要求。也许您需要提供更多关于您正试图解决的底层需求的详细信息?

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

首先,您可以尝试以下方法:

public class Wrapper<TClient>
{
    public TResult Invoke<TArg, TResult>(Func<TArg, TResult> action, TArg arg)
    {
        return action(arg);
    }
}
公共类包装器
{
公共TResult调用(函数操作,目标参数)
{
返回动作(arg);
}
}
那么就这样称呼它:

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

wrapper.Invoke((c, a) => c.Convert(a), 5);
var wrapper=new 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);
    }
}
公共类包装器
{
公共包装器(TClient客户端)
{
this.Client=Client;
}
私人客户;
公共TResult调用(函数操作,目标参数)
{
if(operation.Target!=客户端)
抛出新ArgumentException(nameof(operation));
返回操作(this.Client,arg);
}
}
这样称呼它:

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

wrapper.Invoke((c, a) => c.Convert(a), 5);
var client=new client();
var wrapper=新的包装器(客户端);
调用((c,a)=>c.Convert(a),5);

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

我希望避免指定类型。客户机公开了无数个方法,每个方法都有不同数量的参数。我的目标是避免再次指定所有参数类型,并尽可能平滑地使用包装器。@Shimmy很遗憾,如果不显式指定类型,就无法将方法组隐式解析为
Func
,因为编译器对方法重载持谨慎态度。有什么解决方法吗?问题是,一旦您必须指定一个类型参数,您就必须指定所有类型参数,对吗?我不介意省略
TResult
这会使情况变得更好吗?@Shimmy这很有效,如果您不介意像这样传递包装lambda:
c=>arg=>c.Convert(arg)
。我想避免指定类型。客户机公开了无数个方法,每个方法都有不同数量的参数。我的目标是避免再次指定所有参数类型,并尽可能平滑地使用包装器。@Shimmy很遗憾,如果不显式指定类型,就无法将方法组隐式解析为
Func
,因为编译器对方法重载持谨慎态度。有什么解决方法吗?问题是,一旦您必须指定一个类型参数,您就必须指定所有类型参数,对吗?我不介意省略
TResult
它会使情况变得更好吗?@Shimmy这很有效,如果您不介意像这样传递包装lambda:
c=>arg=>c.Convert(arg)
。第一个代码片段的问题是,您正在实例化
客户机
,而不是使用存储在
包装器
中的客户机。我希望这两者能够混合使用,这样我就不必1)为用户提供对客户机的引用,2)这样我就不必命名所有参数(将有很多参数!)。我想我会选择你的第一个解决方案,因为命名参数比公开客户端更让我害怕。我已经更新了你的代码,按照我将要做的方式,客户端将被包含。第一个代码片段的问题是你正在实例化
客户端
,与其使用存储在
Wrapper
中的参数,不如将两者混合使用,这样我就不必1)为用户提供对客户端的引用,2)不必命名所有参数(将有很多参数!)。我想我会选择你的第一个解决方案,因为命名参数比暴露客户端更让我害怕。我已经更新了你的代码,按照我的方式,客户端无论如何都会被包含。