[英]Unity resolving constructor with ICollection<IMyInterface> dependency
[英]resolving constructor dependency at runtime (without attributes)
我使用Unity进行依赖注入,我想在运行时控制,解析哪个特定类型并作为依赖项传递给构造函数。
我有一个界面:
public interface IDatabase
{
void DoSomething();
}
这是由两个类实现的:
public class SQLDatabase : IDatabase
{
public void DoSomething()
{
//Do Something on a SQL server database...
}
}
public class OracleDatabase : IDatabase
{
public void DoSomething()
{
//Do Something on an Oracle database...
}
}
第三类依赖于IDatabase
public class DataService: IDataService
{
public DataService(IDatabase database)
{
database.DoSomething();
}
}
该模块使用Unity注册每个类,并为两个IDatabase类型指定特定名称,以便区分它们:
container.RegisterType<IDatabase, SQLDatabase>("SQLDatabase");
container.RegisterType<IDatabase, OracleDatabase>("OracleDatabase");
container.RegisterType<IDataService, DataService>();
我需要创建一个Consumer实例,此时我想指定Unity中使用/注入实现IDatabase的两种类型中的哪一种,但我不知道如何告诉Unity要构造哪种特定类型/解决? 我想我想要这样的东西(伪代码):
public class Consumer
{
IDataService dataService = null;
public Consumer(string runtimeChoice)
{
if (runtimeChoice == "SQLSERVER")
{
dataService = _container.Resolve<IDataService>("SQLDatabase");
}
else if (runtimeChoice == "Oracle")
{
dataService = _container.Resolve<IDataService>("OracleDatabase");
}
}
}
那么,我如何告诉Unity使用特定的命名类型解析IDatabase类型,并将其传递给依赖对象的构造函数,但是在运行时执行它?
我会改变两件事,我会尽量确保那些神奇的字符串尽可能接近它们的源处理,我会尽量确保我的代码与容器无关。
我会有以下界面:
public interface IDataServiceFactory
{
IDataService CreateSqlDataService();
IDataService CreateOracleDataService();
}
有这样的实现:
public class DataServiceFactory : IDataServiceFactory
{
private readonly Func<IDataService> _sqlDataServiceFactory;
private readonly Func<IDataService> _oracleDataServiceFactory;
public DataServiceFactory(Func<IDataService> sqlDataServiceFactory, Func<IDataService> oracleDataServiceFactory)
{
_sqlDataServiceFactory = sqlDataServiceFactory;
_oracleDataServiceFactory = oracleDataServiceFactory;
}
public IDataService CreateSqlDataService()
{
return _sqlDataServiceFactory();
}
public IDataService CreateOracleDataService()
{
return _oracleDataServiceFactory();
}
}
然后我会在你的IUnityContainer
注册这个:
_container.RegisterType<IDataService, DataService>("SQLDataService",
new InjectionConstructor(new ResolvedParameter<IDatabase>("SQLDatabase")));
_container.RegisterType<IDataService, DataService>("OracleDataService",
new InjectionConstructor(new ResolvedParameter<IDatabase>("OracleDatabase")));
_container.RegisterType<IDataServiceFactory, DataServiceFactory>(new InjectionConstructor(
new ResolvedParameter<Func<IDataService>>("SQLDataService"),
new ResolvedParameter<Func<IDataService>>("OracleDataService"));
现在,无论先前创建的Consumer
实例如何,都应该依赖于IDataServiceFactory
并且应该处理运行时值以调用正确的方法CreateSqlDataService()
或CreateOracleDataService()
。
现在,所有运行时代码都与容器无关,并且魔术字符串在其源旁边处理。
我能够使用DependencyOverride解析正确的类型,它本身从unity容器中获取所需的类型。 所以消费者变成:
public class Consumer
{
IDataService dataService = null;
public Consumer(string runtimeChoice)
{
DependencyOverride<IDatabase> dependency = null;
if (runtimeChoice == "SQLSERVER")
{
dependency = new DependencyOverride<IDatabase>
(Container.Resolve<IDatabase>("SQLDatabase"));
}
else if (runtimeChoice == "Oracle")
{
dependency = new DependencyOverride<IDatabase>
(Container.Resolve<IDatabase>("OracleDatabase"));
}
dataService = _container.Resolve<IDataService>(dependency);
}
}
我有一个类似的要求,我需要在运行时解析'widgetbuilder'类型。 在我的Unity配置中,我注册了两种类型的小部件构建器: -
container.RegisterType<IWidgetBuilder, SinglePointWidgetBuilder>("SinglePointWidgetBuilder");
container.RegisterType<IWidgetBuilder, CurrentVsTargetWidgetBuilder>("CurrentVsTargetWidgetBuilder");
然后我在运行时解决它们: -
var container = UnityConfig.GetConfiguredContainer();
var widgetBuilder = container.Resolve<IWidgetBuilder>("SinglePointWidgetBuilder");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.