1

我即将学习 IoC 和依赖注入。我想知道我是否理解正确的原理和模式。

我尝试实现 UnitOfWork / Repository Pattern。我想要两个用于单元测试的存储库类的实现,并且我希望 UnitOfWork “决定”要实例化哪个具体实现(在 Unity 的帮助下)。

例子

IUserRepository 接口

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

使用真实数据的存储库实现

public class UserRepository : IUserRepository
{

    private MyDbContext db;

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

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

FakeRepository 实现

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

}

我使用 Unity 的 UnitOfWork 实现

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

现在,当我调用new UnitOfWork()它时,它会给我“UnitOfWork with RealData”实现。如果我打电话给new UnitOfWork(fake: true)它,它会给我“UnitOfWork with Fake Data”。到目前为止,一切都很好。但这是应该使用 Unity 和 DI 的方式吗?如果我的应用程序增长到 30 个存储库,我最终会定义大型“If/else”块,对吗?想象一下,想要添加更多的数据存储,如 XML 或 WCF 作为数据源。如果我继续像上面那样使用它,我最终会得到一个非常复杂和崩溃的 UnitOfWork 类。

首先:我不确定我是否理解 DI 和 Unity,因为它是要使用的。如果我理解正确:使用一个可以为我提供正确类型的 UnitOfWork 的工厂会更好吗?

非常欢迎任何帮助或提示。

谢谢,

马策

4

1 回答 1

1

我会像你对存储库所做的那样分离工作单元:一个 IUnitOfWork 接口和用于伪造的具体类和实体框架工作单元。您现在拥有的工作单元违反了单一职责原则,因为它具有多种职责:

  • 将保存调用传递给实体框架工作单元
  • 确定工作单​​元是假的还是真的
  • 在 Unity 容器上注册存储库

如果您有一个单独的实体框架工作单元,则不需要容器来解析存储库,但您可以使它们成为您在构造函数中初始化的成员变量。您只需在容器上注册正确的工作单元。

于 2012-04-04T08:32:17.760 回答