2009-10-06 69 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)));