2013-07-25 2 views
3

У меня есть объект, который принимает упорядоченный список (IOrderedEnumerable) элементов, где порядок элементов важен.Список заказа Autofac как параметр

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

У меня есть несколько объектов типа IListItem.

Как я могу зарегистрировать OrderedListWorker с Autofac и гарантировать, что я получу ListItems в определенном порядке во время выполнения?

Я вижу, что заказ не гарантируется в This Post, но я не уверен, как гарантировать заказ.

+1

Почему бы не взять 'IOrderedEnumerable' если важен порядок? – neontapir

+0

Хорошая точка - я хотел использовать IList, но Autofac не смог разрешить этот тип параметра. –

+0

Как сказано, как я могу указать Autofac разрешить параметр типа IOrderedEnumerable? –

ответ

4

У меня есть решение, которое представляет собой комбинацию IOrderedEnumerable и решение ResolveOrdered<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>())); 
0

Я знаю, что это старый вопрос, но у меня была подобная проблема сегодня, и я думал, что я d поделиться своим решением.

Регистрация:

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) 
    { 
    } 
} 
Смежные вопросы