我正在使用 Unity 进行依赖注入(inject),我想在运行时控制哪种特定类型被解析并作为依赖项传递到构造函数中。
我有一个界面:
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 的实例,此时我想指定实现 IDatabase 的两种类型中的哪一种将由 Unity 使用/注入(inject),但我不知道如何告诉 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()
。
您的所有运行时代码现在都与容器无关,并且魔术字符串紧挨着它们的源进行处理。
关于c# - 在运行时解析构造函数依赖(没有属性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25026561/