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)不必命名所有参数(将有很多参数!)。我想我会选择你的第一个解决方案,因为命名参数比暴露客户端更让我害怕。我已经更新了你的代码,按照我的方式,客户端无论如何都会被包含。