我们计划在项目中使用Unity来动态加载驻留在不同程序集中的对象/类型。要注册我们使用.config文件的类型。我已经编写了一个小样本应用程序来测试它,并且一切正常。以下是示例代码:
/* App.config
...
<container name="xyz">
<register type="IOperations" mapTo="COperations">
<lifetime type="external" />
</register>
<register type="ITest" mapTo="CTest">
<lifetime type="external" />
</register>
</container>
...
*/
public class CA
{ }
public class CB
{ }
public interface IMyOperations : IDisposable
{
void DoSomething(string str);
}
public interface ITest : IDisposable
{
void DoSomethingElse(string str);
}
class Program
{
static void Main(string[] args)
{
string containerName = "xyz";
using ( IUnityContainer container = new UnityContainer() )
{
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container, containerName);
IMyOperations myOps = container.Resolve<IMyOperations>();
myOps.DoSomething("Hello");
myOps.Dispose();
ITest test = container.Resolve<ITest>();
test.DoSomethingElse("World!");
test.Dispose();
}
}
}
public class COperations
{
private IUnityContainer container;
public COperations(IUnityContainer container)
{
this.container = container;
}
public void DoSomethingElse(string str)
{
// based on runtime values create an instance of class CA or CB and register them with the container
if (str.Length > 10)
container.RegisterInstance<CA>("InstanceCA", new CA());
else
container.RegisterInstance<CB>("InstanceCB", new CB());
}
public void Dispose()
{ }
}
public class CTest
{
private IUnityContainer container;
public CTest(IUnityContainer container)
{
this.container = container;
}
public void DoSomethingElse(string str)
{
// based on runtime values get the registered instance of class CA or CB
if (str.Length > 100)
container.Resolve<CA>("InstanceCA");
else
container.Resolve<CB>("InstanceCB");
}
public void Dispose()
{ }
}
我还在容器解析类型中创建新对象(上面代码中的类CA和CB),并使用ResisterInstance()向容器注册那些对象。为此,我将更改容器已解决的类型的ctor签名,如下所示:
public COperations(IUnityContainer容器)
我不确定这是否是正确的做法。有没有更好的方法来使用容器从容器解析类型对象注册实例?我试图在彼此之间共享一些对象,我只能在运行时才能知道。这也使我的组件与Unity硬连线,如果我们决定稍后移动到另一个容器,则无用。
答案 0 :(得分:0)
如果您想在代码中注册内容,我建议您创建一个注册工厂。然后,您将通过构造函数传递注册工厂,它将注册您的对象。这样你就可以从Unity中解耦了。
所以:
public interface IRegistrationFactory
{
void RegisterInstance<TI,TO>();
void RegisterType<TI,TO>();
void RegisterInstance<TI,TO>(string name, TO objectToRegister);
}
public class COperations
{
private IRegistrationFactory _factory;
public COperations(IRegistrationFactory factory)
{
_factory= factory;
}
public void DoSomethingElse(string str)
{
// based on runtime values create an instance of class CA or CB and register them with the container
if (str.Length > 10)
_factory.RegisterInstance<CA,CA>("InstanceCA", new CA());
else
_factory.RegisterInstance<CB,CB>("InstanceCB", new CB());
}
你显然需要实现IRegistrationFactory。所有这些都是一个在构造函数中使用IUnityContainer然后实现接口的类。
如果您决定从Unity更改为另一个DI容器,您需要做的就是调整IRegistrationFactory以处理新的DI容器。
此外,如果您正在注册实例,您可以这样做:
_container.RegisterType(new ContainerControlledLifetimeManager());
这将始终返回对象的相同实例,因此它就像RegisterInstance。这种方法的优点是Unity将为您解决任何CA依赖项,而如果您使用RegisterInstance,则必须手动执行此操作。