autofacc:如何解析命名类型集合

本文关键字:类型 集合 何解析 autofacc | 更新日期: 2023-09-27 17:52:43

我有一堆taskparameters类实例在容器中注册,如:

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>();获得,我是否在正确的方向上?

autofacc:如何解析命名类型集合

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

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

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

这种方法似乎没有实例化或激活任何东西。