1

我使用 SimpleInjector 作为我的 IoC 容器。我已经创建了一个发布/订阅框架,我现在需要能够通过让订阅者指出他们的执行优先级来对其进行改进。例如,我可以创建一个订阅者来预加载事务剩余部分所需的所有数据。

我能想到的一种方法是[SubscriberPriority]在注册过程中创建一个属性来指示需求,RegisterManyForOpenGeneric但我还没有深入研究。

有没有办法管理GetAllInstances返回注册的订单?

更新:

我刚刚想到的另一个选择是使用 CoC(Convention over Configuration)在实例返回时对它们进行排序GetAllInstances

4

1 回答 1

1

由于您表明您正在使用GetAllInstances,我怀疑您使用了一个RegisterManyForOpenGeneric接受回调委托的重载,如下所示:

container.RegisterManyForOpenGeneric(
    typeof(ISubstriber<>),
    (type, impls) => container.RegisterAll(type, impls),
    typeof(ISubstriber<>).Assembly);

在这种情况下,将实现列表提供给委托的顺序取决于它们从 .NET 元数据返回的顺序。RegisterManyForOpenGeneric只需调用GetExportedTypes()提供的程序集。返回这些类型的顺序非常不可靠,并且在未来的 C# 版本中甚至可能通过重新编译代码和在未来的 CLR 版本中仅通过重新启动应用程序来更改。

因此,如果实现必须按特定顺序放置在列表中,您所要做的就是对实现列表进行排序:

(serviceType, impls) => container.RegisterAll(serviceType,
    impls.OrderBy(type => [some condition]));

但是,总的来说,我会说事情的顺序无关紧要。如果它们确实重要,请仔细查看您的设计。这里可能存在一些问题。例如,您想用[SubscriberPriority]属性标记某些类的事实表明您可能缺少抽象。也许您应该给他们自己的界面并单独注册。

我总是建议做的另一件事是通过将注册列表放在复合后面来隐藏应用程序的注册列表:

public class CompositeSubscriber<T> : ISubscriber<T>
{
    private IEnumerable<ISubscriber<T>> subscribers;

    public CompositeSubscriber(
        IEnumerable<ISubstriber<T>> subscribers)
    {
        this.subscribers = subscribers;
    }

    public void Handle(T value)
    {
        foreach (var subscriber in this.subscribers)
        {
            subscriber.Handle(value);
        }
    }
}

该复合材料可以按如下方式注册:

container.RegisterSingleOpenGeneric(typeof(ISubscriber<>),
    typeof(CompositeSubscriber<>);

这种情况下,应用程序可以简单地依赖ISubscriber<T>而不是IEnumerable<ISubscriber<T>>. RegisterManyForOpenGeneric现在您可以使用组合来控制顺序,而不是使用方法的回调来控制顺序。

于 2013-02-01T09:08:48.013 回答