2011-04-25 77 views
7

我有一堆在容器中註冊,就像TaskParametes類實例:autofac:如何解析命名類型的集合?

builder.Register(c => [some type instantiation] 
    )).Named<TaskParameters>("someTask").InstancePerDependency(); 

builder.Register(c => [some type instantiation] 
    )).Named<TaskParameters>("someOtherTask").InstancePerDependency(); 

這些類可以在應用程序的任何模塊中進行註冊。我想獲取可用命名實例的列表以將其發送給客戶端,客戶端應該實例化並按名稱執行它。

是否有一個選項來獲取名稱列表,而不實際實例化類型? 目前我正在挖掘ComponentRegistry的IComponentContext,我從中獲得,var ctx = Container.Resolve<IComponentContext>();,我在正確的方向嗎?

回答

4

元數據比在這種情況下命名更合適。

對於強類型的變體,定義一個接口來保持的元數據:

public interface ITaskMetadata 
{ 
    string Name { get; } 
} 

然後在生成時的元數據相關聯:

builder.Register(c => [some type instantiation])) 
    .As<TaskParameters>() 
    .WithMetadata<ITaskMetadata>(m => 
     m.For(tm => tm.Name, "someTask")); 

builder.Register(c => [some type instantiation])) 
    .As<TaskParameters>() 
    .WithMetadata<ITaskMetadata>(m => 
     m.For(tm => tm.Name, "someOtherTask")); 

(省略了該InstancePerDependency(),因爲它是默認行爲)。

然後,需要檢查名稱的組件可以依賴於IEnumerable<Lazy<T,TMetadata>>,如下所示:

class SomeComponent : ISomeComponent 
{ 
    public SomeComponent(
     IEnumerable<Lazy<TaskParameters,ITaskMetadata>> parameters) 
    { 
     // Here the names can be examined without causing instantiation. 
    } 
} 

這使用relationship types避免需要在容器中查找任何東西。

請注意,Lazy<,>類型來自.NET 4.有關在.NET 3.5中實現此功能以及替代語法的詳細信息,請參閱Autofac wiki

+0

元數據的問題是我無法從容器中查詢它(有'ResolveNamed'和'ResolveKeyed',但沒有元數據resove)。 我也無法找到「For」擴展名,它是否在一些特殊的命名空間? (AutoFac版本2.4.4.705) – ikutsin 2011-04-26 07:31:33

+1

Intellisense(ReSharper?)在WithMetadata方法中遇到問題 - 它仍然應該編譯。如果您還想從容器中解析這些處理程序,請發佈該場景的一些詳細信息,但您的問題僅涉及通過委派給客戶端來創建實例。對於快速和骯髒,可以使用Named()以及WithMetadata()。乾杯! – 2011-04-26 21:58:28

1

如果服務的名稱對於您的應用程序很重要,那麼可能應該將它建模到您的代碼中。例如,您有TaskParameters;也許你想要的東西是這樣的:

public class Descriptor<T> 
{ 
    private readonly string _description; 
    private readonly Func<T> _create; 

    public Descriptor(string description, Func<T> create) 
    { 
     _description = description; 
     _create = create; 
    } 

    public string Description { get { return _description; } } 
    public T Create() { return _create(); } 
} 

然後你可以註冊你的類型描述符。那麼你可以很容易地打電話

var descriptors = container.Resolve<IEnumerable<Descriptor<TaskParameters>>>(); 
0

我did'n找到任何解決方案,而不是查詢上下文:

var ctx = Container.Resolve<IComponentContext>(); 
    var taskNames = ctx.ComponentRegistry.Registrations 
     .Select(c => c.Services.FirstOrDefault() as KeyedService) 
     .Where(s => s != null && s.ServiceType == typeof (TaskParameters)) 
     .Select(s => s.ServiceKey).ToList(); 

看來,這種做法不會實例,也沒有任何激活。

+0

???那麼,這不是一個答案? – barrypicker 2014-09-30 16:46:52