2013-07-25 16 views
3

我有一個對象,其中的項目順序是重要的項目有序列表(IOrderedEnumerable)。Autofac排序列表作爲參數

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

我有多個對象IListItem

我該如何使用Autofac註冊OrderedListWorker,並確保我在運行時以特定順序獲取ListItems?

我看到訂單不能保證在This Post,但我不知道如何保證訂單。

+1

爲什麼不來'IOrderedEnumerable'如果順序很重要? – neontapir

+0

好點 - 我想使用IList,但Autofac無法解析該參數類型。 –

+0

這就是說,我如何指示Autofac解析IOrderedEnumerable類型的參數? –

回答

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