Register component based on parameter name on requestor in windsor - components

I have this interface for using AutoMapper:
public interface IMapper
{
object Map(object source, Type sourceType, Type destinationType);
}
Then for each type of data, I have a different mapper 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 parametter in my controller class like this:
public UsersController(IUsersRepository repo, IMapper userMapper)
{....}
I am using Windsor as the IOC for my application and the problem is that I want to register the components, so that when running in UsersController , it use the UserMapper class and if running on ProductsController it will use my ProductMapper class.
My registration code looks something along the line of 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 have done my homework on google and stackoverflow, and i know that I need to use ServicesOverride but I am still stuck on this, could anyone give me a hand please?
Thanks

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

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

Related

Using StructureMap[4.7.0] Setter Injection in my MVC5 Controller

I am trying to inject the IApplicationConfigurationSection implementation into this MVC5 Controller, so that I can have access to some of the information (various strings) from my web.config custom section in all of my views:
public class BaseController : Controller
{
public IApplicationConfigurationSection AppConfig { get; set; }
public BaseController()
{
ViewBag.AppConfig = AppConfig; // AppConfig is always null
}
}
I want to use setter injection so I don't have to clutter up my derived Controller constructors with parameters that they don't really care about.
Note: If there is a better way to inject base class dependencies, please let me know. I admit I may not be on the right track here.
In my Global.asax I load my StructureMap configurations:
private static IContainer _container;
protected void Application_Start()
{
_container = new Container();
StructureMapConfig.Configure(_container, () => Container ?? _container);
// redacted other registrations
}
My StructureMapConfig class loads my registries:
public class StructureMapConfig
{
public static void Configure(IContainer container, Func<IContainer> func)
{
DependencyResolver.SetResolver(new StructureMapDependencyResolver(func));
container.Configure(cfg =>
{
cfg.AddRegistries(new Registry[]
{
new MvcRegistry(),
// other registries redacted
});
});
}
}
My MvcRegistry provides the mapping for StructureMap:
public class MvcRegistry : Registry
{
public MvcRegistry()
{
For<BundleCollection>().Use(BundleTable.Bundles);
For<RouteCollection>().Use(RouteTable.Routes);
For<IPrincipal>().Use(() => HttpContext.Current.User);
For<IIdentity>().Use(() => HttpContext.Current.User.Identity);
For<ICurrentUser>().Use<CurrentUser>();
For<HttpSessionStateBase>()
.Use(() => new HttpSessionStateWrapper(HttpContext.Current.Session));
For<HttpContextBase>()
.Use(() => new HttpContextWrapper(HttpContext.Current));
For<HttpServerUtilityBase>()
.Use(() => new HttpServerUtilityWrapper(HttpContext.Current.Server));
For<IApplicationConfigurationSection>()
.Use(GetConfig());
Policies.SetAllProperties(p => p.OfType<IApplicationConfigurationSection>());
}
private IApplicationConfigurationSection GetConfig()
{
var config = ConfigurationManager.GetSection("application") as ApplicationConfigurationSection;
return config; // this always returns a valid instance
}
}
I have also "thrown my hands up" and tried using the [SetterProperty] attribute on the BaseController - that technique failed as well.
Despite my best efforts to find a solution, the AppConfig property in my controller's constructor is always null. I thought that
`Policies.SetAllProperties(p => p.OfType<IApplicationConfigurationSection>());`
would do the trick, but it didn't.
I have found that if I discard setter injection and go with constructor injection, it works as advertised. I'd still like to know where I'm going wrong, but I'd like to stress that I'm not a StructureMap guru - there may be a better way to avoid having to constructor-inject my base class dependencies. If you know how I should be doing this but am not, please share.
While constructor injection in this scenario appears to be the better solution to the stated problem as it follows The Explicit Dependencies Principle
Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.
The mention of only needing to access the AppConfig in your views leads me to think that this is more of an XY problem and a cross cutting concern.
It appears that the controllers themselves have no need to use the dependency so stands to reason that there is no need to be injecting them into the controller explicitly just so that the dependency is available to the View.
Consider using an action filter that can resolve the dependency and make it available to the View via the same ViewBag as the request goes through the pipeline.
public class AccessesAppConfigAttribute : ActionFilterAttribute {
public override void OnActionExecuting(ActionExecutingContext filterContext) {
var resolver = DependencyResolver.Current;
var appConfig = (IApplicationConfigurationSection)resolver.GetService(typeof(IApplicationConfigurationSection));
filterContext.Controller.ViewBag.AppConfig = appConfig;
}
}
This now makes the required information available to the views with out tight coupling of the controllers that may have a use for it. Removing the need to inject the dependency into derived classes.
Either via adorning Controller/Action with the filter attribute
[AccessesAppConfig] //available to all its actions
public class HomeController : Controller {
//[AccessesAppConfig] //Use directly if want to isolate to single action/view
public ActionResult Index() {
//...
return View();
}
}
or globally for all requests.
public class FilterConfig {
public static void RegisterGlobalFilters(GlobalFilterCollection filters) {
filters.Add(new AccessesAppConfigAttribute());
}
}
At this point it really does not matter which IoC container is used. Once the dependency resolver has been configured, Views should have access to the required information in the ViewBag

