Autofac - 注册一个(部分)开放通用。
Autofac - Register a (Partially) Open Generic.
我想在 autofac 中注册以下配置:
UploadStrategy1<T> : IUploadStrategy<Thing1, T>
UploadStrategy3<T> : IUploadStrategy<Thing3, T>
......
在这样的构造函数中
public class UploadDownloadHandlerStrategy1<T> : IUploadDownloadHandlerStrategy1<T, Thing1, OtherThing1>
{
public UploadDownloadHandlerStrategy1(IUpoadStrategey<Thing1, T>,
IDownloadStrategy<Thing1, OtherThing1>)
}
这是不理想的情况之一,它确实必须如此混乱。实际上,我很自豪我完全解耦了它。
我唯一没有使用的部分是 IUploadStrategy。到目前为止大约有 8 个实现,但它应该按比例放大,所以最好是批量。
我就是想不通那在 autofac 中应该是什么样子。
builder.???
假设您有这些类型:
public class Thing1 { }
public class Thing2 { }
public class Thing3 { }
public interface IUploadStrategy<T1, T2> { }
public class UploadStrategy1<T> : IUploadStrategy<Thing1, T> { }
public class UploadStrategy2<T> : IUploadStrategy<Thing2, T> { }
当您解析 IUploadStrategy<Thing1, String>
时,您希望 Autofac 成为 return UploadStrategy1<String>
的一个实例,当您解析 IUploadStrategy<Thing2, String>
时,您想要一个 UploadStrategy2<String>
的实例
您可以像这样注册这些类型来做到这一点:
builder.RegisterGeneric(typeof(UploadStrategy1<>)).As(typeof(IUploadStrategy<,>));
builder.RegisterGeneric(typeof(UploadStrategy2<>)).As(typeof(IUploadStrategy<,>));
通过这样做 Autofac 将自动考虑对 T1
.
的约束
所以,
var s1 = container.Resolve<IUploadStrategy<Thing1, String>>();
Console.WriteLine(s1.GetType()); // will be UploadStrategy1
var s2 = container.Resolve<IUploadStrategy<Thing2, String>>();
Console.WriteLine(s2.GetType()); // will be UploadStrategy2
将按预期工作。请参阅此 dotnetfiddle 以获取实时示例:https://dotnetfiddle.net/cwvait
如果要自动解析这些类型,可以考虑使用RegisterAssemblyTypes
方法。不幸的是,这种方法不会让你做你想做的事,因为它不是 RegisterAssemblyGenericTypes
方法。您将不得不自己扫描您的程序集。例如:
foreach (Type t in typeof(Program).Assembly
.GetLoadableTypes()
.Where(t => t.GetInterfaces()
.Any(i => i.IsGenericType
&& i.GetGenericTypeDefinition() == typeof(IUploadStrategy<,>))))
{
builder.RegisterGeneric(t).As(typeof(IUploadStrategy<,>));
}
GetLoadableTypes
方法是位于Autofac.Util
命名空间的扩展方法,这是RegisterAssemblyTypes
方法内部使用的方法。
我想在 autofac 中注册以下配置:
UploadStrategy1<T> : IUploadStrategy<Thing1, T>
UploadStrategy3<T> : IUploadStrategy<Thing3, T>
......
在这样的构造函数中
public class UploadDownloadHandlerStrategy1<T> : IUploadDownloadHandlerStrategy1<T, Thing1, OtherThing1>
{
public UploadDownloadHandlerStrategy1(IUpoadStrategey<Thing1, T>,
IDownloadStrategy<Thing1, OtherThing1>)
}
这是不理想的情况之一,它确实必须如此混乱。实际上,我很自豪我完全解耦了它。
我唯一没有使用的部分是 IUploadStrategy。到目前为止大约有 8 个实现,但它应该按比例放大,所以最好是批量。
我就是想不通那在 autofac 中应该是什么样子。
builder.???
假设您有这些类型:
public class Thing1 { }
public class Thing2 { }
public class Thing3 { }
public interface IUploadStrategy<T1, T2> { }
public class UploadStrategy1<T> : IUploadStrategy<Thing1, T> { }
public class UploadStrategy2<T> : IUploadStrategy<Thing2, T> { }
当您解析 IUploadStrategy<Thing1, String>
时,您希望 Autofac 成为 return UploadStrategy1<String>
的一个实例,当您解析 IUploadStrategy<Thing2, String>
时,您想要一个 UploadStrategy2<String>
您可以像这样注册这些类型来做到这一点:
builder.RegisterGeneric(typeof(UploadStrategy1<>)).As(typeof(IUploadStrategy<,>));
builder.RegisterGeneric(typeof(UploadStrategy2<>)).As(typeof(IUploadStrategy<,>));
通过这样做 Autofac 将自动考虑对 T1
.
所以,
var s1 = container.Resolve<IUploadStrategy<Thing1, String>>();
Console.WriteLine(s1.GetType()); // will be UploadStrategy1
var s2 = container.Resolve<IUploadStrategy<Thing2, String>>();
Console.WriteLine(s2.GetType()); // will be UploadStrategy2
将按预期工作。请参阅此 dotnetfiddle 以获取实时示例:https://dotnetfiddle.net/cwvait
如果要自动解析这些类型,可以考虑使用RegisterAssemblyTypes
方法。不幸的是,这种方法不会让你做你想做的事,因为它不是 RegisterAssemblyGenericTypes
方法。您将不得不自己扫描您的程序集。例如:
foreach (Type t in typeof(Program).Assembly
.GetLoadableTypes()
.Where(t => t.GetInterfaces()
.Any(i => i.IsGenericType
&& i.GetGenericTypeDefinition() == typeof(IUploadStrategy<,>))))
{
builder.RegisterGeneric(t).As(typeof(IUploadStrategy<,>));
}
GetLoadableTypes
方法是位于Autofac.Util
命名空间的扩展方法,这是RegisterAssemblyTypes
方法内部使用的方法。