Dependency injection 如何将IDBContextFactory正确注入控制器';使用Ninject MVC3的主要工厂? 预备赛 我正在使用Ninject.mvc32.2.2.0 Nuget包向控制器中注入IDomain接口的实现,该接口使用工厂方法分离我的业务逻辑(BL)

Dependency injection 如何将IDBContextFactory正确注入控制器';使用Ninject MVC3的主要工厂? 预备赛 我正在使用Ninject.mvc32.2.2.0 Nuget包向控制器中注入IDomain接口的实现,该接口使用工厂方法分离我的业务逻辑(BL),dependency-injection,ninject,ninject-2,ninject.web.mvc,ninject-extensions,Dependency Injection,Ninject,Ninject 2,Ninject.web.mvc,Ninject Extensions,我正在预配置的NinjectMVC3.cs中注册我的Ninject模块,使用: private static void RegisterServices(IKernel kernel) { var modules = new INinjectModule[] { new DomainBLModule(), new ADOModule() }; kernel.Load(modules); } 我试图避免恶魔服务定位器反模式的致命诅

我正在预配置的NinjectMVC3.cs中注册我的Ninject模块,使用:

private static void RegisterServices(IKernel kernel)
{
    var modules = new INinjectModule[]
    {
        new DomainBLModule(),
        new ADOModule()
    };
    kernel.Load(modules);
}
  • 我试图避免恶魔服务定位器反模式的致命诅咒

  • Domain类使用DBContext,我正试图通过IDBContext注入接口实现,场景如下:

    IDOMAINLFactory

    public interface IDomainBLFactory
    {
        DomainBL CreateNew();
    }
    
    public class DomainBLFactory : IDomainBLFactory
    {
        public DomainBL CreateNew()
        {            
            return new DomainBL();
        }
    }
    
    域名工厂

    public interface IDomainBLFactory
    {
        DomainBL CreateNew();
    }
    
    public class DomainBLFactory : IDomainBLFactory
    {
        public DomainBL CreateNew()
        {            
            return new DomainBL();
        }
    }
    
    在控制器的命名空间中:

    public class DomainBLModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IDomainBLFactory>().To<DomainBLFactory>().InRequestScope();
        }
    }
    
    现在是我的核心问题。 在DomainBL实现中,我将再次使用IDBContextFactory将依赖项注入特定的DBContext,在本例中,是实体框架中的ADO DBContext:

    IDbDataContextFactory

    public interface IDbDataContextFactory
    {
        myADOEntities CreateNew();
    }
    
    public class DbDataContextFactory : IDbDataContextFactory
    {
        public myADOEntities CreateNew()        
        {
            return new myADOEntities ();
        }
    }
    
    DbDataContextFactory

    public interface IDbDataContextFactory
    {
        myADOEntities CreateNew();
    }
    
    public class DbDataContextFactory : IDbDataContextFactory
    {
        public myADOEntities CreateNew()        
        {
            return new myADOEntities ();
        }
    }
    
    ADO模块

    public class ADOModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IDbDataContextFactory>().To<DbDataContextFactory>().InRequestScope();
        }
    }
    
    我试过什么?
  • 使用构造函数注入。但是我不知道在IDBContextFactory中对工厂CreateNew()的调用中注入什么。为了明确:

    public class DomainBLFactory: IDomainBLFactory        
    {
        // Here the constructor requires one argument for passing the factory impl.
        public DomainBL CreateNew()
        {
            return new DomainBL(?????)  // I need a IDBContextFactory impl to resolve.
            //It's not like in the MVC Controller where injection takes place internally
            //for the controller constructor. I'm outside a controller
        }
    }
    
    在此,我们唯一的真正朋友Remo Gloor在评论中为我描述了一个可能的解决方案,引用:“创建一个具有CreateSomething方法的接口,该方法接受创建实例所需的一切,并让它返回实例。然后在配置中实现此接口,并将IResolutionRoot添加到其构造函数中,并使用此Instance获取所需的对象。”

    问题:我如何使用Ninject.MVC3和我的适度域类方法以正确的方式实现这一点?我如何解析IResolutionRoot而不因在服务定位器反模式中中继而受到惩罚

  • 为IDBContextFactory使用属性注入。在学习和阅读所有相互矛盾的观点以及关于它的理论解释的过程中,我可以推断这不是为我的DBContextFactory类代码进行注入的正确方法。不管怎样,它都不起作用

    public class DomainBL
    {
    
      [Inject]
      public IDbDataContextFactory contextFactory
      {
          get;
          set;
      }
      //Doesn't works, contextFactory is null with or without parameterless constructor
      .... (methods that uses contextFactory.CreateNew()....
    
    }
    
    问题:我遗漏了什么?即使这种方法是错误的,财产也没有注入

  • 被诅咒。使用DependencyResolver和Stumata一起生活。这很有效,我会一直使用这种方法,直到找到适合我的解决方案。这真的很令人沮丧,因为我在过去10天的努力中缺乏知识,试图理解和正确地做事

    public class DomainBL
    {
      private readonly IDbDataContextFactory contextFactory;
      this.contextFactory = DependencyResolver.Current.GetService<IDbDataContextFactory>();
      //So sweet, it works.. but i'm a sinner.
    
    }
    
    公共类域bl
    {
    私有只读IDbDataContextFactory contextFactory;
    this.contextFactory=DependencyResolver.Current.GetService();
    //太好了,它起作用了……但我是个罪人。
    }
    
    问题:我对注入接口实现和分解业务逻辑的工厂方法的理解是否存在重大错误?如果我错了,我应该自信地实现哪些模式堆栈

    我以前看到过大量的文章和博客,它们没有以一种开放的方式明确地提出这个重要的问题


  • Remo Gloor在www.planetgeek.ch/2011/12/31/Ninject-Extensions-Factory-introduction中介绍了Ninject 3.0.0 RC的Ninject.Extensions.Factory

    问题:此扩展与通用porpouse的Ninject.MVC3结合使用是否可行?在这种情况下,我希望在不久的将来实现这一点


    提前感谢您的指导,请记住,我们感谢您的善意帮助。我想很多人会发现此场景也很有用。

    我并不真正了解您工厂的用途。通常,一个请求只有一个ObjectContext实例。这意味着您不需要工厂,只需绑定
    Myadonti即可在请求范围中绑定
    ,并将其注入您的
    域BL
    ,而无需添加工厂:

    Bind<myADOEntities>().ToSelf().InRequestScope();
    Bind<DomainBL>().ToSelf().InRequestScope();
    
    Bind().ToSelf().InRequestScope();
    Bind().ToSelf().InRequestScope();
    

    是的,factory和mvc Extrension可以协同工作。

    这里是一个通用IFactory的实现,它可以在不使用ServiceLocator反模式的情况下解决问题

    首先定义一个好的通用工厂接口

      public interface IFactory<T>
      {
        T CreateNew();
      }
    
    公共接口IFactory
    {
    T CreateNew();
    }
    
    并定义使用ninject内核创建请求对象的实现

      class NinjectFactory<T> : IFactory<T>
      {
        private IKernel Kernel;
    
        public NinjectFactory( IKernel Kernel )
        {
          this.Kernel = Kernel;
        }
    
        public T CreateNew()
        {
          return Kernel.Get<T>();
        }
      }
    
    工厂类别:IFactory
    {
    私有IKernel内核;
    公共工厂(IKernel内核)
    {
    this.Kernel=Kernel;
    }
    公共T CreateNew()
    {
    返回Kernel.Get();
    }
    }
    
    使用以下命令绑定到您的工厂

      private static void RegisterServices(IKernel kernel)
      {
        kernel.Bind<myADOEntities>().ToSelf();
        kernel.Bind<DomainBL>().ToSelf();
        kernel.Bind(typeof(IFactory<>)).To(typeof(NinjectFactory<>));
      }        
    
    私有静态无效注册服务(IKernel内核)
    {
    kernel.Bind().ToSelf();
    kernel.Bind().ToSelf();
    Bind(typeof(IFactory)).To(typeof(NinjectFactory));
    }        
    
    现在,您可以在控制器中执行以下操作

      public class MyController : Controller
      {
        private readonly IFactory<DomainBL> DomainBLFactory;
    
        public MyController( IFactory<DomainBL> DomainBLFactory )
        {
          this.DomainBLFactory = DomainBLFactory;
        }
    
        // ... (use the Domain for performing tasks/commands with the Database Context)
      }
    
    公共类MyController:Controller
    {
    私有只读IFactory DomainBLFactory;
    公共MyController(IFactory域工厂)
    {
    this.DomainBLFactory=DomainBLFactory;
    }
    //…(使用域与数据库上下文执行任务/命令)
    }
    
    在你的领域

      public class DomainBL
      {
        IFactory<myADOEntities> EntitiesFactory;
    
        public DomainBL( IFactory<myADOEntities> EntitiesFactory )
        {
          this.EntitiesFactory = EntitiesFactory;
        }
    
        // ... (use the Entities factory whenever you need to create a Domain Context)
      }
    
    公共类域bl
    {
    工厂实体工厂;
    公共领域BL(工厂实体工厂)
    {
    this.EntitiesFactory=EntitiesFactory;
    }
    //…(在需要创建域上下文时使用实体工厂)
    }
    
    非常感谢您的快速响应Remo。好的,我得到了想法。现在,我将按照您所说的绑定到我的impl以避免工厂。剩下的问题是如何在clas中注入MyADO实体