am i using dependency incection with unity the right way?

Go To StackoverFlow.com

1

i am about to learn IoC and Dependency Injection. And i am wondering if i understood the priciple an the pattern right.

I try to implement a UnitOfWork / Repository Pattern. I want two implementations of my Repository Classes for Unit Testing, and i want the UnitOfWork to "decide" which Concrete Implementation to instantiate (with the Help of Unity).

Example

The IUserRepository Interface

public interface IUserRepository
{
    List<User> getAll();       
}

The Repository Implementation using real data

public class UserRepository : IUserRepository
{

    private MyDbContext db;

    public UserRepository(MyDbContext db)
    {
        this.db = db;
    }

    public List<DomainModel.User> getAll()
    {
        return db.Users.ToList();
    }
}

The FakeRepository Implementation

public class FakeUserRepository : IUserRepository
{
    private List<User> userSet;

    public FakeUserRepository()
    {
        // Fake Data
        userSet = new List<User>();
        userSet.Add(new User { Username = "john", Active = true, EMail = "john@ann.net", Password = "supersecret" });
        userSet.Add(new User { Username = "ashley", Active = true, EMail = "ashley@ann.net", Password = "supersecret" });
        userSet.Add(new User { Username = "kaidan", Active = true, EMail = "kaidan@ann.net", Password = "supersecret" });
        userSet.Add(new User { Username = "tali", Active = true, EMail = "tali@ann.net", Password = "supersecret" });

    }

    public List<DomainModel.User> getAll()
    {
        return userSet;
    }

}

My UnitOfWork Implementation using Unity

// To Keep it simple, i skipped the IDisposable part ;)

public class UnitOfWork
{
    MyDbContext db;
    private IUserRepository userRepository;
    UnityContainer container = new UnityContainer();
    public UnitOfWork(bool fake = false)
    {
        if (fake)
        {
            container.RegisterType<IUserRepository, FakeUserRepository>();
        }
        else
        {
            db =  = new MyDbContext();
            container.RegisterType<IUserRepository, UserRepository>(new InjectionConstructor(db));
        }
    }


    public IUserRepository UserRepository
    {
        get
        {
            if (userRepository == null)
            {
                userRepository = container.Resolve<IUserRepository>();
            }
            return userRepository;
        }
    }

    public void Save()
    {
        db.SaveChanges();
    }
}

Now when i call new UnitOfWork() it will give me the "UnitOfWork with RealData" Implementation. If i call new UnitOfWork(fake: true) it will give me the "UnitOfWork with Fake Data". So far so good. But is this the way Unity and DI should be used? If my Application grows to say 30 Repositories do i end up defining large "If/else" Blocks, right? And imagine a want do add more data stores like XML or WCF as Source for Data. If i continue to use it like above, i will end up with a very complex and blown UnitOfWork Class.

First: I am not sure if i understood DI and Unity as it's ment to be used. If i understood it right: would it be better to use a Factory that gives me the right Type of UnitOfWork?

Any Help or tip is very welcome.

Thanks,

Matze

2012-04-04 08:19
by Matze-Berlin
Your UnitOfWork should not know which repository it needs. It should just have the correct type injected into it - Richard Dalton 2012-04-04 08:30
You've got test code in your production code (if (fake)). Prevent doing that - Steven 2012-04-04 08:32
This article might give you some ideas - Steven 2012-04-04 08:32
@RichardD : Yes, I've already thought that. Since i am new to this topic: could you give me a hint, example or link on how can achieve that behavior - Matze-Berlin 2012-04-04 08:36


1

I would separate the Unit of Work like you did with the repositories: an IUnitOfWork interface and concrete classes for the fake and the Entity Framework Unit of Work. The Unit of Work you have now violates the Single Responsibility Principle because it has multiple responsibilities:

  • Pass the save call to the Entity Framework Unit of Work
  • Determining if the Unit of Work is fake or real
  • Registering the repositories on the Unity container

If you have a separate Unit of Work for Entity Framework, you won't need the container to resolve the repositories from, but you can make them member variables which you initialize in your constructor. You only have to register the correct Unit of Work on the container.

2012-04-04 08:32
by Jesse van Assen
Yes you are right. I think its the best way to deal with the problem. Having different UnitOfWork Classen makes most sense - Matze-Berlin 2012-04-04 09:13
Ads