Autofac - 注册(部分)开放通用。

时间:2015-06-26 14:03:48

标签: c# dependency-injection autofac

我有以下配置,我想在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.???

1 个答案:

答案 0 :(得分:2)

让我们假设你有这些类型:

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 返回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方法内部使用的方法。