2011-05-11 18 views
2

我已經成功地設置了一個列出團隊的簡單mvc應用程序。我正在使用Ninject根據控制器注入適當的存儲庫(感謝堆棧溢出;)。除了存儲庫代碼看起來完全相同之外,所有這些看起來都不錯。我知道那是錯誤的。所以我的TeamRepository有兩個類(現在)。如何避免重複代碼的存儲庫

public class SwimTeamRepository : ITeamRepository<SwimTeam> 
{ 
    private readonly Table<SwimTeam> _teamTable; 
    public SwimTeamRepository(string connectionString) 
    { 
     _teamTable = (new DataContext(connectionString).GetTable<SwimTeam>()); 
    } 

    public IQueryable<SwimTeam> Team 
    { 
     get { return _teamTable; } 
    } 
} 

public class SoccerTeamRepository : ITeamRepository<SoccerTeam> 
{ 
    private readonly Table<SoccerTeam> _teamTable; 
    public SoccerTeamRepository(string connectionString) 
    { 
     _teamTable = (new DataContext(connectionString).GetTable<SoccerTeam>()); 
    } 

    public IQueryable<SoccerTeam> Team 
    { 
     get { return _teamTable; } 
    } 
} 

它們看起來除了類和表名一樣的,所以我顯然需要重新考慮此因素。這裏最好的方法是什麼?辛格爾頓?工廠方法?

在此先感謝!

回答

4

你可以使用泛型:

public interface ITeamRepository<T> 
{ 
} 

public class TeamRepository<TTeam> : ITeamRepository<TTeam> 
    where TTeam : Team 
{ 
    private readonly Table<TTeam> _teamTable; 
    public TeamRepository(string connectionString) 
    { 
     _teamTable = (new DataContext(connectionString).GetTable<TTeam>()); 
    } 

    public IQueryable<TTeam> Team 
    { 
     get { return _teamTable; } 
    } 
} 

public class Team 
{ 
} 

public class SwimTeam : Team 
{ 
} 

然後使用它是這樣的...

public void MyMethod() 
{ 
    var repository = new TeamRepository<SwimTeam>(); 
} 

...和設置您的IoC容器W/Ninject像這樣.. 。

public class MyModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<ITeamRepository<SwimTeam>> 
      .To<TeamRepository<SwimTeam>>(); 
    } 
} 

public void MyMethod() 
{  
    var repository = kernel.Get<ITeamRepository<SwimTeam>>(); 
} 

如果你想獲得REAL通用和h AVE爲所有映射類的單個存儲庫中,你可以做這樣的事情:

public interface IRepository 
{ 
    IQueryable<T> Get<T>() where T : class, new(); 
} 

public class Repository : IRepository, IDisposable 
{ 
    private DataContext _dataContext; 
    public Repository(string connectionString) 
    { 
     _dataContext = new DataContext(connectionString); 
    } 

    public IQueryable<T> Get<T>() 
     where T : class, new() 
    { 
     return _dataContext.GetTable<T>().AsQueryable(); 
    } 

    public void Dispose() 
    { 
     if (_dataContext != null) 
     { 
      _dataContext.Dispose(); 
      _dataContext = null; 
     } 
    } 
} 

...你可以調用像這樣(在設置你的Ninject容器)...

using (var repository = kernel.Get<IRepository>()) 
{ 
    var swimTeam = repository.Get<SwimTeam>(); 
} 

由於Ninject負責管理對象的生命週期管理,因此您不必將庫存儲在using語句中。實際上,如果您打算在其生命週期的範圍內多次使用存儲庫,則根本不想使用using語句。 Ninject會在生命週期結束時自動處理它。

這是Rob Conery的good article關於使用這種技術來減少使用不同ORM的摩擦。

編輯由keeg:

我想

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : Team {} 

應該

public class TeamRepository<TTeam> : ITeamRepository<TTeam> where TTeam : class {} 

請更正,如果我錯了。

+0

你的答案比我的更厲害。 – 2011-05-11 19:14:06

+0

哇,我只是想知道使用聲明,我當然包裝它,然後得到一個錯誤,說對象已被處置...呃。我*心* ninject – keeg 2011-05-11 19:39:15

+0

感謝凱文,我在NinjectModule中出現錯誤,關於沒有從Entities.SwimTeam到Domain.Concreate.TeamRepository keeg 2011-05-11 20:11:05

1

這是你想要的嗎?

public class TeamRepository : ITeamRepository<T> 
    { 
     private readonly Table<T> _teamTable; 
     public TeamRepository(string connectionString) 
     { 
      _teamTable = (new DataContext(connectionString).GetTable<T>()); 
     } 

     public IQueryable<T> Team 
     { 
      get { return _teamTable; } 
     } 
    } 
+0

你也不想讓成爲任何東西。您需要設置一個過濾器,其中必須從正確的基類中派生。 – 2011-05-11 19:05:16

+0

感謝道格,但凱文的回答非常詳細,希望我能像「專家交流」那樣「分裂」。 – keeg 2011-05-11 19:37:28

+0

@Keeg - 查看我對Kevin的帖子的評論。 – 2011-05-11 19:41:53