2011-04-25 72 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