开发者

Is order of dependencies guaranteed when injecting IEnumerable<T>

I register in container services implementing IMyService.

Do I have any guarantees about their order in

container.Resolve<I开发者_开发百科Enumerable<IMyService>>

?


Just as extra help for people like me landing on this page... Here is an example how one could do it.

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 IEnumerable<TComponent> ResolveOrdered<TComponent>(this IComponentContext context)
    {
      return from m in context.Resolve<IEnumerable<Meta<TComponent>>>()
             orderby m.Metadata[OrderString]
             select m.Value;
    }
  }


No, there's no ordering guaranteed here. We've considered extensions to enable it but for now it's something to handle manually.


I don't mean to self-promote, but I have also created a package to solve this problem because I had a similar need: https://github.com/mthamil/Autofac.Extras.Ordering

It uses the IOrderedEnumerable<T> interface to declare the need for ordering.


I know this is an old post but to maintain the order of registration, can't we just use PreserveExistingDefaults() during registration?

builder.RegisterInstance(serviceInstance1).As<IService>().PreserveExistingDefaults();    
builder.RegisterInstance(serviceInstance2).As<IService>().PreserveExistingDefaults();

// services should be in the same order of registration
var services = builder.Resolve<IEnumberable<IService>>();


I didn't find any fresh information on topic and wrote a test which is as simple as (you'd better write your own):

var cb = new ContainerBuilder();
cb.RegisterType<MyClass1>().As<IInterface>();
// ...
using (var c = cb.Build())
{
    using (var l = c.BeginLifetimeScope())
    {
        var e = l.Resolve<IEnumerable<IInterface>>().ToArray();
        var c = l.Resolve<IReadOnlyCollection<IInterface>>();
        var l = l.Resolve<IReadOnlyList<IInterface>>();
        // check here, ordering is ok
    }
}

Ordering was kept for all cases I've come up with. I know it is not reliable, but I think that in the current version of Autofac (4.6.0) ordering is wisely kept.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