C# 使用 Autofac 解析通用接口
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1189519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Resolving Generic Interface with Autofac
提问by DownChapel
Given the following code, how do I resolve the right SomeInstance in autofac?
给定以下代码,如何在 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
I want to choose SomeInstance1 or 2 based on the type of of the generic on the sub classes.
我想根据子类上的泛型类型选择 SomeInstance1 或 2。
So for example I have a collection of sub classes (SubClass1, 2....) and while iterating over them I want to choose the right SomeInstance class.
例如,我有一组子类(SubClass1、2....),在迭代它们时,我想选择正确的 SomeInstance 类。
采纳答案by andrey.tsykunov
Autofac supports open generics. You can use the following code if generics type is known at compile time:
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);
If type parameter is not known until runtime (which is likely your case if you want to iterate through collection of types) then you can build your type using MakeGenericType:
如果直到运行时才知道类型参数(如果您想遍历类型集合,这很可能是您的情况),那么您可以使用 MakeGenericType 构建您的类型:
var typeInRuntime = typeof (SubClass1);
var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime));
回答by JeremyFromNaples
Correction. You cannot call MakeGenericType from the Container. I solved the issue of instantiating Generics using the 'TYPE' as the parameter on the Resolve call. The builder is registered.
更正。您不能从 Container 调用 MakeGenericType。我解决了使用“TYPE”作为 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);
}
});
Then the resolution happens like this, passing a TypedParameter to the Resolve. In this case I have a list of items (IItem) that are resolved that I want to create a repository for all of the items of that type.
然后解析像这样发生,将 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);
}
Thanks for your post it helped and I Hope this update helps.
感谢您的帖子,它有所帮助,我希望此更新有所帮助。