2010-10-31 27 views
6
public interface IRepository<T> where T : Entity 
{ 
    void Delete(T entity); 
    T[] GetAll(); 
    T GetById(int id); 
    void SaveOrUpdate(T enity); 
    void Merge(T entity); 
} 

public interface ITeamEmployeeRepository : IRepository<TeamEmployee> 
{ 
    PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize); 
} 


public class Repository<T> : IRepository<T> where T : Entity 
{ 
    private readonly ISession _session; 

    protected Repository() 
    { 
     _session = GetSession(); 
    } 

    public virtual void Delete(T entity) 
    { 
     _session.Delete(entity); 
    } 

    public virtual T[] GetAll() 
    { 
     return _session.CreateCriteria<T>().List<T>().ToArray(); 
    } 

    public virtual T GetById(int id) 
    { 
     return _session.Get<T>(id); 
    } 

    public virtual void SaveOrUpdate(T enity) 
    { 
     _session.SaveOrUpdate(enity); 
    } 

    public void Merge(T entity) 
    { 
     _session.Merge(entity); 
    } 

    protected ISession GetSession() 
    { 
     return new SessionBuilder().GetSession(); 
    } 
} 

public class TeamEmployeeRepository : Repository<TeamEmployee>, ITeamEmployeeRepository 
{ 
    public PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize) 
    { 
     return GetSession().QueryOver<TeamEmployee>() 
      .Fetch(x => x.Employee).Eager 
      .Fetch(x => x.Team).Eager 
      .ToPagedList(pageIndex, pageSize); 
    } 
} 

Để bây giờ tôi đăng ký kho như sau:StructureMap - Làm thế nào để đăng ký và giải quyết một mở generic loại

For<ILoanedItemRepository>().Use<LoanedItemRepository>(); 
For<ITeamEmployeeRepository>().Use<TeamEmployeeRepository>(); 
For<IArticleRepository>().Use<ArticleRepository>(); 
For<ISalesmanRepository>().Use<SalesmanRepository>(); 
For<ISalesmanArticleRepository>().Use<SalesmanArticleRepository>(); 
For<IGoodsGroupRepository>().Use<GoodsGroupRepository>(); 
For<IEmployeeRepository>().Use<EmployeeRepository>(); 

Điều này thực sự cồng kềnh, đặc biệt là nếu có đi kèm cùng kho mới.

Một đăng ký dễ dàng hơn và tốt hơn sẽ là:

For(typeof(IRepository<>)).Use(typeof(Repository<>)); 

Nhưng điều này không làm việc. StructureMap là mọi lúc nói với tôi rằng không có Instance mặc định nào được định nghĩa cho PluginFamily Core.Domain.Bases.Repositories.ITeamEmployeeRepository.

tôi đã tìm kiếm trên stackoverflow và tìm thấy những điều mới mẻ:

Scan(x => 
{ 
    x.AssemblyContainingType(typeof(TeamEmployeeRepository)); 
    x.AddAllTypesOf(typeof (IRepository<>)); 
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>)); 
}); 

Nhưng vẫn được thông báo lỗi tương tự.

Làm cách nào để đăng ký kho lưu trữ của tôi với StructureMap 2.6.1.0?

+0

Mặc dù điều này không trực tiếp trả lời câu hỏi của bạn, vui lòng xem bài viết này: http://stackoverflow.com/questions/4128640/how-to-remove-unit-of-work-functionality-from-repositories-using -ioc/41 32186 # 4132186. Nó cho thấy một cách khác để thực hiện mẫu kho lưu trữ. Việc thực hiện ẩn kho của bạn đằng sau một đơn vị công việc và bạn chỉ cần đăng ký một 'IUnitOfWorkFactory' và bạn đã hoàn tất. – Steven

Trả lời

7

Tôi đã tìm được giải pháp.

Scan(x => 
{ 
    x.WithDefaultConventions(); 
    x.AssemblyContainingType(typeof(TeamEmployeeRepository)); 
    x.AddAllTypesOf(typeof(Repository<>)); 
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>)); 
}); 

WithDefaultConventions là một phần quan trọng của mã hiển thị, bởi vì với thiết lập này bạn nói StructureMap để sử dụng quy ước của mappping ITeamEmployeeRepository để TeamEmployeeRepository. Vì vậy, StructureMap tiến hành từ giả định rằng lớp được đặt tên giống như tên của giao diện mà không có tiền tố I.

-1

Gần đây, tôi đã giải quyết được điều gì đó tương tự bằng cách thiết kế lại nhỏ, điều này khiến mọi thứ trở nên đơn giản hơn rất nhiều. Điều này có thể làm việc cho bạn là tốt. Bạn có thể thử xóa các giao diện cụ thể như ITeamEmployeeRepositoryILoanedItemRepository khỏi thiết kế của mình. Cách tôi đã làm điều này là bằng cách sử dụng các phương pháp mở rộng. Dưới đây là một ví dụ:

public static class RepositoryExtensions 
{ 
    public static TeamEmployee GetById(
     this IRepository<TeamEmployee> repository, int id) 
    { 
     return repository.Single(e => e.TeamEmployeeId == id); 
    } 

