views:

507

answers:

1

I have this wcf method

Profile GetProfileInfo(string profileType, string profileName)

and a business rule:

if profileType is "A" read from database.

if profileType is "B" read from xml file.

The question is: how to implement it using a dependency injection container?

Mark Seemann author of book "Dependency injection in .net" Suggest me using abstract factory. Now i search an example :)

+5  A: 

Let's first assume that you have an IProfileRepository something like this:

public interface IProfileRepository
{
     Profile GetProfile(string profileName);
}

as well as two implementations: DatabaseProfileRepository and XmlProfileRepository. The issue is that you would like to pick the correct one based on the value of profileType.

You can do this by introducing this Abstract Factory:

public interface IProfileRepositoryFactory
{
    IProfileRepository Create(string profileType);
}

Assuming that the IProfileRepositoryFactory has been injected into the service implementation, you can now implement the GetProfileInfo method like this:

public Profile GetProfileInfo(string profileType, string profileName)
{
    return this.factory.Create(profileType).GetProfile(profileName);
}

A concrete implementation of IProfileRepositoryFactory might look like this:

public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
    private readonly IProfileRepository aRepository;
    private readonly IProfileRepository bRepository;

    public ProfileRepositoryFactory(IProfileRepository aRepository,
        IProfileRepository bRepository)
    {
        if(aRepository == null)
        {
            throw new ArgumentNullException("aRepository");
        }
        if(bRepository == null)
        {
            throw new ArgumentNullException("bRepository");
        }

        this.aRepository = aRepository;
        this.bRepository = bRepository;
    }

    public IProfileRepository Create(string profileType)
    {
        if(profileType == "A")
        {
            return this.aRepository;
        }
        if(profileType == "B")
        {
            return this.bRepository;
        }

        // and so on...
    }
}

Now you just need to get your DI Container of choice to wire it all up for you...

Mark Seemann
Those sequential `ifs` could be replaced be a faster/more legible `switch/case`. And `profileType` really should be an enumeration, not an arbitrary string. Other than that it's a great answer. :)
Aaronaught
Yes, no disagreement there, but I just went with the API given by the OP :)
Mark Seemann
In which way it can change if i don't know at compile time the number of repositories?And if my wcf have only dependencies with log library and these repositories, where is the best DI Container choice?is MEF a good choiche in this scenario?
tartafe
just a little clarification:i'll use the lo library for logging custom message in method and not for tracing
tartafe
You can configure most DI Containers using XML configuration, which is a good option when you don't know all the repositories at compile time, but MEF might also be a good option in this case.
Mark Seemann