【问题标题】:Resolving Generic Interface with Autofac使用 Autofac 解析通用接口
【发布时间】:2009-07-27 17:28:27
【问题描述】:

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

【问题讨论】:

    标签: c# autofac


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      更正。您不能从容器中调用 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);
                  }
              });
      

      然后解析像这样发生,将一个 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);
              }
      

      感谢您的帖子提供了帮助,希望这次更新对您有所帮助。

      【讨论】:

      • MakeGenericType 按照 andrey.tsykunov 接受的答案中的描述为我工作。从你描述的方式来看,听起来你可能试图在 DI 容器而不是类型上调用它。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 2020-01-27
      • 1970-01-01
      • 2019-11-23
      • 2012-11-22
      相关资源
      最近更新 更多