我几乎已经完成了我的存储库模式的实现 IRepository<T> 接口,一个 NewsRepository 类和一个 News 实体。我遇到的问题是尝试将通用方法抽象为基本存储库类。

我找不到一种方法来抽象 Get 方法 NewsRepository 因为它包含特定的 Linq 表达式。

我的问题是:

1) 我如何抽象为基类 public T Get(int id) 请问方法?到目前为止我做到的唯一方法是通过 Expression<Func<T,bool>> 而不是 int ,但是这种 deosn 并没有真正抽象出常见的行为,因为每个子类仍然需要传递一个在每种情况下几乎相同的表达式,即 n => n.id == id.

2) 如何将子类 GetViolations 和映射方法传递到 Update 方法的基类中?我想解决方案可能是使用委托,但我无法编译语法

这是一组简化的代码 - 实际上,我有一个 Save 方法,它执行更新和插入操作,而不仅仅是此处显示的更新。

public interface IRepository<T>
{
    T Get(int id);
    void Update(T item);
}

public class NewsRepository : IRepository<News>
{
    private Table<News> _newsTable;
    public NewsRepository(string connectionString)
    {
        _newsTable = new DataContext(connectionString).GetTable<News>();
    }

    public News Get(int id)
    {
        return _newsTable.SingleOrDefault(n => n.NewsId == id);
    }

    public void Update(News item)
    {
        var errors = item.GetRuleViolations();
        if (errors.Count > 0)
            throw new RuleException(errors);

        News dbNews = _newsTable.SingleOrDefault(n => n.NewsId == item.NewsId);
        map(dbNews, item);

        _newsTable.Context.SubmitChanges();
    }

    private void map(News dbNews, News news)
    {
        dbNews.Title = news.Title;
        dbNews.Article = news.Article;
    }
}

public class Repository<T> where T : class
{
    protected Table<T> _table;

    public Repository(Table<T> t)
    {
        _table = t;
    }

    //How do i do this??! - This doesn't compile due to T no having a NewsId
    public T Get(int id)
    {
    return _table.SingleOrDefault(n => n.NewsId == id);
    }

    //This seems to be a solution, but it's not really abstracting common behaviour as each
    //sub-class will still need to pass in the same linq expression...
    public T Get(Expression<Func<T,bool>> ex)
    {
        return _table.SingleOrDefault(ex);
    }

    public void Update(T item)
    {
        //How is it possible to pass in the GetRuleViolations and map functions to this method?
        var errors = item.GetRuleViolations();
        if (errors.Count > 0)
            throw new RuleException(errors);

        T dbNews = _table.SingleOrDefault(n => n.NewsId == item.NewsId);
        map(dbNews, item);

        _table.Context.SubmitChanges();
    }
}
有帮助吗?

解决方案

  1. 拥有一个确实有帮助的 实体的层超类型. 。他们将共享一个 Id 属性。您不必处理表示 id 属性的表达式,您只需知道它是什么即可。

  2. 模板方法模式. 。在此模式中,您的基本 Update 会按顺序调用帮助器方法执行所有工作,并且您的派生类实现这些受保护的抽象帮助器方法。

其他提示

  1. L2S 既不支持层超类型,也不支持在查询中使用接口成员,这使得重用变得相当困难。一种选择是动态构建表达式树。这有点混乱,但是如果将其隔离到基类存储库中,那就没那么糟糕了。

这是一个例子:

public interface IEntity
{
    int Id { get; }
}

public partial class News : IEntity
{
}

public class Repository<T> where T : class, IEntity
{

    private readonly DataContext _db;

    public Repository(DataContext db)
    {
        _db = db;
    }

    public T Get(int id)
    {
        Expression<Func<T, bool>> hasId = HasId(id);
        return _db.GetTable<T>().Single(hasId);
    }

    // entity => entity.Id == id;   
    private Expression<Func<T, bool>> HasId(int id)
    {
        ParameterExpression entityParameter = Expression.Parameter(typeof (T), "entity");
        return Expression.Lambda<Func<T, bool>>(
            Expression.Equal(
                Expression.Property(entityParameter, "Id"),
                Expression.Constant(id)
                ),
            new[] {entityParameter}
            );
    }
}

也可以看看 http://msdn.microsoft.com/en-us/library/bb397951.aspx

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top