我正在尝试通过反射调用泛型方法。我需要传递实现此方法期望参数的接口的类的对象。我收到System.ArgumentException告诉我“类型'ReflectionTest.MyRequest'的对象不能转换为类型'ReflectionTest.IRequest`1 [ReflectionTest.MyRequest]'”。
class Program
{
static void Main(string[] args)
{
var request = new MyRequest();
IMediator mediator = new Mediator();
//This works (of course), but I need to call this by reflection. I don't know the type at design time.
//var r = mediator.Send(request);
//I tried this, but it doesn't work
var type = request.GetType();
var method = mediator.GetType().GetMethod("Send");
var generic = method.MakeGenericMethod(type);
//Exception
var response = generic.Invoke(mediator, new object[] { request });
}
}
public interface IRequest<out TResponse>
{
}
public interface IMediator
{
TResponse Send<TResponse>(IRequest<TResponse> requests);
}
public class MyRequest : IRequest<MyResponse>
{
}
public class MyResponse
{
}
public class Mediator : IMediator
{
public TResponse Send<TResponse>(IRequest<TResponse> requests)
{
Console.WriteLine("Processing...");
return default(TResponse);
}
}
有人问我在做什么错吗?不幸的是,我不太会思考,所以欢迎您提供帮助。
示例git repo:https://github.com/alan994/ReflectionProblem
答案 0 :(得分:3)
在这一行:
var generic = method.MakeGenericMethod(type);
您正在创建type
类型的通用方法,即MyRequest
。
因此,最终您将MyRequest
用作TResponse
。
但是您实际上想要做的是将MyResponse
传递为TResponse
。
您可以执行以下操作以便能够动态调用它:
IMyRequest<>
TResponse
这是代码的外观,但是您需要在此处添加一些类型检查和有效的错误处理:
var type = request.GetType();
var responseType = type.GetInterfaces() // [IRequest<MyResponse>]
.Single(i => i.GetGenericTypeDefinition() == typeof(IRequest<>)) // IRequest<MyResponse>
.GetGenericArguments() // [MyResponse]
.Single(); // MyResponse
var method = mediator.GetType().GetMethod("Send");
var generic = method.MakeGenericMethod(responseType); // note that responseType is used here
var response = generic.Invoke(mediator, new object[] { request });
毕竟,您确定要将响应绑定到请求的特定定义吗?我不知道您的体系结构以及您要实现的目标,但是,也许这可以是一个更加敏捷的解决方案:
public interface IRequest
{
}
public interface IMediator
{
TResponse Send<TRequest, TResponse>(IRequest request);
}
public class MyRequest : IRequest
{
}
public class MyResponse
{
}
public class Mediator : IMediator
{
public TResponse Send<TRequest, TResponse>(IRequest request)
{
Console.WriteLine("Processing...");
return default(TResponse);
}
}
答案 1 :(得分:0)
您为Send
方法的通用类型发送了错误的类型。它的通用类型是响应类型-TResponse
,但您实际上将请求类型赋予了请求类型-IRequest<TResponse>
。
以下内容将为您提供正确的通用方法来调用。
var generic = method.MakeGenericMethod(typeof(MyReponse));
答案 2 :(得分:0)
问题在于您正在使用MyRequest
而不是MyResponse
来创建通用方法,请看一下签名Send<TResponse>
。试试:
var generic = method.MakeGenericMethod(typeof(MyReponse));