使用Autofac解决通用接口问题

37
给定以下代码,我该如何在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或SomeInstance2。

例如,我有一个子类集合(SubClass1、2...),在迭代它们时,我希望能够选择正确的SomeInstance类。

2个回答

76

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);

如果类型参数直到运行时才知道(如果你想迭代类型集合的话,这很可能是你的情况),那么你可以使用MakeGenericType构建你的类型:

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

4

更正:您不能从容器中调用MakeGenericType。我通过在Resolve调用中使用“TYPE”作为参数解决了实例化泛型的问题。生成器已注册。

        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传递给解析。在这种情况下,我有一个项目列表(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);
        }

感谢您的帖子,它对我很有帮助。希望这个更新能够发挥作用。

MakeGenericType按照andrey.tsykunov的答案所描述的方式对我有效。从你的描述中,听起来你可能尝试在DI容器上调用它而不是类型本身。 - Chris D

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接