Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.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# 通过反射调用泛型方法。发生System.ArgumentException异常_C#_.net_Generics_Reflection - Fatal编程技术网

C# 通过反射调用泛型方法。发生System.ArgumentException异常

C# 通过反射调用泛型方法。发生System.ArgumentException异常,c#,.net,generics,reflection,C#,.net,Generics,Reflection,我试图通过反射调用泛型方法。我需要传递实现此方法期望参数的接口的类的对象。我收到System.ArgumentException通知我“ReflectionTest.MyRequest类型的对象”无法转换为“ReflectionTest.IRequest`1[ReflectionTest.MyRequest]”类型 class Program { static void Main(string[] args) { var request = new MyReque

我试图通过反射调用泛型方法。我需要传递实现此方法期望参数的接口的类的对象。我收到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);
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var request=new MyRequest();
IMediator mediator=新的mediator();
//这是可行的(当然),但我需要通过反射来调用它。我在设计时不知道它的类型。
//var r=mediator.Send(请求);
//我试过了,但没用
var type=request.GetType();
var method=mediator.GetType().GetMethod(“发送”);
var generic=method.MakeGenericMethod(类型);
//例外情况
var response=generic.Invoke(中介,新对象[]{request});
}
}
公共接口IRequest
{
}
公共接口IMediator
{
t响应发送(IRequest请求);
}
公共类MyRequest:IRequest
{
}
公共类MyResponse
{
}
公共类中介:IMediator
{
公共响应发送(IRequest请求)
{
Console.WriteLine(“处理…”);
返回默认值(t响应);
}
}
有人对我做错了什么有什么建议吗?不幸的是,我不太擅长思考,所以欢迎任何帮助


git回购示例:

您为
Send
方法的泛型类型发送了错误的类型。它的泛型类型是响应类型-
treresponse
,但您给它的是请求类型-实际上是
IRequest

下面将为您提供要调用的正确泛型方法

var generic = method.MakeGenericMethod(typeof(MyReponse));
在这方面:

var generic = method.MakeGenericMethod(type);
您正在创建类型为
type
的通用方法,即
MyRequest

因此,最终您将使用
MyRequest
作为
treresponse

但实际上您想要做的是将
MyResponse
作为
treresponse
传递

您可以执行以下操作,以便能够动态调用它:

  • 获取接口
    IMyRequest
    ,它是您的请求正在实现的
  • 获取此接口的唯一泛型参数,它将是
    treponse
代码可能是这样的,但您需要在此处添加一些类型检查和有效错误处理:

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 });
var type=request.GetType();
var responseType=type.GetInterfaces()/[IRequest]
.Single(i=>i.GetGenericTypeDefinition()==typeof(IRequest))//IRequest
.GetGenericArguments()/[MyResponse]
.Single();//我的反应
var method=mediator.GetType().GetMethod(“发送”);
var generic=method.MakeGenericMethod(responseType);//注意这里使用的是responseType
var response=generic.Invoke(中介,新对象[]{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);
    }
}  
公共接口IRequest
{
}
公共接口IMediator
{
t响应发送(IRequest请求);
}
公共类MyRequest:IRequest
{
}
公共类MyResponse
{
}
公共类中介:IMediator
{
公共响应发送(IRequest请求)
{
Console.WriteLine(“处理…”);
返回默认值(t响应);
}
}  

问题在于,您正在使用
MyRequest
而不是
MyResponse
创建一个通用方法,请查看签名
Send
。尝试:

var generic = method.MakeGenericMethod(typeof(MyReponse));

感谢您的详细解释和代码示例。我现在明白了,我能说什么……我是白痴:)这只是一个较大代码库的小例子。接口IMediator是外部nuget包的一部分。谢谢你的回答!