我最近第一次开始使用IoC容器,但我没有接受过使用它的最佳实践的教育。更具体地说,我在C#.NET项目中使用Unity,我开始使用它,因为它带有Prism。
我使用容器来解析“顶级”对象,并根据容器获取正确的对象。但是,当我有一个带有孩子和孩子的孩子的物体时,我无法清楚地看到最佳实践,我需要一些来自IoC容器的数据,而不是介于两者之间。您通常如何组织使用IoC容器?
最初我认为你会在需要的地方传递容器,而不是从顶层的容器中提取所需的数据并传递这些数据。但是当我到达除了注入接口之外的其他特定数据的对象时,我再次遇到问题,并且我不希望在解析对象之后通过属性或init方法注入这些数据。
我希望这很清楚,但让我们来看一个虚构的(有点愚蠢的......)例子。
class Employee
{
private ICommands _commands;
priate List<Customer> _customers = new List<Customer>();
public Employee(ICommands commands)
{
_commands = commands;
}
public void AddCustomer(string customerName)
{
var customer = new Customer(customerName, _commands);
_customers.Add(customer);
}
}
class Customer
{
private string _name;
private ICommands _commands;
priate List<Case> _cases = new List<Case>();
public Customer(string, name, ICommands commands)
{
_name = name;
_commands = commands;
}
public void AddCase()
{
var case = new Case(_commands);
_cases.Add(case);
}
}
class Case {
private ICommands _commands;
public Customer(ICommands commands)
{
_commands = commands;
}
public void TriggerCommands()
{
_command.TriggerSomething();
}
}
所以,这个例子并没有多大意义,但本质与我需要做的事情相同。我有一些应用程序命令,我通过我的ViewModel类向下传递,因为它们中的一些需要能够触发命令来显示某些东西。我也有一些常见的存储空间等,这可能是某些类所需要的,但目前通过并存储在中间类中。如果存储命令或容器,只有命令就没什么大不了的,但是典型的IoC使用中的一个会通过IoC容器,而是使用它来解决对象的问题吗?那些特定的数据如客户名称呢?你不能只在Resolve()上传入它,所以你需要在之后注入它吗?
对不起 - 这就像我能做到的那么短。不需要相同长度的答案;-) ..只是;用IoC容器做这样的事情的最佳做法是什么?
答案 0 :(得分:3)
我不太清楚我理解你的问题。但我认为你根本不应该把容器转过来。为容器创建一个包装类要容易得多。例如:
public class IoCContainer
{
private static ContainerType = null;
public static ContainerType Instance
{
get
{
if (_container == null)
{
string configFileName = ConfigurationManager.AppSettings[ConfigFileAppSettingName];
_container = new WindsorContainer(new XmlInterpreter(configFileName));
}
return _container;
}
}
}
现在,您可以在代码中随处调用它。
IoCContainer.Instance.Resolve<IAwesomeService>();
这对你有帮助吗?
答案 1 :(得分:2)
我不确定这是否能回答您的问题,但我想说使用Unity容器(也适用于我认为的其他IoC引擎)对应用程序采取行动的好方法是:
IUnityContainer
),并创建所有新的
使用Resolve
的对象实例
方法。即使是没有的物体
已注册且没有依赖关系,
容器会给你一个合适的
实例,稍后您可以决定注册以前未注册的类型,而无需更改客户端代码。InjectionMembers
类中的RegisterType
参数)。答案 2 :(得分:1)
您似乎需要为实体声明工厂。通过构造函数注入解析工厂并通过Create方法传递数据值。必须通过工厂的构造函数解析所有其他依赖项。
请参阅this回答。
答案 3 :(得分:0)
我定义了一个静态类IoC,可以使用特定容器进行初始化,并实现Resolve,Resolve(...)等方法,然后将实际工作委托给容器实例(你将存储它)在一个领域或财产中的实例)。这样你就不必传递任何东西,只需使用
即可IoC.Resolve<SomeType>();
代码中的任何位置。
关于特定数据:某些容器将根据此参数获取参数并解析(Autofac具有此类功能)。或者,您始终可以创建一个工厂类,该工厂类将具有接受一组参数(如客户名称)的方法,并返回相应的对象实例。