我正在预先配置的 NinjectMVC3.cs 中注册我的Ninject模块:
private static void RegisterServices(IKernel kernel)
{
var modules = new INinjectModule[]
{
new DomainBLModule(),
new ADOModule()
};
kernel.Load(modules);
}
我正在努力避免恶意服务定位器反模式的致命诅咒。
Domain Class使用DBContext,我试图通过IDBContext注入接口实现,具体情况如下:
IDomainBLFactory :
public interface IDomainBLFactory
{
DomainBL CreateNew();
}
DomainBLFactory :
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实现中,我将使用IDBContextFactory将依赖项注入特定的DBContext,在本例中是来自Entity Framework的ADO DBContext:
IDbDataContextFactory
public interface IDbDataContextFactory
{
myADOEntities CreateNew();
}
DbDataContextFactory
public class DbDataContextFactory : IDbDataContextFactory
{
public myADOEntities CreateNew()
{
return new myADOEntities ();
}
}
ADOModule
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 ***
...
}
使用构造函数Injection 。但我不知道在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
}
}
在这个Useful Post中,我们独特的真正朋友 Remo Gloor 在评论中为我描述了一个可能的解决方案,引用:“创建一个具有CreateSomething方法的接口创建实例所需的一切,让它返回实例。然后在配置中实现此接口并将IResolutionRoot添加到其构造函数中,并使用此实例获取所需对象。“
问题:如何使用Ninject.MVC3和我适度的Domain Class方法以正确的方式实现这一点?如何解决IResolutionRoot而不会因服务定位器反模式中继而受到惩罚?
为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()....
}
问题:我错过了什么?即使这种做法是错误的,财产也不会注入。
被诅咒。使用DependencyResolver并与耻辱一起生活。这有效,我将继续采用这种方法,直到找到适当的解决方案。这真是令人沮丧,因为我过去10天努力理解并做正确的事情缺乏知识。
public class DomainBL
{
private readonly IDbDataContextFactory contextFactory;
this.contextFactory = DependencyResolver.Current.GetService<IDbDataContextFactory>();
//So sweet, it works.. but i'm a sinner.
}
问题:我对注入接口实现的工厂方法的理解是否存在重大错误,而using a Domain Driven Approach用于拆分业务逻辑?如果我错了,我应该自信地实施哪些模式?
我之前看过很多文章和博客,并没有明确地提出这个重要问题。
Remo Gloor 在www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction中介绍了Ninject 3.0.0 RC的Ninject.Extensions.Factory。
问题:此扩展程序是否与Ninject.MVC3一起用于普通porpouse?在这种情况下,它应该是我对不久的将来的希望。
提前感谢您的指导,并记住我们感谢您的帮助。我想很多人会发现这种情况也很有用。
答案 0 :(得分:1)
我真的没有达到你工厂的目的。通常,您只有一个ObjectContext实例用于一个请求。这意味着您不需要工厂,只需在请求范围中绑定myADOEntities
并将其注入DomainBL
而无需添加工厂:
Bind<myADOEntities>().ToSelf().InRequestScope();
Bind<DomainBL>().ToSelf().InRequestScope();
是的,工厂和mvc extrensions一起工作。
答案 1 :(得分: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)
}