让我的工作单位......好吧,工作!

时间:2011-04-07 20:32:23

标签: unit-of-work

我正在实施工作单位。这是我界面的一部分:

public interface IUnitOfWork
{
    void Add(object entity);
    void Update(object entity);
    void Delete(object entity);        
    void Commit();
}

从我在网上或书中找到的例子来看,工作单元被迫使用“对象”类型,因为我们可以向uow添加任何“类型”的实体。

在提交Commit()之前没什么大不了的。当我提交时,给定一个实体类型,我需要根据实体类型查找存储库,然后调用相应的操作。

例如,我有一个名为Expert

的实体类型
public class Expert
{
    public object ID { get; set; }
    public string Name { get; set; }
}

Expert有一个名为ExpertRepository的存储库。我的应用程序中的所有存储库都实现了IRepository:

public interface IRepository<T>
{
    void Create(T item);
    void Update(T item);
    void Delete(T item);
}

public class ExpertRepository : IRepository<Expert>
{        
    public void Create(Expert item)
    {
        //TSQL to insert
    }

    public void Update(Expert item)
    {
        //TSQL to update
    }

    public void Delete(Expert item)
    {
        //TSQL to delete
    }
}

我想澄清一下,我的存储库不负责从我的uow添加,更新或删除实体,相反,我将消费代码(可能在服务层中)新的uow,然后直接添加到它...当我的应用程序准备就绪时,它将调用Commit()。

这有两件事。它允许我的消费代码决定它希望实体如何持久化。消费代码可以直接在Repository上调用.Create()来持久保存实体,或者消费代码可以启动uow,在uow上调用.Add(),然后调用.Commit()时, uow将遍历所有实体,并通过操作类型(添加,更新删除),新建相应的存储库,并执行TSQL代码。

现在,我遇到的问题是当我在我的uow中循环添加,更新和删除集合时。这是一段代码:

public void Commit()
{
using (TransactionScope tx = new TransactionScope())
    {
        try
        {
            foreach (object item in addedItems)
            {
                if (item.GetType() == typeof(Expert))
                {
                    IRepository<Expert> repository = new ExpertRepository();
                    repository.Create((Expert)item);
                }
            }
        }
    }
}

我必须通过item变量解析对象集合中的内容的实体类型。然后我需要新建该实体的Repository(也为IRepository接口提供正确的类型),然后调用.Create()。

这一切都很好,但是我不希望对每个可能的实体,实体的接口以及坐在我的uow中的实体的存储库进行这些条件检查。那非常糟糕。

我知道IoC容器可以在这里提供帮助(例如Unity),但是有没有可以在运行时解析泛型类型的IoC容器?我问,b / c IRepository需要正确输入,才能成为保存给定实体存储库实例的var。

我在这里做了一些设计决定,例如使用存储库进行强类型处理,而不是UOW。例如,我不希望.Create()方法位于一个采用类型对象的存储库,特别是。因为我的存储库与我的实体(Expert,ExpertRepository)有一对一的关系。

我还决定,由于大多数存储库调用都是相同的,我不希望每个存储库都有一个接口(也就是说,ExpertRepository实现了IExpertRepository)。这没有意义,我认为在这里使用泛型就是答案。

但这一切都归结为我的问题。我如何得到正确实现它所需要的东西。

任何有正确方向的建议或指示都将受到赞赏。

谢谢!

1 个答案:

答案 0 :(得分:1)

IoC是要走的路。其中一些支持开放式泛型。我们来看StructureMap as an example。您需要具有与此类似的注册码:

// default implementation
x.For(typeof(IRepository<>)).Use(typeof(DefaultRepository<>)); 
// specific implementations
x.For<IRepository<Expert>>().Use<ExpertRepository>(); 

然后,您的Commit方法可以向容器询问给定类型的实现:

_container.ForGenericType(typeof(IRepository<>))
                .WithParameters(item.GetType())
                .GetInstanceAs<IRepository>();

(您需要使用非通用的IRepository接口来满足Commit方法的需求,但我相信在实施方式不同时也没问题。