Ronald Emergo Ronald Emergo - 3 months ago 13
C# Question

Unity: configure container to resolve to same type in mutliple ways

Consider these interfaces and classes

interface IWorkflowService
{
void FillContext(WFContext context, IWorkflowableEntity entity);
}

interface IDataService<Entity>
{
}

abstract class DataService<TEntity>
{
}

class EmployeeDataService : IWorkflowService, DataService<Employee>
{
}

class WorkflowHandler
{
private IUnityContainer _container;

public bool Handle(IWorklfowableEntity entity)
{
// now I want to resolve the correct IWorkflowService
// suppose entity is an employee Entity
// EmployeeDataService should be resolved
}
}

//container definition:
container.RegisterType<IDataService<employee>, EmployeeDataService>();


In the Workflhandler I want to resolve the correct IWorkflowService, which is dependent on the type of the given entity.


  1. How should I define my unity container to be able get the EmployeeDataService, based on IWorkflowService and the Employee type of my entity?

  2. How should I call this from my Handle method in Workflowhandler?



By the way: Perhaps I am misusing Unity as a service locator. If that is the case should I create my own service locator to get the correct service?

Thanks in advance for any thoughts and answers.

Answer

As I was suspecting, it is considered a malpractice to use the unity container as a service locator.

Instead, the workflowhandler class should be dependent on a factory. This is often needed when you are writing cross cutting features and use Dependecy Injection.

So instead WorkflowHandler looks like this:

class WorkflowHandler 
{
    private IWorkflowServiceFactory _wfsfactory

    public WorkflowHandler(IWorkflowServiceFactory workflowservicefactory)
    {
        _wfsfactory = workflowservicefactory;
    }

    public bool Handle(IWorklfowableEntity entity)
    {
        var svc = _wfsfactory.GetServiceByEntity(entity);
        var context = new WfContext();
        svc.FillContext(context, entity);

        //handle evaluate etc.
    }
}

And the service factory would look like this:

class WorkflowServiceFactory : IWorkflowServiceFactory
{
    private IUnityContainer _container;

    public GetServiceByEntity(IWorkflowableEntity entity)
    {
        Type t = typeof(IDataService<>);
        Type fulltype = t.MakeGenericType(new [] { entity.GetType() });

        return _container.Resolve(fulltype);
    }

}