简体   繁体   English

使用Autofac解析通用接口

[英]Resolving Generic Interface with Autofac

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类。

Autofac supports open generics. Autofac支持开放式泛型。 You can use the following code if generics type is known at compile time: 如果在编译时已知泛型类型,则可以使用以下代码:

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: 如果直到运行时才知道type参数(如果你想迭代类型集合,可能就是这种情况),那么你可以使用MakeGenericType构建你的类型:

        var typeInRuntime = typeof (SubClass1);
        var instance1 = container.Resolve(typeof(IGenericInterface<>).MakeGenericType(typeInRuntime));

Correction. 更正。 You cannot call MakeGenericType from the Container. 您不能从Container调用MakeGenericType。 I solved the issue of instantiating Generics using the 'TYPE' as the parameter on the Resolve call. 我解决了使用'TYPE'作为Resolve调用的参数来实例化泛型的问题。 The builder is registered. 建造者已注册。

        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. 然后解决方案就像这样,将TypedParameter传递给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. 在这种情况下,我有一个项目列表(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. 感谢您的帖子,它有所帮助,我希望此更新有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM