Register component based on parameter name on requestor in windsor

后端 未结 2 1201
傲寒
傲寒 2020-12-21 04:26

I have this interface for using AutoMapper:

public interface IMapper
{
    object Map(object source, Type sourceType         


        
相关标签:
2条回答
  • 2020-12-21 05:09

    This registration works for me:

    container.Register(
        Component.For<IMapper>()
            .ImplementedBy<UserMapper>()
            .Named("userMapper"),
        Component.For<IMapper>()
            .ImplementedBy<ProductMapper>()
            .Named("productMapper"),
        Component.For<UsersController>()
            .ServiceOverrides(ServiceOverride.ForKey<IMapper>().Eq("userMapper")),
        Component.For<ProductsController>()
            .ServiceOverrides(ServiceOverride.ForKey<IMapper>().Eq("productMapper"))
        );
    
    0 讨论(0)
  • 2020-12-21 05:19

    While svick's solution looks correct to me (I haven't attempted to compile it, though), this scenario is an excellent case for convention-based configuration.

    Let's introduce this convention: Each consumer of IMapper will signal the intended role of the mapper by its name. By default, that name will be matched with a type of the same name - only with different casing.

    So, constructor parameters could be mapped like this:

    • userMapper -> UserMapper
    • productMapper -> ProductMapper

    In Castle Windsor, such a configuration might look like this:

    container.Register(Classes
        .FromThisAssembly()
        .Pick()
        .WithServiceAllInterfaces()
        .WithServiceSelf());
    
    container.Kernel.Resolver.AddSubResolver(
        new MapperConvention(container.Kernel));
    

    And the Sub Resolver (where the magic really happens) looks like this:

    public class MapperConvention : ISubDependencyResolver
    {
        private readonly IKernel kernel;
    
        public MapperConvention(IKernel kernel)
        {
            this.kernel = kernel;
        }
    
        public bool CanResolve(CreationContext context,
            ISubDependencyResolver contextHandlerResolver,
            ComponentModel model,
            DependencyModel dependency)
        {
            return typeof(IMapper).IsAssignableFrom(dependency.TargetType);
        }
    
        public object Resolve(CreationContext context,
            ISubDependencyResolver contextHandlerResolver,
            ComponentModel model,
            DependencyModel dependency)
        {
            var representativeMapperType = typeof(UserMapper);
            var concreteMapperType = representativeMapperType.Assembly
                .GetExportedTypes()
                .Where(t => 
                    t.Name.Equals(dependency.DependencyKey,
                        StringComparison.OrdinalIgnoreCase))
                .Single();
            return this.kernel.Resolve(concreteMapperType);
        }
    }
    
    0 讨论(0)
提交回复
热议问题