Register component based on parameter name of requestor in windsor

I have this interface to use AutoMapper:

public interface IMapper { object Map(object source, Type sourceType, Type destinationType); } 

Then for each data type I have a different mapping class, for example:

  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); } } 

Then I have IMapper as one of the parameters in my controller class, for example:

 public UsersController(IUsersRepository repo, IMapper userMapper) {....} 

I use Windsor as IOC for my application, and the problem is that I want to register the components, so when I run it in UserController it uses the UserMapper class, and if it runs on ProductController, it will use my ProductMapper class.

My registration code looks something like this:

 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")) ) 

I did my homework on google and stackoverflow and I know that I need to use ServiceOverride, but I still stick to this, can anyone give me a hand?

thanks

+4
source share
2 answers

Although the svick solution looks right to me (I have not tried to compile it yet), this script is a great example for a legend based configuration .

We introduce this agreement: each IMapper consumer will indicate the intended role of the converter by its name. By default, this name will be mapped to the type of the same name - only to a different enclosure.

So, constructor parameters can be displayed as follows:

  • userMapper -> UserMapper
  • productMapper → ProductMapper

In Castle Windsor, this 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); } } 
+8
source

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")) ); 
+7
source

Source: https://habr.com/ru/post/1397169/


All Articles