1

IRepository<T>インタフェース、NewsRepositoryクラス、Newsエンティティを持つことで、私のレポジトリパターンの実装がほぼ完了しました。私が遭遇した問題は、一般的なメソッドをベースリポジトリクラスに抽象化しようとすることでした。インタフェース、ベース、コンクリートによるリポジトリパターンの実装方法

特定のLinq式が含まれているため、NewsRepositoryのGetメソッドを抽象化する方法が見つかりませんでした。

私の質問はです:

1)どのように私はpublic T Get(int id)方法は、基本クラスに抽象してくださいますか?私がこれまで行ってきた唯一の方法は、intの代わりにExpression<Func<T,bool>>を渡すことですが、各サブクラスが依然としてそれぞれの場合にほぼ同じ式を渡す必要があるため、共通の振舞いを実際に抽象化しませんすなわちn => n.id == id

2)サブクラスのGetViolationsメソッドとmapメソッドをUpdateメソッドの基底クラスに渡すにはどうすればよいですか?私は、ソリューションがおそらく代理人を使用していると想像しますが、コンパイルする構文を取得できませんでした

これはコードの単純化されたセットです - 実際は私は更新だけでなく更新ここに表示されます。

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
  1. それは本当にlayer supertype for entitiesを持っているのに役立ちます。彼らはIdプロパティを共有します。あなたはid proeprtyを表現する表現を扱う必要はありません、あなたはそれが何であるかを知るだけです。

  2. template method pattern。このパターンでは、ベースUpdateはヘルパーメソッドを呼び出すすべての作業を順番に行い、派生クラスは保護された抽象ヘルパーメソッドを実装します。

2
  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

も参照してください。
関連する問題