Resolve type without creating object

前端 未结 2 606
攒了一身酷
攒了一身酷 2021-02-08 17:41

Here\'s my problem: I have a container where I register concrete types as interfaces.

builder.RegisterType().As

        
2条回答
  •  北荒
    北荒 (楼主)
    2021-02-08 18:21

    You can very nicely encapsulate @Danielg's method so that you can let Autofac inject the type-list into a construtor. It requires you to implement the IRegistrationSource.

    In my case I wanted to get all registered types derived from IConsoleCommand like that:

    public Help(TypeList commands)
    {
        _commands = commands;
    }
    

    I used a simple DTO-List to carry the types and the T that I wanted to resolve them for:

    public class TypeList : List
    {
        public TypeList(IEnumerable types) : base(types)
        {
        }
    }
    

    The actual registration source is implemented as following where the from the TypeList is used to match the type of interface that is registered and that we want to retrieve.

    internal class TypeListSource : IRegistrationSource
    {
        public IEnumerable RegistrationsFor(Service service, Func> registrationAccessor)
        {
            if (service is IServiceWithType swt && typeof(TypeList).IsAssignableFrom(swt.ServiceType))
            {
                var registration =
                    new ComponentRegistration(
                        id: Guid.NewGuid(),
                        activator: new DelegateActivator(swt.ServiceType, (context, p) =>
                        {
                            var types =
                                context
                                    .ComponentRegistry
                                    .RegistrationsFor(new TypedService(typeof(T)))
                                    .Select(r => r.Activator)
                                    .OfType()
                                    .Select(activator => activator.LimitType);
                            return new TypeList(types);
                        }),
                        services: new[] {service},
                        lifetime: new CurrentScopeLifetime(),
                        sharing: InstanceSharing.None,
                        ownership: InstanceOwnership.OwnedByLifetimeScope,
                        metadata: new Dictionary()
                    );
                return new IComponentRegistration[] {registration};
            }
            // It's not a request for the base handler type, so skip it.
            else
            {
                return Enumerable.Empty();
            }
        }
    
        public bool IsAdapterForIndividualComponents => false;
    }
    

    Finally you have to add it to the builder with:

    builder.RegisterSource(new TypeListSource());
    

    Now Autofac can resolve the types with dependency injection.

提交回复
热议问题