Autofac有序列表作为参数

时间:2013-07-25 16:21:35

标签: c# autofac

我有一个对象,它接受一个有序的List(IOrderedEnumerable)项,其中项的顺序很重要。

public class OrderedListWorker : IListWorker
{
    private OrderedListWorker(IOrderedEnumerable<IListItem> orderedListItems)
    {
        foreach (var listItem in orderedListItems)
            listItem.DoSomethingWhereOrderMatters();
    }
}

我有多个IListItem类型的对象。

如何向Autofac注册OrderedListWorker并确保在运行时以特定顺序获取ListItem?

我发现This Post无法保证订单,但我不确定如何保证订单。

2 个答案:

答案 0 :(得分:4)

我有一个解决方案,即我在上面链接的帖子中IOrderedEnumerableResolveOrdered<TComponent>解决方案的组合。

使用AutofacExtensions类:

public static class AutofacExtensions
{
    private const string OrderString = "WithOrderTag";
    private static int _orderCounter;

    public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle>
        WithOrder<TLimit, TActivatorData, TRegistrationStyle>(
        this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> registrationBuilder)
    {
        return registrationBuilder.WithMetadata(OrderString, Interlocked.Increment(ref _orderCounter));
    }

    public static IOrderedEnumerable<TComponent> ResolveOrdered<TComponent>(this IComponentContext context)
    {
        return
            context.Resolve<IEnumerable<Meta<TComponent>>>()
                   .OrderBy(m => m.Metadata[OrderString])
                   .Select(m => m.Value).OrderBy(c => true);
    }
}

我可以按如下方式指定我的注册:

builder.RegisterType<ListItemA>().As<IListItem>().WithOrder();
builder.RegisterType<ListItemB>().As<IListItem>().WithOrder();
builder.RegisterType<OrderedListWorker>()
                   .As<IListWorker>()
                   .WithParameter(
                       new ResolvedParameter(
                           (info, context) => true,
                           (info, context) => context.ResolveOrdered<IListItem>()));

答案 1 :(得分:0)

我知道这是一个老问题,但今天我遇到了类似的问题,我想我会分享我的解决方案。

注册:

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterOrdered<IListItem>(scope =>
    {
        scope.Register<Item1>();
        scope.Register<Item2>();
    });
}

基础设施:

public static class AutofacExtensions
{
    public static void RegisterOrdered<TService>(this ContainerBuilder builder, Action<IOrderedScope> setter)
    {
        var scope = new OrderedScope<TService>(builder);
        setter(scope);
        builder.Register(ctx => ctx.Resolve<IEnumerable<TService>>().OrderBy(x => scope.OrderedTypes[x.GetType()]));
    }

    private class OrderedScope<TService> : IOrderedScope
    {
        private readonly ContainerBuilder _builder;
        private int _order = 1;

        public OrderedScope(ContainerBuilder builder)
        {
            _builder = builder;
            OrderedTypes = new Dictionary<Type, int>();
        }

        public Dictionary<Type, int> OrderedTypes {get;}

        public IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle> Register<T>()
        {
            OrderedTypes.Add(typeof(T), _order++);
            return _builder.RegisterType<T>().As<TService>();
        }
    }
}

public interface IOrderedScope
{
    IRegistrationBuilder<T, ConcreteReflectionActivatorData, SingleRegistrationStyle> Register<T>();
}

用法:

public class OrderedListWorker : IListWorker
{
    public OrderedListWorker(IOrderedEnumerable<IListItem> items)
    {
    }
}