2

预赛

  1. 我正在使用 Ninject.MVC3 2.2.2.0 Nuget 包将 IDomain 接口的实现注入到我的控制器中,该接口使用工厂方法分离我的业务逻辑 (BL)。
  2. 我正在使用以下方法在预配置的NinjectMVC3.cs中注册我的 Ninject 模块:

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

域类使用我试图通过 IDBContext 注入接口实现的 DBContext,具有以下场景:

IDomainBLFactory

public interface IDomainBLFactory
{
    DomainBL CreateNew();
}

域BLFactory

public class DomainBLFactory : IDomainBLFactory
{
    public DomainBL CreateNew()
    {            
        return new DomainBL();
    }
}

在控制器的命名空间中:

public class DomainBLModule : NinjectModule
{
    public override void Load()
    {
        Bind<IDomainBLFactory>().To<DomainBLFactory>().InRequestScope();
    }
}

此时我可以使用 Ninject Constructor Injection 将 IDomainBLFactory 实现注入到我的控制器中,没有任何问题:

public class MyController : Controller
{
    private readonly IDomainBLFactory DomainBLFactory;
    // Default Injected Constructor
    public MyController(IDomainBLFactory DomainBLFactory)
    {
        this.DomainBLFactory = DomainBLFactory;
    }
    ... (use the Domain for performing tasks/commands with the Database Context)
}

现在我的中心问题。

在 DomainBL 实现中,我将依赖注入到特定的 DBContext,在本例中,来自 Entity Framework 的 ADO DBContext,再次使用 IDBContextFactory:

IDbDataContextFactory

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

现在在 DomainBL 实现中,我遇到了为 DBContext 对象工厂注入必要接口的问题:

public class DomainBL
{
  private readonly IDbDataContextFactory contextFactory;
  **** OPS, i tried to understand about 10+ Stackoverflow articles ***
  ...
}

我尝试了什么?

  1. 使用构造函数注入。但我不知道在 IDBContextFactory 中的 Factory 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 到它的构造函数,并使用这个实例来获取所需的对象。”

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

  2. 对 IDBContexFactory 使用属性注入。在学习和阅读所有相互矛盾的观点以及有关它的理论解释的过程中,我可以推断这不是为我的 DBContexFactory 类代码进行注入的正确方法。没关系。无论如何它都不起作用。

    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()....
    
    }
    

    问题:我错过了什么?即使这种方法是错误的,属性也不会注入。

  3. 被诅咒。使用 DependencyResolver 并忍受耻辱。这行得通,我将继续采用这种方法,直到为我找到合适的解决方案。这真的很令人沮丧,因为在我过去 10 天的努力中缺乏知识,试图理解和做正确的事情。

    public class DomainBL
    {
      private readonly IDbDataContextFactory contextFactory;
      this.contextFactory = DependencyResolver.Current.GetService<IDbDataContextFactory>();
      //So sweet, it works.. but i'm a sinner.
    
    }
    

    问题:我对注入接口实现的工厂方法和使用领域驱动方法分解业务逻辑的理解是否存在很大错误?如果我错了,我应该自信地实现哪​​些模式堆栈?

    我之前看到大量的文章和博客并没有以开放清晰的方式提出这个重要问题。


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

问题:此扩展是否可以与 Ninject.MVC3 一起用于一般海豚?在这种情况下,这应该是我对不久的将来的希望。

提前感谢大家的指导,并记住我们感谢您的帮助。我想很多人会发现这个场景也很有用。

4

2 回答 2

1

我真的不明白你们工厂的目的。通常,一个请求只有一个 ObjectContext 实例。这意味着您不需要工厂,只需myADOEntities在请求范围内绑定并将其注入您DomainBL的工厂,而无需添加工厂:

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

是的,工厂和 mvc 扩展一起工作。

于 2012-02-22T16:28:00.760 回答
1

这是一个通用 IFactory 的实现,用于解决问题,而无需求助于 ServiceLocator 反模式。

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

  public interface IFactory<T>
  {
    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>();
    }
  }

使用以下内容绑定到您的工厂

  private static void RegisterServices(IKernel kernel)
  {
    kernel.Bind<myADOEntities>().ToSelf();
    kernel.Bind<DomainBL>().ToSelf();
    kernel.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)
  }

在你的 DomainBL

  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)
  }
于 2012-05-16T15:26:54.723 回答