ServiceStack IOC: How to register templated class

I have the following repository classes for Redis databases:
public class RedisRepositoryBase<TRedisEntity> : IRedisRepository<TRedisEntity> where TRedisEntity : class, IRedisEntity
public class MyClassARepository : RedisRepositoryBase<MyClassA>
public class MyClassBRepository : RedisRepositoryBase<MyClassB>
public class MyClassCRepository : RedisRepositoryBase<MyClassC>
TRedisEntity is the base class of my POCOs where some common props like Id, CreationDate and others are defined. The constructor of the derived repo classes is defined as such:
public MyClassARepository(IRedisClientsManager redisManager) : base(redisManager)
{
}
Now I try to register those repositories in my AppHost class:
public override void Configure(Container container)
{
container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(connStr)); // the connection pool
// Now I do not understand how to register the repositories
container.Register<IRedisRepository<IRedisEntity>>(c => new MyClassARepository(c.Resolve<IRedisClientsManager>()); //This is wrong, get conversion error!
// ... other configuration stuff
}
Reading the ServiceStack IOC docs, I see there are many ways to register my repos but I cannot get it going....
I guess I have to register all my derived classes or is this a wrong assumption?
What is the correct syntax to register my repo classes with Func?
Many thanks!
Your MyClassARepository only implements IRedisRepository<MyClassA> so you can only do:
container.Register<IRedisRepository<MyClassA>>(c =>
new MyClassARepository(c.Resolve<IRedisClientsManager>());

Setting proper Unity Container configuration for resolving interface-class in decorator pattern

Given below are my different class declarations and how I am trying to setup unity container configuration to get a Interface to Concrete class implementation. The code currently throws either an stackoverflow exception or suggests that a interface cannot be constructed.
Please help me fix, either the class structure or the container configuration.
CodesController Class -
public class CodesController : ApiController
{
private readonly IUnitOfWorkAsync unitOfWork;
private readonly ICodeRepository repository;
public CodesController(IUnitOfWorkAsync unitOfWork, ICodeRepository codeRepository)
{
if (unitOfWork == null)
{
throw new ArgumentNullException("unitOfWork");
}
this.unitOfWork = unitOfWork;
this.repository = codeRepository;
}
//Other class level methods here
}
CodeRepository class -
public class CodeRepository : ICodeRepository
{
private readonly ICodeRepository codeRepository;
public CodeRepository(ICodeRepository repository)
{
this.codeRepository = repository;
}
public virtual async Task<IEnumerable<Code>> GetCodeAsync(string codeKey)
{ //Some implementation here}
}
ICodeRepository Interface -
public interface ICodeRepository : IRepositoryAsync<Code>
{
Task<IEnumerable<Code>> GetCodeAsync(string codeKey);
}
IRepositoryAsync Interface -
public interface IRepositoryAsync<TEntity> : IRepository<TEntity> where TEntity : class, IPersistenceHint
{
Task<bool> DeleteAsync(params object[] keyValues);
Task<bool> DeleteAsync(CancellationToken cancellationToken, params object[] keyValues);
Task<TEntity> FindAsync(params object[] keyValues);
Task<TEntity> FindAsync(CancellationToken cancellationToken, params object[] keyValues);
}
Unity Container Configuration-
container.RegisterType<IUnitOfWorkAsync, UnitOfWork>(
"test",
new TransientLifetimeManager(),
new InjectionConstructor(container.Resolve<IDataContextAsync>("test")));
container.RegisterType<ICodeRepository, CodeRepository>();
container.RegisterType<CodesController, CodesController>();
With this given configuration and class structure, based on my experimentation with container config, I get following exception -
JSON
exceptionMessage=An error occurred when trying to create a controller of type 'CodesController'. Make sure that the controller has a parameterless public constructor.
exceptionType=System.InvalidOperationException
innerException
exceptionMessage=Type '<Namespace>.Api.Controllers.CodesController' does not have a default constructor
stackTrace= at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
Please suggest, if anything is wrong here, so that I can fix the same. Already struggling many days on this.
You're injecting ICodeRepository to CodeRepository, which probably causes to stackoverflow exception, since it will keep generating ICodeRepositories. It will generate a recursive call. Somewhat like this one:
public class BaseFoo
{
public BaseFoo(BaseFoo foo){ }
}
public class Foo : BaseFoo
{
public Foo() : base(new Foo()) { }
}
And regarding the "does not have a default constructor"-exception, have you registered a DependencyResolver for Web API? See one of these questions for more detailed information how to do it:
Using Unity with Web Api 2 gives error does not have a default constructor
Unity.WebApi | Make sure that the controller has a parameterless public constructor
ASP.Net MVC 4 Web API controller dosn't work with Unity.WebApi
As a side note, you shouldn't have to register the CodesController in your unity registration.

Using LogManager.GetLogger with Unity

Given this class:
class Foo
{
readonly ILog log;
public Foo(ILog log)
{
this.log = log;
}
...
}
I'd like to configure Unity to inject ILog. That's easy:
container.RegisterInstance<ILog>(LogManager.GetLogger(typeof(XYZ)));
But I'd like to make Unity call LogManager.GetLogger with the type of the parent type being resolved.
This is close:
container.RegisterType<ILog>(new InjectionFactory((c, t, s) => LogManager.GetLogger(t)));
But t in this case is the type being resolved (ILog), not the type that the object is being resolved for (Foo).
I know I can do this:
container.RegisterType<Foo>(new InjectionFactory(c => new Foo(LogManager.GetLogger(typeof(Foo)));
But I don't want to have to add that crazy declaration every time I register an object.
I know this can be done in Autofac, and I know the Real Answer is not to use Unity in the first place, but can this be done? :)
Unity might not give you all the goodies some of the other containers offer but I have yet to find a feature you can't easily add.
var container = new UnityContainer();
container.AddNewExtension<TrackingExtension>();
container.RegisterType<ILog>(
new InjectionFactory((ctr, type, name) =>
{
var tracker = ctr.Resolve<ITracker>();
var parentType = tracker.CurrentBuildNode.Parent.BuildKey.Type;
return LogManager.GetLogger(parentType);
}));
var sut = container.Resolve<UsesLog>();
Assert.AreEqual(typeof(UsesLog), sut.Log.Type);
You can find the source code for the TrackingExtension here. Its located in the TecX.Unity project folder.
If you want a DI container to return you a logger based on the class’ type information, then put the type information into the public interface so the DI container can see it. It removes the need for any container specific override features and then it won’t matter if you are using Unity or AutoFac.
Someone that knows the log4net object model well might be able to give you a more efficient implementation, but try something like this:
using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnityLoging
{
public interface ILog<T> : log4net.ILog
{ }
public class MyLogger<T> : log4net.Core.LogImpl, ILog<T>
{
public MyLogger() : base(log4net.LogManager.GetLogger(typeof(T).Name).Logger)
{ }
}
public class ClassToLog
{
private readonly log4net.ILog log;
public ClassToLog(ILog<ClassToLog> log)
{
this.log = log;
}
public void LogMe()
{
log.Debug("Got here");
}
}
[TestClass]
public class TestClass
{
[TestMethod]
public void GenericLogRegistrationTest()
{
log4net.Config.XmlConfigurator.Configure();
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(ILog<>), typeof(MyLogger<>));
ClassToLog c = container.Resolve<ClassToLog>();
c.LogMe();
log4net.LogManager.Shutdown();
}
}
}
This seems like a very clean approach: https://github.com/roblevine/UnityLoggingExtensions

looking for a proper way to implement my generic factory

I'm struggling with implementing a factory object. Here's the context :
I've in a project a custom store. In order to read/write records, I've written this code in a POCO model/separated repository:
public class Id { /* skip for clarity*/} // My custom ID representation
public interface IId
{
Id Id { get; set; }
}
public interface IGenericRepository<T> where T : IId
{
T Get(Id objectID);
void Save(T #object);
}
public interface IContext
{
TRepository GetRepository<T, TRepository>()
where TRepository : IGenericRepository<T>
where T:IId;
IGenericRepository<T> GetRepository<T>()
where T:IId;
}
My IContext interface defines two kind of repositories.
The former is for standard objects with only get/save methods, the later allows me to define specifics methods for specific kind of objects. For example :
public interface IWebServiceLogRepository : IGenericRepository<WebServiceLog>
{
ICollection<WebServiceLog> GetOpenLogs(Id objectID);
}
And it the consuming code I can do one of this :
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID); --> specific operation
Because most of objects repository are limited to get and save operations, I've written a generic repository :
public class BaseRepository<T> : IGenericRepository<T>
where T : IId, new()
{
public virtual T Get(Id objectID){ /* provider specific */ }
public void Save(T #object) { /* provider specific */ }
}
and, for custom ones, I simply inherits the base repository :
internal class WebServiceLogRepository: BaseRepository<WebServiceLog>, IWebServiceLogRepository
{
public ICollection<WebServiceLog> GetByOpenLogsByRecordID(Id objectID)
{
/* provider specific */
}
}
Everything above is ok (at least I think it's ok). I'm now struggling to implement the MyContext class. I'm using MEF in my project for other purposes. But because MEF doesn't support (yet) generic exports, I did not find a way to reach my goal.
My context class is looking like by now :
[Export(typeof(IContext))]
public class UpdateContext : IContext
{
private System.Collections.Generic.Dictionary<Type, object> m_Implementations;
public UpdateContext()
{
m_Implementations = new System.Collections.Generic.Dictionary<Type, object>();
}
public TRepository GetRepository<T, TRepository>()
where T : IId
where TRepository : IGenericRepository<T>
{
var tType = typeof(T);
if (!m_Implementations.ContainsKey(tType))
{
/* this code is neither working nor elegant for me */
var resultType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(
(a) => a.GetTypes()
).Where((t)=>t.GetInterfaces().Contains(typeof(TRepository))).Single();
var result = (TRepository)resultType.InvokeMember("new", System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { this });
m_Implementations.Add(tType, result);
}
return (TRepository)m_Implementations[tType];
}
public IGenericRepository<T> GetRepository<T>() where T : IId
{
return GetRepository<T, IGenericRepository<T>>();
}
}
I'd appreciate a bit of help to unpuzzle my mind with this quite common scenario
Not sure if I've understood you correctly, but I think you're perhaps over complicating things. To begin with, make sure you've designed your code independent of any factory or Dependency Injection framework or composition framework.
For starters lets look at what you want your calling code to look like, this is what you said:
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID);
You don't have to agree with my naming choices below, but it indicates what I undertand from your code, you can tell me if I'm wrong. Now, I feel like the calling would be simpler like this:
RepositoryFactory.New<IRepository<Customer>>().Get(myId);
RepositoryFactory.New<IWebServiceLogRepository>().GetOpenLogs(myId);
Line 1:
Because the type here is IRepository it's clear what the return type is, and what the T type is for the base IRepository.
Line 2:
The return type here from the factory is IWebServiceLogRepository. Here you don'y need to specify the entity type, your interface logically already implements IRepository. There's no need to specify this again.
So your interface for these would look like this:
public interface IRepository<T>
{
T Get(object Id);
T Save(T object);
}
public interface IWebServiceLogRepository: IRepository<WebServiceLog>
{
List<WebServiceLog> GetOpenLogs(object Id);
}
Now I think the implementations and factory code for this would be simpler as the factory only has to know about a single type. On line 1 the type is IRepository, and in line 2, IWebServiceLogRepository.
Try that, and try rewriting your code to simply find classes that implement those types and instantiating them.
Lastly, in terms of MEF, you could carry on using that, but Castle Windsor would really make things much simpler for you, as it lets you concentrate on your architecture and code design, and its very very simple to use. You only ever reference Castle in your app startup code. The rest of your code is simply designed using the Dependency Injection pattern, which is framework agnostic.
If some of this isn't clear, let me know if you'd like me to update this answer with the implementation code of your repositories too.
UPDATE
and here's the code which resolves the implementations. You were making it a bit harder for yourself by not using the Activator class.
If you use Activator and use only one Generic parameter as I've done in the method below, you should be ok. Note the code's a bit rough but you get the idea:
public static T GetThing<T>()
{
List<Type> assemblyTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes()).ToList();
Type interfaceType = typeof(T);
if(interfaceType.IsGenericType)
{
var gens = interfaceType.GetGenericArguments();
List<Type> narrowed = assemblyTypes.Where(p => p.IsGenericType && !p.IsInterface).ToList();
var implementations = new List<Type>();
narrowed.ForEach(t=>
{
try
{
var imp = t.MakeGenericType(gens);
if(interfaceType.IsAssignableFrom(imp))
{
implementations.Add(imp);
}
}catch
{
}
});
return (T)Activator.CreateInstance(implementations.First());
}
else
{
List<Type> implementations = assemblyTypes.Where(p => interfaceType.IsAssignableFrom(p) && !p.IsInterface).ToList();
return (T)Activator.CreateInstance(implementations.First());
}
}

Resources