简体   繁体   中英

Ninject generic binding resolve throws ActivationException

I have a generic type for query handlers.

public interface IQueryHandler<in TQuery, out TResult>
    where TQuery : IQuery<TResult>
{
    TResult Execute(TQuery query);
}

And I have so many implementation for this interface. So I created a service to resolve these types:

    public class QueryService : IQueryService
    {
        private readonly IResolver resolver;

        public QueryService(IResolver resolver)
        {
            this.resolver = resolver;
        }

        public TResult ExecuteQuery<TResult>(IQuery<TResult> query)
        {
            var queryHandlerType = typeof IQueryHandler<,>).MakeGenericType(query.GetType(),  typeof (TResult));
            var queryHandlerImpl = resolver.Resolve(queryHandlerType);

            return (TResult) ((dynamic) queryHandlerImpl).Execute((dynamic) query);
        }
    }

My resolver type is using ninject.

public class Resolver : IResolver
{
    private readonly IKernel container;

    public Resolver(IKernel container)
    {
        this.container = container;
    }

    public object Resolve(Type T)
    {
        return container.Get(T);
    }
}

And I bind Query service and Resolver type on application start.

 container.Bind<IResolver>().To<Resolver>();         
 container.Bind<IQueryService>().To<QueryService>();

When application started an exception is throwing at this method of Resolver :

public object Resolve(Type T)
{
    return container.Get(T);
}

            An exception of type 'Ninject.ActivationException' 
    occurred in Ninject.dll but was not handled in user code

            Additional information: Error activating IQueryHandler{PlaceByIdQuery, PlaceByIdQueryResult}       No matching bindings are available,  and the type is not self-bindable.

        Activation path:
1) Ensure that you have defined a binding for IQueryHandler{PlaceByIdQuery, PlaceByIdQueryResult}.

  2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.

  3) Ensure you have not accidentally created more than one kernel.

  4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.

  5) If you are using automatic module loading, ensure the search path and filters are correct.

I checked 5 steps but not find anything. Should I bind something else?

Ninject should know your concreate types to bind interfaces. I think you have multiple implementation of IQueryHandler<,> interface so you can not bind manually them to interface.

But Ninject.Extensions.Conventions is doing this automatically. (you can download from nuget)

        kernel.Bind(x => x.FromThisAssembly()
                          .IncludingNonePublicTypes()
                          .SelectAllClasses()
                          .InheritedFrom(typeof(IQueryHandler<,>))
                          .BindSingleInterface());

Be careful applying correct assembly(FromThisAssembly or else).

Now your Resolve method knows cancreate instances.

Ninject cannot resolve IQueryHandler<,> interface. You need to define binding for it.

Something like:

container.Bind(typeof(IQueryHandler<,>)).To(typeof(QueryHandler<,>));

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM