managedheap84
managedheap84

Reputation: 851

Calling a method on a dynamic object implementing a generic interface

I've got a query object that's coming in off a service bus, deserialized from JSON - looks like it's working...

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);

I then want to match it to the handler that's been registered for it's type (find the method that implements TResult IQueryHandler) - fine. The only constraint on TResult is that it's a class.

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

I then want to call the Handle method on this handler with the query object i've rebuilt, but that's where I'm getting:

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

I've verified that the handler is being returned from SimpleInjector (although would casting it to a dynamic cause a problem here?) and that the handler takes the query and returns the expected TResult so not sure why I'm getting this result. Any help appreciated.

here's the definition of IQueryHandler<,>

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

and IQuery:

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

Upvotes: 2

Views: 391

Answers (1)

Erti-Chris Eelmaa
Erti-Chris Eelmaa

Reputation: 26338

Assuming JsonConvert.DeserializeObject(message.Json, queryType, settings); returns object, you'd want to actually call the Handle fuction with the real type, such as this:

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

Right now, you're calling handler.Handle<MyRealType>(object).

Upvotes: 1

Related Questions