鉴于以下代码,如何在autofac中解析正确的SomeInstance?
public class BaseClass {}
public class SubClass1 : BaseClass {}
public class SubClass2 : BaseClass {}
public interface IGenericInterface<T> where T : BaseClass {}
public class SomeInstance1<T> : IGenericInterface<T> where T : SubClass1
public class SomeInstance2<T> : IGenericInterface<T> where T : SubClass2
我想根据子类的泛型类型选择SomeInstance1或2。
因此,例如,我有一个子类的集合(SubClass1,2 ....),并在迭代它们时,我想选择正确的SomeInstance类。
答案 0 :(得分:66)
Autofac支持开放式泛型。如果在编译时已知泛型类型,则可以使用以下代码:
var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(SomeInstance1<>))
.As(typeof(IGenericInterface<>));
var container = builder.Build();
var instance1 = container.Resolve<IGenericInterface<SubClass1>>();
Assert.IsInstanceOfType(typeof(SomeInstance1<SubClass1>), instance1);
如果在运行时之前不知道type参数(如果你想迭代类型集合,可能就是这种情况),那么你可以使用MakeGenericType构建你的类型:
var typeInRuntime = typeof (SubClass1);
var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime));
答案 1 :(得分:3)
校正。您不能从Container调用MakeGenericType。我解决了使用&#39; TYPE&#39;来实例化泛型的问题。作为Resolve调用的参数。建造者已注册。
builder.RegisterGeneric(typeof (FakeRepository<>)).As(typeof (IRepository<>)).OnActivating(e =>
{
var typeToLookup = e.Parameters.FirstOrDefault() as TypedParameter;
if (typeToLookup != null)
{
var respositoryType = typeof (FakeRepository<>);
Type[] typeArgs = {typeToLookup.Value.GetType()};
var genericType = respositoryType.MakeGenericType(typeArgs);
var genericRepository = Activator.CreateInstance(genericType);
e.ReplaceInstance(genericRepository);
}
});
然后解决方案就像这样,将TypedParameter传递给Resolve。在这种情况下,我有一个项目列表(IItem)已解决,我想为该类型的所有项目创建一个存储库。
var items = container.Resolve<IEnumerable<IItem<string>>>();
foreach (var item in items)
{
var repository = container.Resolve(typeof (IRepository<DataItemBase>), new TypedParameter(item.GetType(), item));
Assert.IsNotNull(repository);
}
感谢您的帖子帮助,我希望此更新有所帮助。