Get a list of all registered objects implementing a certain interface

前端 未结 6 1885
失恋的感觉
失恋的感觉 2020-12-05 05:23

Consider the following

builder.Register(c => new A());
builder.Register(c => new B());
builder.Register(c => new C());

B

相关标签:
6条回答
  • 2020-12-05 06:00

    I needed to resolve based on some context. So slight variation...

     builder.RegisterAssemblyTypes(Assembly.GetAssembly(typeof(ISomeStrategy)))
       .Where(t => typeof(ISomeStrategy).IsAssignableFrom(t))
       .AsSelf();
    
     builder.Register<Func<SomeEnum, ISomeStrategy>>(c =>
     {
        var types = c.ComponentRegistry.Registrations
          .Where(r => typeof(ISomeStrategy).IsAssignableFrom(r.Activator.LimitType))
          .Select(r => r.Activator.LimitType);
    
        ISomeStrategy[] lst = types.Select(t => c.Resolve(t) as ISomeStrategy).ToArray();
    
        return (someEnum) =>
        {
          return lst.FirstOrDefault(x => x.CanProcess(someEnum));
        };
     });
    

    Then for your class using the strategy

     public SomeProvider(Func<SomeType, ISomeStrategy> someFactory)
     {
        _someFactory = someFactory;
     }
    
     public void DoSomething(SomeType someType)
     {
        var strategy = _someFactory(someType);
        strategy.DoIt();
     }
    
    0 讨论(0)
  • 2020-12-05 06:12

    Here is how I did it.

    var l = Container.ComponentRegistry.Registrations
              .SelectMany(x => x.Services)
              .OfType<IServiceWithType>()
              .Where(x => 
                     x.ServiceType.GetInterface(typeof(ISomeInterface).Name) != null)
              .Select(c => (ISomeInterface) c.ServiceType);
    
    0 讨论(0)
  • 2020-12-05 06:15

    If you have

    container.Register(c => new A()).As<ISomeInterface>();
    container.Register(c => new B()).As<ISomeInterface>();
    

    Then when you do

    var classes = container.Resolve<IEnumerable<ISomeInterface>>();
    

    You will get a variable that is a list of ISomeInterface, containing A and B

    0 讨论(0)
  • 2020-12-05 06:23

    I was looking for a similar solution for registrations done as follows:

    builder.RegisterType<Bamboo>().As<IExoticTree>();
    // and/or
    builder.RegisterType<SolidOak>().Keyed<IMountainTree>(key);
    

    where IExoticTree and IMountainTree inherit from a common ITree interface.

    With those, the service type (e.g. registered interface) is different from the LimitType and hence, the proposed solution is not applicable.

    I got inspired by the accepted solution to manage these as well with the following code:

    IEnumerable<ITree> instances = scope.ComponentRegistry.Registrations
                                                          .Where(r => typeof(ITree).IsAssignableFrom(r.Activator.LimitType))
                                                          .Select(r => r.Services.First())
                                                          .Select(s => scope.ResolveService(s) as ITree)
                                                          .Distinct();
    

    Hope it helps someone ^^

    0 讨论(0)
  • 2020-12-05 06:24

    Clarification for any one searching this with regards to Inherited Class

    Ex :

        public static IEnumerable<Type> GetTypesInherit<T>(this Assembly assembly)
        {
            var types = assembly.GetTypes()
                .Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(T)))
                .ToList();
    
            return types;
        }
    

    Installer :

        public static IContainer Install()
        {
            var builder = new ContainerBuilder();
            var executingAssembly = Assembly.GetExecutingAssembly();
    
            var testScreens = executingAssembly.GetTypesInherit<TestScreen>();
            foreach (var testScreen in testScreens)
            {                   
                builder.RegisterType(testScreen).As<TestScreen>();
            }
    
            var container = builder.Build();
            return container;
        }
    

    Usage (Implicit) :

      public class MainViewModel(IEnumerable<TestScreen> testScreens) 
      {}
    
    0 讨论(0)
  • 2020-12-05 06:26

    Just tried this, works and does not depend on lifetime context:

    Enumerate types using Activator instead

    var types = con.ComponentRegistry.Registrations
         .Where(r => typeof(ISomeInterface).IsAssignableFrom(r.Activator.LimitType))
         .Select(r => r.Activator.LimitType);
    

    Then to resolve:

    IEnumerable<ISomeInterface> lst = types.Select(t => con.Resolve(t) as ISomeInterface);
    
    0 讨论(0)
提交回复
热议问题