C# 统一:条件分解
我希望使用Unity根据收到的特定数据在运行时解析类型。我的代码(与下面显示的代码类似)当前在启动时在引导程序类中注册类型,然后在主流中决定需要什么类型 我想做的是用解析器替换使用“new”关键字的代码行,然而,由于这段代码已经超出了我的引导程序,我不确定如何做到这一点……我是Unity的新手,所以请轻松一点C# 统一:条件分解,c#,dependency-injection,unity-container,C#,Dependency Injection,Unity Container,我希望使用Unity根据收到的特定数据在运行时解析类型。我的代码(与下面显示的代码类似)当前在启动时在引导程序类中注册类型,然后在主流中决定需要什么类型 我想做的是用解析器替换使用“new”关键字的代码行,然而,由于这段代码已经超出了我的引导程序,我不确定如何做到这一点……我是Unity的新手,所以请轻松一点 // In Bootstrapper class resolver.RegisterType<IDataType1, DataType1>(); resolver.Regist
// In Bootstrapper class
resolver.RegisterType<IDataType1, DataType1>();
resolver.RegisterType<IDataType2, DataType2>();
resolver.RegisterType<IDataType3, DataType3>();
// Main flow...outwith bootstrapper
switch (dataRecordType)
{
case DataRecordType.dataType1:
DataType1 dt1 = new DataType1();
dt1.ProcessData();
break;
case DataRecordType.dataType2:
DataType2 dt2 = new DataType2();
dt2.ProcessData();
break;
case DataRecordType.dataType3:
DataType3 dt3 = new DataType3();
dt3.ProcessData();
break;
default:
break;
}
//在引导程序类中
resolver.RegisterType();
resolver.RegisterType();
resolver.RegisterType();
//主流…用引导器输出
开关(数据记录类型)
{
案例DataRecordType.dataType1:
DataType1 dt1=新的DataType1();
dt1.ProcessData();
打破
案例DataRecordType.dataType2:
DataType2 dt2=新的DataType2();
dt2.ProcessData();
打破
案例DataRecordType.dataType3:
DataType3 dt3=新的DataType3();
dt3.ProcessData();
打破
违约:
打破
}
这里缺少一些抽象概念。您缺少对数据类型的一般抽象和创建这些数据类型的实现的抽象:
// In your core layer
public interface IDataType {
void ProcessData();
}
public interface IDataTypeFactory {
IDataType Create(DataRecordType dataRecordType);
}
// In Bootstrapper class
resolver.RegisterInstance<IDataTypeFactory>(new DataTypeFactory(resolver));
resolver.RegisterType<IDataType1, DataType1>();
resolver.RegisterType<IDataType2, DataType2>();
resolver.RegisterType<IDataType3, DataType3>();
private sealed class DataTypeFactory : IDataTypeFactory {
private readonly IUnityContainer container;
public DataTypeFactory(IUnityContainer container) {
this.container = container;
}
public IDataType Create(DataRecordType dataRecordType) {
switch (dataRecordType) {
case DataRecordType.dataType1:
return this.container.Resolve<IDataType1>();
case DataRecordType.dataType2:
return this.container.Resolve<IDataType2>();
case DataRecordType.dataType3:
return this.container.Resolve<IDataType3>();
default:
throw new InvalidEnumArgumentException();
}
}
}
IDataType1
、IDataType2
和IDataType3
现在仅在引导程序中使用,并且已变得冗余(或者至少与您提供的代码冗余),因此您甚至可以将它们一起删除,并将引导逻辑更改为以下内容:
// In Bootstrapper class
resolver.RegisterInstance<IDataTypeFactory>(new DataTypeFactory(resolver));
resolver.RegisterType<DataType1>();
resolver.RegisterType<DataType2>();
resolver.RegisterType<DataType3>();
private sealed class DataTypeFactory : IDataTypeFactory {
private readonly IUnityContainer container;
public DataTypeFactory(IUnityContainer container) {
this.container = container;
}
public IDataType Create(DataRecordType dataRecordType) {
switch (dataRecordType) {
case DataRecordType.dataType1:
return this.container.Resolve<DataType1>();
case DataRecordType.dataType2:
return this.container.Resolve<DataType2>();
case DataRecordType.dataType3:
return this.container.Resolve<DataType3>();
default:
throw new InvalidEnumArgumentException();
}
}
}
//在引导程序类中
resolver.RegisterInstance(新的DataTypeFactory(resolver));
resolver.RegisterType();
resolver.RegisterType();
resolver.RegisterType();
私有密封类DataTypeFactory:IDataTypeFactory{
专用只读IUnityContainer容器;
公共数据类型工厂(IUnityContainer容器){
this.container=容器;
}
公共IDataType创建(DataRecordType DataRecordType){
开关(数据记录类型){
案例DataRecordType.dataType1:
返回此.container.Resolve();
案例DataRecordType.dataType2:
返回此.container.Resolve();
案例DataRecordType.dataType3:
返回此.container.Resolve();
违约:
抛出新的InvalidEnumArgumentException();
}
}
}
+1值得一提的是,IOC容器不应遗漏合成根(因为OP似乎是初学者)。还有一种方法,我们可以创建一个工厂,而无需将代码与容器耦合。解析?@SriramSakthivel:感谢您的注意。我同意,容器不应该被引用到任何地方,除了复合根。可以将工厂与容器解耦,但由于此工厂实现可以是Composition根的一部分,因此工厂引用容器本身没有问题。但是另一种选择是将DataTypeX
类注入工厂而不是容器。我想您的意思是将Func
注入工厂?否则,我们需要多个工厂实例来获取新的DataTypeX的实例,不是吗?@SriramSakthivel:不是。我的意思是要有一个具有以下构造函数的工厂:DataTypeFactory(DataType1 dt1,DataType2 dt2,DataType3 dt3)
。是的,但是您的工厂将始终返回相同的实例。这改变了人们的行为,对吗?为了实现当前行为(瞬态),我们需要DataTypeFactory(Func dt1,Func dt2,…)
如果我错了,请纠正我。我是autofac用户,默认生存期是每个依赖项的实例数,这就是我问这个问题的原因:)
// In Bootstrapper class
resolver.RegisterInstance<IDataTypeFactory>(new DataTypeFactory(resolver));
resolver.RegisterType<DataType1>();
resolver.RegisterType<DataType2>();
resolver.RegisterType<DataType3>();
private sealed class DataTypeFactory : IDataTypeFactory {
private readonly IUnityContainer container;
public DataTypeFactory(IUnityContainer container) {
this.container = container;
}
public IDataType Create(DataRecordType dataRecordType) {
switch (dataRecordType) {
case DataRecordType.dataType1:
return this.container.Resolve<DataType1>();
case DataRecordType.dataType2:
return this.container.Resolve<DataType2>();
case DataRecordType.dataType3:
return this.container.Resolve<DataType3>();
default:
throw new InvalidEnumArgumentException();
}
}
}