繁体   English   中英

autofac:如何解决命名类型的集合?

[英]autofac: How to resolve collection of named types?

我在容器中注册了一堆TaskParametes类实例,如:

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

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

这些类可以在应用程序的任何模块中注册。 我想获取可用的命名实例列表以将其发送到客户端,客户端应该按名称实例化并执行它。

是否有选项可以获取名称列表,而无需实际实例化类型? 目前我正在挖掘IComponentContext的ComponentRegistry,我得到了它, var ctx = Container.Resolve<IComponentContext>(); 我正朝着正确的方向前进吗?

在这种情况下,元数据比命名更合适。

对于强类型变体,定义用于保存元数据的接口:

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.
    }
}

这使用关系类型来避免在容器中查找任何内容。

注意, Lazy<,>类型来自.NET 4.有关在.NET 3.5中实现此功能的详细信息以及替代语法,请参阅Autofac wiki

如果服务名称对您的应用程序很重要,那么可能应该将其建模到您的代码中。 例如,您有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>>>();

我找不到任何解决方案而不是查询上下文:

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

似乎这种方法不会实例化也不会激活任何东西。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM