如何删除此设计中的重复代码?

时间:2011-09-02 09:56:02

标签: caching reflection refactoring

我有大约30个数据访问类,它们都包含带有一些参数的GetAll方法。

我在所有这些代码中的代码如下所示:

public IEnumerable<IHierarchyDivisionDailyResult> GetAll(short masterId, DateTime startDate, short gbuId)
    {
        var cacheKey = this.Cache.CreateCacheKey(this, masterId, startDate, gbuId);

        var result = this.Cache.GetList<IHierarchyDivisionDailyResult>(cacheKey);

        if (result != null) return result;

        lock (LockObject)
        {
            result = this.Cache.GetList<IHierarchyDivisionDailyResult>(cacheKey);

            if (result != null) return result;

            using (var dataContext = OscaDataContext.CreateWithCustomTimeOut())
            {
                result = dataContext.HierarchyDivisionDaily(masterId, startDate, gbuId).ToList();
                this.Cache.Add(cacheKey, result);
            }
        }

        return result;
    }

我想重构代码,以便删除重复的代码。怎么可能?

每个实现中的常见/不同之处是:

  • CreateCacheKey始终获取所有输入参数
  • Cache.GetList - 虽然类型可能不同
  • GetAll方法的返回类型在每个实现中都是不同的
  • 如上所述,锁定存在于所有这些中
  • 始终按上述方法创建dataContext对象
  • dataContext.Entity(...)也不同

我认为一个可能的选择是使用Reflection来找出输入参数和输出类型,然后我将能够合并大部分代码,但是反射方法的性能不会很好我读过

能够为方法添加“缓存”属性以便自动缓存结果的理想是什么!



[Cache]
public IEnumerable GetAll(short masterId, DateTime startDate, short gbuId)
 {
    using (var dataContext = OscaDataContext.CreateWithCustomTimeOut())
    {
        return dataContext.HierarchyDivisionDaily(masterId, startDate, gbuId).ToList();
    }
 }

您怎么看?

谢谢,

1 个答案:

答案 0 :(得分:0)

如果我是你,我会创建一个抽象基类,它有一个像这样的通用GetAll方法..

public abstract class DataAccessBase<T> where T : VehicleBase
{

    public virtual T GetAll(short masterId, DateTime startDate, short gbuId)
    {
        ...
    }

}

然后你可以创建这个的具体实现..

public class CarDataAccess : DataAccessBase<Car>
{

    public override Car GetAll(short masterId, DateTime startDate, short gbuId)
    {
        ...
    }

}

public class VanDataAccess : DataAccessBase<Van>
{

    public override Van GetAll(short masterId, DateTime startDate, short gbuId)
    {
        ...
    }

}

在基类中,您可以放置​​所有常见的行为,然后在重写方法中,您可以放置​​特定于您正在处理的特定类型的任何内容。

这不是使用汽车和货车,而是一个更具体的代码示例..

public abstract class DataAccessBase<T>
{

    public virtual IEnumerable<T> GetAll(short masterId, DateTime startDate, short gbuId)
    {
        var cacheKey = this.Cache.CreateCacheKey(this, masterId, startDate, gbuId);

        List<T> result = this.Cache.GetList<T>(cacheKey);

        if (result != null) return result;

        lock (LockObject)
        {
            result = this.Cache.GetList<T>(cacheKey);

            if (result != null) return result;

            using (var dataContext = OscaDataContext.CreateWithCustomTimeOut())
            {
                result = this.GetResult(dataContext, masterId, startDate, gbuId);
                this.Cache.Add(cacheKey, result);
            }
        }

        return result;
    }

    protected abstract List<T> GetResult(var dataContext, short masterId, DateTime startDate, short gbuId);
}


public class HierarchyDivisionDailyResultDataAccess : DataAccessBase<IHierarchyDivisionDailyResult>
{

    public virtual IEnumerable<IHierarchyDivisionDailyResult> GetAll(short masterId, DateTime startDate, short gbuId)
    {
        return base.GetAll(masterId, startDate, gbuId);
    }

    protected override List<IHierarchyDivisionDailyResult> GetResult(var dataContext, short masterId, DateTime startDate, short gbuId)
    {
        return dataContext.HierarchyDivisionDaily(masterId, startDate, gbuId).ToList();
    }
}