我有一个泛型类,它有一个方法'Call',它带有泛型返回类型和lambda表达式作为参数。这必须使用反射生成,并且由于类型未知,我需要创建lambda表达式。我有一个下面列出的工作解决方案,但我不喜欢必须从泛型类中获取实例,因为它是私有的并且在检索上做了一些逻辑。
班级:
public class Proxy<T>
{
public TR Call<TR>(Func<T, TR> serviceInvoke)
private T Instance
}
反思用法:
var serviceInstance = proxy.GetType().GetProperty("Instance", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(proxy, null);
var serviceMethod = type.GetMethod(rule.ServiceMethodName);
var parameters = serviceMethod.GetParameters().Select(parameterInfo => PropertyChainNavigator.GetValueForPropertyChain(((string)rule.Parameters[parameterInfo.Name]).Split(new[] { '.' }), context)).ToArray();
var thisParam = Expression.Constant(serviceInstance);
var valueParams = parameters.Select(Expression.Constant).ToList();
var call = Expression.Call(thisParam, serviceMethod, valueParams);
var func = Expression.Lambda(call, Expression.Parameter(type)).Compile();
var callMethod = proxy.GetType().GetMethods().Where(x => x.Name == "Call" && x.ReturnType != typeof(void)).First().MakeGenericMethod(serviceMethod.ReturnType);
result = callMethod.Invoke(proxy, new[] { func });
正常用法:
var proxy = new Proxy<ITestClass>();
proxy.Call(x => x.Method);
我试图将Expression.Call更改为不接受实例,但这仅适用于静态方法。有没有人知道我创建调用的方法,将其转换为lambda并使其编译而不会出错
答案 0 :(得分:3)
如果您使用lambda而不是表达式,那么您当前的代码将如下所示:
var serviceInstance = …; // retrieve using reflection
proxy.Call(i => serviceInstance.CallMethod(parameters));
请注意,lambda采用参数i
,但不使用它。我假设您想直接在i
上调用该方法,例如:
proxy.Call(i => i.CallMethod(parameters));
为此,请将Expression.Parameter()
的值用作thisParam
:
var thisParam = Expression.Parameter(type, "i"); // the name is optional
var call = Expression.Call(thisParam, serviceMethod, valueParams);
var func = Expression.Lambda(call, thisParam).Compile();
答案 1 :(得分:0)
public class Proxy<T>
{
public TR Call<TR>(Func<T, TR> serviceInvoke)
{
return serviceInvoke(Instance);
}
private T Instance;
}
这不是你需要的全部吗?为什么需要使用反射来获取T
实例?