2009-10-06 56 views
6

指定的文档指出Autofac支持开放泛型和我能够像这样注册和解析的基本情况:Autofac与开放式泛型和类型在运行时

报名:

builder.RegisterGeneric(typeof(PassThroughFlattener<>)) 
     .As(typeof(IFlattener<>)) 
     .ContainerScoped(); 

解决:

var flattener = _container.Resolve<IFlattener<Address>>(); 

上面的代码工作得很好。但是,假设我不知道提供给IFlattener类型,直到运行时,我想要做这样的事情:

object input = new Address(); 
var flattener = (IFlattener)_container.Resolve(typeof(IFlattener<>), new TypedParameter(typeof(IFlattener<>), input.GetType())); 

这可能与AutoFac?我从以下使用StructureMap的想法:

http://structuremap.sourceforge.net/Generics.htm

我试图实现在这篇文章中列出的相同目标。

回答

9

这对于Autofac来说当然是可行的。在“注册时间”,这就是你基本上做到:

  1. 注册的开放式泛型类型(PassThroughFlattener <>)
  2. 注册任何特定类型(AddressFlattener)
  3. 注册可用于的方法解决基于输入对象

在 “解决时间” 上的IFlattener,你会做什么:

  1. 解决方法
  2. 呼叫与输入参数(S)的方法来解决IFlattener实施

这里有一个(希望)工作样本:

var openType = typeof(IFlattener<>); 

var builder = new ContainerBuilder(); 
builder.RegisterGeneric(typeof(PassThroughFlattener<>)).As(openType); 
builder.Register<AddressFlattener>().As<IFlattener<Address>>(); 
builder.Register<Func<object, IFlattener>>(context => theObject => 
    { 
     var concreteType = 
      openType.MakeGenericType(theObject.GetType()); 
      return (IFlattener) context.Resolve(concreteType, 
       new PositionalParameter(0, theObject)); 
    }); 
var c = builder.Build(); 

var factory = c.Resolve<Func<object, IFlattener>>(); 

var address = new Address(); 
var addressService = factory(address); 

Assert.That(addressService, Is.InstanceOfType(typeof(AddressFlattener))); 

var anything = "any other data"; 
var anyService = factory(anything); 

Assert.That(anyService, Is.InstanceOfType(typeof(PassThroughFlattener<string>))); 
+0

感谢您的快速响应,该工作! – 2009-10-06 12:54:05

4

如果你不知道类型,直到您可以使用MakeGenericType构建它:

var addressFlattener = _container.Resolve(typeof(IFlattener<>).MakeGenericType(typeof(Address)));