我在Ninject wiki上阅读了一堆问题和所有文档,但我仍然怀疑并向自己提出问题,例如"我做得对吗?"
A)所以我需要这样的东西:
public class MyClass : IMyInterface
{
private string _field;
readonly IRepository _repo;
public MyClass(string field, IRepository repo)
{
_field = field;
_repo = repo;
}
}
但如何正确捆绑?或者我应该永远忘记使用构造函数,但构造函数依赖注入?
B)并且这样做:
public class MyClass : IMyInterface
{
private string _field;
readonly IRepository _repo;
public MyClass(IRepository repo)
{
_repo = repo;
}
public void Initialize(string field)
{
_field = field;
}
}
我认为当我需要对象初始化函数或者我错了时,随时打电话都不行吗?
根据此答案Can't combine Factory / DI和Dependency Inject (DI) "friendly" library以及Is there a pattern for initializing objects created via a DI container
如果您需要短期对象,请使用Abstract Factory
使用构造函数注入注入的依赖项往往是长期存在的,但有时您需要一个短期对象,或基于仅在运行时知道的值构建依赖项。
C)我应该这样做:
public interface IMyInterface { }
public interface IMyFactory
{
MyClass Create(string field);
}
public class MyFactory : IMyFactory
{
private readonly IRepository _repo;
public MyFactory (IRepository repo)
{
_repo = repo;
}
public MyClass Create(string field)
{
return new MyClass(_repo, field);
}
}
public class MyClass : IMyInterface
{
private string _field;
readonly IRepository _repo;
public MyClass(IRepository repo, string field)
{
_repo = repo;
_field = field;
}
}
如果我需要来自其他课程的MyClass,我会像
一样使用它public class OtherClass
{
private IMyInterface _myClass;
public OtherClass(IMyFactory factory)
{
_myClass = factory.Create("Something");
}
}
不是太笨重了吗?
我的问题是:我必须使用A,B或C案例?为什么?或者别的什么?
答案 0 :(得分:2)
如果我需要使用控制器初始化对象怎么办?而字段参数只能在运行时知道吗?
正如here所解释的那样,您的应用程序组件在初始化期间不应要求运行时数据。相反,你应该:
与流行的看法相反,抽象工厂几乎不是解决这个问题的正确方法,因为:
而不是降低消费者的复杂性,工厂实际上增加了复杂性,因为消费者现在需要依赖于IService和Abstract Factory IServiceFactory,而不仅仅依赖于服务抽象IService。 [...]单元测试此类时,可以立即感受到复杂性的增加。这不仅迫使我们测试消费者与服务的互动,我们也必须测试与工厂的互动。
有关详细讨论,请阅读this article。
答案 1 :(得分:1)
答案是,一如既往,取决于它。没有上下文,就很难建议。
然而,有一件事我会犹豫不决 - 配置注入"纯"字符串到组件。字符串可能意味着成千上万的事情,以后可能很难支持该设计。当然,您可以定义注入XController的字符串将是SQL的连接字符串,当注入YController时将是一个授权令牌,但我怀疑它是否可读且易于维护。
据说我会选择 C 选项或以下方法:
public class DescriptiveMeaningOfAClass
{
public string Value { get; set; }
}
public class MyClass : IMyInterface
{
private string _field;
readonly IRepository _repo;
public MyClass(DescriptiveMeaningOfAClass something, IRepository repo)
{
_field = something.Value;
_repo = repo;
}
}
答案 2 :(得分:0)
Personnaly我会通过使用ChildKernel而不是直接引用构造函数来混合A)和C)。 https://github.com/ninject/Ninject.Extensions.ChildKernel
在你的工厂:
var parentKernel = new StandardKernel();
var childKernel1 = new ChildKernel(parentKernel);
childKernel1.Bind<string>().ToConstant("MyRuntimeValue");
var myClass = childKernel1.Get<MyClass>();
我没有测试它,但它应该可以工作。