我有这样的课程(WebApi 2 Controller):
class DatabaseAnalysisController (IDatabase databaseOne,
IDatabase databaseTwo) : ApiController
这样的课程:
class Database : IDatabase
现在我有两个实例:
Database databaseOne = new Database("one");
Database databaseTwo = new Database("two");
我不希望DatabaseAnalysis
对Autofac有任何依赖。但是我想使用Autofac来根据构造函数的参数名称进行注入。
我正在使用Autofac.WebApi
注册我的控制器。
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
但之后这不起作用,因为databaseOne
和databaseTwo
都是IDatabase
。
builder.RegisterInstance(new Database("one")).As<IDatabase>();
Autofac是否可以将databaseOne
注入databaseOne
的构造函数DatabaseAnalysis
(以及databaseTwo
中的databaseTwo
)?
如果是这样,怎么样? :P
答案 0 :(得分:3)
由于您有多个具有相同接口和类型的实例 - 您需要使用名称注册它们:
builder.RegisterInstance(new Database("one")).Named<IDatabase>("databaseOne");
builder.RegisterInstance(new Database("two")).Named<IDatabase>("databaseTwo");
然后您可以注册DatabaseAnalysisController
,如下所示:
builder.RegisterType<DatabaseAnalysis>().WithParameter(
(pi, ctx) => pi.ParameterType == typeof(IDatabase),
(pi, ctx) => ctx.ResolveNamed<IDatabase>(pi.Name));
您可以使用扩展方法执行此类注册:
public static class AutofacExtensions {
public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> WithNamedParameter<TLimit, TReflectionActivatorData, TStyle>(this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration, Type targetType)
where TReflectionActivatorData : ReflectionActivatorData {
return registration.WithParameter(
(pi, ctx) => pi.ParameterType == targetType,
(pi, ctx) => ctx.ResolveNamed(pi.Name, targetType));
}
}
要为所有控制器执行此操作,请执行以下操作:
builder.RegisterApiControllers().WithNamedParameter(typeof(IDatabase));
答案 1 :(得分:2)
不是使注入的依赖项依赖于构造函数参数名称,处理这些依赖项的另一种方法就是使接口通用。然后,通用结束类型(T
)将确定要注入的IDatabase<T>
。
interface IDatabase<T> {}
class Database1 : IDatabase<Database1>
class Database2 : IDatabase<Database2>
在您的服务中:
class SomeService1
{
public SomeService1(IDatabase<Database1> database)
{
// set database to private variable
}
}
class SomeService2
{
public SomeService2(IDatabase<Database2> database)
{
// set database to private variable
}
}
可以注册如下:
builder.RegisterType<IDatabase<Database1>>().As<Database1>();
builder.RegisterType<IDatabase<Database2>>().As<Database2>();
虽然实现之间共享IDatabase<T>
,但.NET类型系统(以及Autofac)将IDatabase<Database1>
视为与IDatabase<Database2>
完全不同的类型。这意味着类型会自动放到正确的位置,但这也意味着您不能只在应用程序中交换一个类型。因此,这是否适合您取决于您的具体用例。