    public static IQueryable<Salesman> GetActiveSalesmen(
     this IRepository<ISalesmanRepository> repository) 
    { 
     return repository.Where(salesman => salesman.Active); 
    } 

    // etc 
} 

Sau đó tôi tạo ra một IRepositoryFactory cho phép tôi để tạo ra các kho của một loại nhất định:

public interface IRepositoryFactory 
{ 
    IRepository<T> CreateNewRepository<T>(); 
} 

Khi có giao diện này tại chỗ nó rất dễ dàng để tạo ra một thực hiện nhà máy này yêu cầu các container để tạo ra một bê tông Repository<T>. Các RepositoryFactory có thể trông như thế này:

public class RepositoryFactory : IRepositoryFactory 
{ 
    public IRepository<T> CreateNewRepository<T>() 
    { 
     return ObjectFactory.GetInstance(typeof(Repository<T>)); 
    } 
} 

Với thiết kế này, bạn chỉ cần đăng ký bê tông RepositoryFactory bởi giao diện IRepositoryFactory của nó và bạn đã làm xong. Thay vì tiêm IRepository<ITeamEmployeeRepository> trong thiết kế cũ, bây giờ bạn hãy tiêm IRepositoryFactory và để cho khách hàng gọi phương thức CreateNewRepository<T>. Vì việc sử dụng các phương thức mở rộng, bạn có thể gọi các kiểu phương thức cụ thể trên kho lưu trữ.

Một ưu điểm khác của việc này là bạn không cần phải triển khai lại các phương pháp mà ban đầu bạn đã xác định trên ITeamEmployeeRepository trên mọi triển khai.

Thiết kế này hoạt động rất tốt trong tình huống của tôi, đặc biệt là vì các giao diện IRepository<T> của tôi sử dụng các cây biểu thức. Tất nhiên là không thể cho tôi biết liệu thiết kế đó có phù hợp với bạn hay không nhưng tôi hy vọng nó sẽ thành công.

Chúc may mắn.

+0

"Một ưu điểm khác của việc này là bạn không cần phải triển khai lại các phương thức mà bạn đã định nghĩa ban đầu trên ITeamEmployeeRepository trong mỗi lần triển khai." Đây không phải là trường hợp, bởi vì Kho lưu trữ đã triển khai các công cụ CRUD chuẩn. ITeamEmployeeRepository cụ thể chỉ có các yêu cầu cụ thể. – Rookian

+0

Có lẽ tôi hiểu sai, nhưng tôi tưởng tượng rằng bạn sẽ sử dụng 'ITeamEmployeeRepository' cho các phương thức cụ thể của nhân viên nhóm. Những phương thức này sẽ không có ý nghĩa trong lớp 'Repository '. Tôi cho rằng bạn có các phương thức cụ thể của thực thể trên giao diện đó, bởi vì một giao diện không có các phương thức sẽ không hữu ích lắm. Những thứ như 'hoạt động GetByYear' hoặc CRUD không có ý nghĩa trên Repository . Bạn thường sẽ có ít nhất hai cài đặt của giao diện 'ITeamEmployeeRepository' này ... – Steven

+0

Một trong môi trường sản xuất của bạn và một cho môi trường thử nghiệm đơn vị của bạn. Điều này có nghĩa là trong các tình huống đó, bạn sẽ phải thực hiện 'GetByYear' trong cả sản phẩm' TeamEmployeeRepository' của bạn và kho kiểm tra sử dụng. Với một phương pháp mở rộng, bạn không chỉ tiết kiệm cho mình từ việc phải viết nó nhiều lần, nhưng nó cho phép bạn bao gồm mã đó. Nhưng một lần nữa, có lẽ tôi hiểu lầm nhu cầu của bạn. – Steven

-2

Bạn cần tạo ITypeScanner của riêng mình và đăng ký số đó trong cuộc gọi Scan(). Hãy xem mã nguồn của GenericConnectionScanner làm điểm bắt đầu. Thay vì tìm kiếm các loại để xem chúng có thực hiện IRepository<T> hay không, bạn sẽ xem xét xem chúng có triển khai bất kỳ giao diện nào thực hiện IRepository<T> hay không và sau đó đăng ký loại giao diện đó.

CẬP NHẬT: Tất cả cuộc trò chuyện của IRepository<T> khiến tôi suy nghĩ quá mức về điều này, khi đó thực sự là một chi tiết không liên quan. Chỉ cần sử dụng trình quét DefaultConventions theo đề xuất của Rookian.

2

Tôi tìm thấy câu hỏi này googling "structuremap resolve generic". Các câu trả lời hiện có là tốt nhưng phức tạp. Đối với những người tìm kiếm câu trả lời đơn giản: cho giao diện ISome và triển khai lớp Một số chúng ta viết

c.For<ISome>().Use<Some>() 

Trong khi cho generic ISome <T> và triển khai lớp Một số <T> chúng tôi viết

c.For(typeof(ISome<>)).Use(typeof(Some<>)) 

Và đó là tất cả

Các vấn đề liên quan