【问题标题】:Ninject doesn't make implementation of interfaceNinject 不实现接口
【发布时间】:2015-06-28 14:51:39
【问题描述】:

我无法让 Ninject 在我的 ASP.NET MVC 5 项目中工作。
它不想让具体对象连接到接口,我不知道有什么办法可以解决这个问题。

我的项目在Domain.Abstract 中有一个接口IQuizRepository,其中仅包含ICollection<Quiz> Quizes { get; }
实现是Domain.Concrete 中的QuizRepository,如下所示:

public class QuizRepository : IQuizRepository
{
    public ICollection<Quiz> Quizes { get; private set; }

    public QuizRepository()
    {
        List<Quiz> quizes = new List<Quiz>();
        // adding some Quiz objects to the list
        Quizes = quizes;
    }
}

控制器是Website.Controllers.HomeController.cs,它只是测试 Ninject 是否工作,看起来像这样:

public ActionResult Index(IQuizRepository quiz)
{
    ViewBag.test = quiz.Quizes.First().Id;
    return View();
}

Website.App_Start 中的NinjectWebCommon 等于默认生成的RegisterServices 方法除外:

public static class NinjectWebCommon 
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        public static void Start() 
        {
            DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
            DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
            bootstrapper.Initialize(CreateKernel);
        }

        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            try
            {
                kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<Domain.Abstract.IQuizRepository>().To<Domain.Concrete.QuizRepository>();
        }        
    }

仍然无法实现IQuizRepository
我想我已经安装了所有需要的 NuGet 包:

Ninject v3.2.0.0
Ninject.MVC5 v3.2.1.0
Ninject.Web.Common v3.2.0.0
Ninject.Web.Common.WebHost v3.2.0.0

堆栈跟踪(遗憾的是部分使用荷兰语,因为我无法以英语显示错误消息):

[MissingMethodException: Kan geen exemplaar van een interface maken.]
   System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
   System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +113
   System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) +232
   System.Activator.CreateInstance(Type type, Boolean nonPublic) +83
   System.Activator.CreateInstance(Type type) +66
   System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +197

[MissingMethodException: Kan geen exemplaar van een interface maken. Object type 'Domain.Abstract.IQuizRepository'.]
   System.Web.Mvc.DefaultModelBinder.CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) +233
   System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +532
   System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +330
   System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +331
   System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +105
   System.Web.Mvc.Async.<>c__DisplayClass21.<BeginInvokeAction>b__19(AsyncCallback asyncCallback, Object asyncState) +743
   System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +14
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
   System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +343
   System.Web.Mvc.Controller.<BeginExecuteCore>b__1c(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +25
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
   System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +465
   System.Web.Mvc.Controller.<BeginExecute>b__14(AsyncCallback asyncCallback, Object callbackState, Controller controller) +18
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +20
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
   System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +374
   System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +16
   System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__4(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +52
   System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
   System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +384
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

【问题讨论】:

    标签: c# asp.net ninject


    【解决方案1】:

    在您的 NinjectWebCommon 文件中,您需要将最后一个方法(Private RegisterServices)更改为如下内容:

        private static void RegisterServices(IKernel kernel)
        {
            DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
        }
    

    然后你需要像这样添加一个 NinjectDependencyResolver.cs 文件:

        public class NinjectDependencyResolver: IDependencyResolver {
            private readonly IKernel _kernel;
    
            public NinjectDependencyResolver(IKernel kernel) {
                _kernel = kernel;
                AddBindings();
            }
            public object GetService(Type serviceType) {
                return _kernel.TryGet(serviceType);
            }
    
            public IEnumerable<object> GetServices(Type serviceType) {
                return _kernel.GetAll(serviceType);
            }
    
            private void AddBindings() {
                // PULL YOUR BINDINGS HERE
                _kernel.Bind<Domain.Abstract.IQuizRepository>().To<Domain.Concrete.QuizRepository>();
            }
        }
    

    【讨论】:

    • 另外,只是因为我遇到过几次。确保删除 bin 文件夹。如果您重命名了任何库,它们可能仍存在于 Bin 文件夹中,Ninject 将尝试检查它们并炸毁它们。
    • 感谢您的回答,但我得到的答案完全相同。已删除 bin 文件夹,尝试在 Visual Studio 中清理解决方案并将绑定移动到 Website.Infrastructure.NinjectDependencyResolver.cs 堆栈跟踪和错误保持完全相同。我已将完整文件上传到 pastebin:NinjectDependencyResolver & NinjectWebCommon
    • 在你的 Website.Controllers.HomeController.cs 你有这个:public class HomeController: Controler{ private IQuizRepository _quizRepo; public HomeController(IQuizRepository repo){ _quizRepo = repo; } }
    • 好的,谢谢!那成功了。问题是我要求在Index() 方法中实现。将其移至构造函数并将 repo 设为实例变量即可!
    • 您可以在方法级别进行实现。以下是模式:link