在windsor的请求者上注册基于参数名称的组件

tua*_*nvt 4 components castle-windsor inversion-of-control

我有这个使用AutoMapper的界面:

public interface IMapper
{
    object Map(object source, Type sourceType, Type destinationType);
}
Run Code Online (Sandbox Code Playgroud)

然后对于每种类型的数据,我有一个不同的映射器类,例如:

 public class UserMapper : IMapper
{
    static UserMapper()
    {
        Mapper.CreateMap<User, UserViewModel>();
        Mapper.CreateMap<UserViewModel, User>();
    }

    public object Map(object source, Type sourceType, Type destinationType)
    {
        return Mapper.Map(source, sourceType, destinationType);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我将IMapper作为我的控制器类中的参数之一,如下所示:

public UsersController(IUsersRepository repo, IMapper userMapper)
{....}
Run Code Online (Sandbox Code Playgroud)

我使用Windsor作为我的应用程序的IOC,问题是我想注册组件,因此当在UsersController中运行时,它使用UserMapper类,如果在ProductsController上运行,它将使用我的ProductMapper类.

我的注册码看起来像这样:

container.Register(
    Component.For<IMapper>()
             .ImplementedBy<UsersMapper>()
             .Named("usersMapper"),
    Component.For<IMapper>()
             .ImplementedBy<ProductsMapper>()
             .Named("productsMapper"),
    Component.For<ProductController>()
             .ServiceOverrides(ServiceOverride.ForKey("usersMapper").Eq("productsMapper"))
)
Run Code Online (Sandbox Code Playgroud)

我已经完成了google和stackoverflow上的功课,我知道我需要使用ServicesOverride但是我仍然坚持这个,有人能帮我一把吗?

谢谢

Mar*_*ann 8

虽然svick的解决方案对我来说是正确的(虽然我没有尝试编译它),但这种情况对于基于约定的配置来说是一个很好的例子.

让我们来介绍一下这个约定:IMapper的每个消费者都会用它的名字来表示mapper的预期角色.默认情况下,该名称将与同名的类型匹配 - 仅使用不同的大小写.

因此,构造函数参数可以像这样映射:

  • userMapper - > UserMapper
  • productMapper - > ProductMapper

在Castle Windsor,这样的配置可能如下所示:

container.Register(Classes
    .FromThisAssembly()
    .Pick()
    .WithServiceAllInterfaces()
    .WithServiceSelf());

container.Kernel.Resolver.AddSubResolver(
    new MapperConvention(container.Kernel));
Run Code Online (Sandbox Code Playgroud)

Sub Resolver(魔法真正发生的地方)看起来像这样:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)


svi*_*ick 7

此注册适用于我:

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"))
    );
Run Code Online (Sandbox Code Playgroud)