And*_*dre 8 c# dependency-injection inversion-of-control property-injection constructor-injection
我正在寻找有关为IoC设计对象的最佳方法的建议
假设我有一个对象(Service)依赖于向Ioc注册的DataContext.
但它还需要一个名称属性,我可以像这样设计对象:
class Service
{
public Service(IDataContext dataContext,
string name)
{
this._dataContext = dataContext;
this._name = name
}
public string Name
{
get
{
return _name;
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题是使用Ioc容器变得非常复杂,因为字符串对象如名称不容易注册,并且Ioc容器的使用变得复杂:因此解决方案变得混乱:
var service = Ioc.Resolve<Service>( ?? )
Run Code Online (Sandbox Code Playgroud)
另一种方法是将其设计如下:
class Service
{
public Service(IDataContext dataContext)
{
this._dataContext = dataContext;
}
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
分辨率现在更容易:
var service = Ioc.Resolve<Service>();
service.Name = "Some name";
Run Code Online (Sandbox Code Playgroud)
唯一的缺点是不再需要指定名称.我想听听DI或IoC专家如何设计这个并且仍然对混凝土Ioc容器技术保持相当不可知.
我知道很多取决于你想如何使用它,如果name真的是可选的,选项2将是完美的.但是在需要名称的情况下,你可以在代码的另一个点添加验证步骤,而是去设计使Ioc更简单.
思考?
您对 DI 容器的选择不应决定 API 的设计。如果name不是可选的,它应该是构造函数签名的一部分(从而使其成为强制性的)。
下一个问题是如何在不产生大量开销的情况下配置容器。如何做到这一点取决于容器。以下是如何在温莎城堡中围绕字符串参数实现约定:
public class NameConvention : ISubDependencyResolver
{
public bool CanResolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model, DependencyModel dependency)
{
return dependency.TargetType == typeof(string)
&& dependency.DependencyKey == "name";
}
public object Resolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model, DependencyModel dependency)
{
return "foo"; // use whatever value you'd like,
// or derive it from the provided models
}
}
Run Code Online (Sandbox Code Playgroud)
NameConvention然后像这样向容器注册:
container.Kernel.Resolver.AddSubResolver(new NameConvention());
Run Code Online (Sandbox Code Playgroud)
如果您的容器没有适当的扩展点,请选择具有适当扩展点的容器。