【问题标题】:Calling a method on a dynamic object implementing a generic interface在实现通用接口的动态对象上调用方法
【发布时间】:2014-11-09 16:54:05
【问题描述】:

我有一个从服务总线传入的查询对象,从 JSON 反序列化 - 看起来它正在工作...

public TResult Execute<TResult>(IQuery<TResult> query) where TResult : class {
....
var types = Assembly.GetExecutingAssembly().GetTypes();            
var queryType = types.FirstOrDefault(z => z.Name.Equals(message.MessageType));
var queryObj = JsonConvert.DeserializeObject(message.Json, queryType, settings);

然后我想将它与已为其类型注册的处理程序相匹配(找到实现 TResult IQueryHandler 的方法) - 很好。 TResult 的唯一限制是它是一个类。

var handlerType = typeof(IQueryHandler<,>);
var genericType = handlerType.MakeGenericType(new[] { queryType, typeof(TResult) });
var handler = (dynamic)Startup.SimpleInjector.Instance.GetInstance(genericType);

然后我想用我重建的查询对象在这个处理程序上调用 Handle 方法,但这就是我得到的地方:

result = handler.Handle(queryObj);
Log.Instance.Info("result {0}", result);

An exception occurred, MassTransit.Exceptions.RequestException: The response handler threw an exception ---> Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'HomeApi.Handlers.Workflow.AnyWorkflowsStartWithEventQueryHandler.Handle(HomeApi.Queries.AnyWorkflowsStartWithEventQuery)' has some invalid arguments

我已经验证了处理程序是从 SimpleInjector 返回的(尽管将其转换为动态会导致问题在这里?)并且处理程序接受查询并返回预期的 TResult 所以不确定我为什么会得到这个结果。任何帮助表示赞赏。

这是IQueryHandler的定义

public interface IQueryHandler<T, out TR> where T : class where TR : class
{
    TR Handle(T query);
}

和 IQuery:

public interface IQuery<T> where T : class
{
    string Type { get; }
}

【问题讨论】:

    标签: c# dynamic reflection


    【解决方案1】:

    假设JsonConvert.DeserializeObject(message.Json, queryType, settings); 返回object,你会想用真实类型实际调用Handle 函数,例如:

    result = handler.Handle((dynamic)queryObj);
    

    现在,您正在呼叫handler.Handle&lt;MyRealType&gt;(object)

    【讨论】:

    • 嗨,克里斯,对DeserializeObject 的调用导致实现IQuery (AnyWorkflowsStartWithEventQuery) 处理程序的具体查询类型从通用处理程序的SimpleInjector 容器返回到具体(AnyWorkFlowsStartWithEventQueryHandler which is IQueryHandler&lt;AnyWorkflowsStartWithEventQuery, List&lt;IWorkflow&gt;&gt; 我认为TResult handler.Handle&lt;IQuery, TResult&gt; 是我的'm after 但它似乎不喜欢我试图用它来调用 Handle 的东西。如果有帮助,我可以发布该方法
    • 是的,我尝试添加动态转换来查询 obj,但不幸的是导致了同样的异常:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: The best overloaded method match for 'HomeApi.Handlers.Workflow.AnyWorkflowsStartWithEventQueryHandler.Handle(HomeApi.Queries.AnyWorkflowsStartWithEventQuery)' has some invalid arguments at CallSite.Target(Closure , CallSite , Object , Object )
    • 我在这里创建了一个方法的要点gist.github.com/danbyrne84/66698b6c438923708d2a
    • @managedheap84,很难看出出了什么问题。我建议你一步一步做事。你能确定Startup.SimpleInjector.Instance.GetInstance 返回它应该返回的内容吗?暂时用你认为正确的代替它。转储每个类型/对象及其方法。没有必要解决这个错误,你试图调用的签名不匹配:-)
    猜你喜欢
    • 2013-08-16
    • 2017-08-21
    • 2020-09-29
    • 2019-12-21
    • 2016-02-01
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多