[英]Autofac and generics
我有这堂课
public class MyViewModel<T> where T : class
{
public MyViewModel(
Func<IEnumerable<T>, MyService<T>> myServiceFactory,
IEnumerable<T> list)
{
}
}
我需要在引导程序中注册Func
。
我尝试了类似的东西
builder.Register<Func<IEnumerable<T>, MyService<T>>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return collection => ctx.Resolve<MyService<T>>(collection);
});
但我无法正常运作。 谁能帮我?
正如您已经注意到的,您尝试执行的操作不会编译。 没有在某个地方定义T
,C#编译器将无法理解。 如果没有静态定义的T
,则必须使用反射来定义类型,但是很快就会达到Autofac和C#的极限。 您的代码变得非常讨厌。 相反,您必须在辅助方法中提取以下代码:
private static void RegisterMyServiceFactory<T>(IContainerBuilder builder) {
builder.Register<Func<IEnumerable<T>, MyService<T>>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return collection => ctx.Resolve<MyService<T>>(collection);
});
使用此方法时,需要为应用程序中需要的每个T
调用此方法:
RegisterMyServiceFactory<Customer>(builder);
RegisterMyServiceFactory<Order>(builder);
RegisterMyServiceFactory<Employee>(builder);
这个解决方案并不是特别好,但这是因为您缺少抽象。 不要让消费者依赖Func<IEnumerable<T>, MyService<T>>
,而应创建特定的抽象供消费者依赖:
public interface IServiceFactory<T> {
MyService<T> Resolve(IEnumerable<T> collection);
}
并将您的代码嵌入IServiceFactory<T>
实现中:
private sealed class AutofacServiceFactory<T> : IServiceFactory<T> {
private readonly IComponentContext context;
public AutofacServiceFactory(IComponentContext context) {
this.context = context;
}
public MyService<T> Resolve(IEnumerable<T> collection) {
return context.Resolve<MyService<T>>(collection);
}
}
您可以按以下方式注册此开放通用类型:
builder.RegisterGeneric(typeof(AutofacServiceFactory<>))
.As(typeof(IServiceFactory<>));
如果builder.Register代码是由MyViewModel的实例执行的,则可以/应该工作。
否则,这取决于在特定上下文中如何/是否声明T,并且您需要提供更多信息。
无论如何,您的问题似乎与autofac无关。 它与泛型的使用有关。 Register方法确实是通用方法,但是在进行调用时,必须将通用参数最终转换为具体类型。 因此,除非在对builder.Register的调用上下文中正确声明了T,否则它将无法正常工作,因为您似乎正在尝试注册整个类型的类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.