2012-06-14 11 views
5

Đây là lớp generic Tôi đang làm việc với:C# bê tông ghi đè chung lớp

public interface IRepository<T> where T : EntityObject 
{ 
    RepositoryInstructionResult Add(T item); 
    RepositoryInstructionResult Update(T item); 
    RepositoryInstructionResult Delete(T item); 
} 
public class Repository<T> : IRepository<T> where T : EntityObject 
{ 

    RepositoryInstructionResult Add(T item) 
    { //implementation} 
    RepositoryInstructionResult Update(T item); 
    { //implementation} 
    RepositoryInstructionResult Delete(T item); 
    { //implementation} 
} 

Bây giờ tôi đang tìm cách để thỉnh thoảng thay đổi hành vi của các phương pháp khi t: một loại cụ thể. Có phải điều gì đó như sau có thể xảy ra không? Cố gắng đặc biệt này đưa ra một lỗi (Lỗi 5: Khai báo một phần của 'Kho lưu trữ' phải có cùng tên thông số kiểu theo cùng thứ tự).

public class Repository<Bar> //where Bar : EntityObject 
{ 
    RepositoryInstructionResult Add(Bar item) 
    { //different implementation to Repository<T>.Add() } 
    //other methods inherit from Repository<T> 
} 
+2

'BarRepository: Repository ... ', và đánh dấu những methods augmentible như ảo/ghi đè trong các lớp cơ sở/con, tương ứng. –

+0

@Anthony: Tại sao không đăng câu trả lời đó? (Cái mà tôi sắp sửa gửi = P) – benjer3

Trả lời

4
public class BarRepository : Repository<Bar> 
{ 
    RepositoryInstructionResult Add(Bar item) 
    { //different implementation to Repository<T>.Add() } 
    //other methods inherit from Repository<T> 
} 
+1

Phản đối của tôi đối với giải pháp này là bạn cần phải tạo ra 'mới BarRepository()' một cách rõ ràng. Nếu bạn gọi 'Kho lưu trữ mới ()', bạn sẽ nhận được thực thi chung (nghĩa là sai). Kể từ khi kho đã được tạo ra và tiêu thụ trên codebase của tôi, tôi không muốn phải ẩn instanciation trong một nhà máy. – daveharnett

+0

Mã này rõ ràng sẽ cần các phương thức được hiển thị dưới dạng công khai để hoàn thành giao diện và cần các công cụ sửa đổi ảo/ghi đè trong cơ sở/con để sử dụng các hành vi đa hình. –

+0

@daveharnett, để sử dụng tốt nhất mẫu lưu trữ, mã hoặc logic phụ thuộc vào kho lưu trữ sẽ được mã hóa cho giao diện thay vì triển khai. Mã đó, sau đó, sẽ xem xét 'IRepository ', và do đó sẽ không cần phải thay đổi. Mặc dù bạn là chính xác, bất kỳ mã nào chịu trách nhiệm tạo ra các triển khai cụ thể sẽ cần phải được cập nhật. –

0

Tên lớp RepositoryBase Repository của bạn và làm cho các phương pháp giao diện ảo. thực hiện chúng theo cách tổng quát bên trong lớp RepositoryBase của bạn, nhưng vì u được đánh dấu các phương thức như ảo u sẽ có thể ghi đè lên chức năng trong các lớp dẫn xuất của bạn, mã của bạn sẽ trông giống như thế này.

public interface IRepository<T> where T : EntityObject 
{ 
    RepositoryInstructionResult Add(T item); 
    RepositoryInstructionResult Update(T item); 
    RepositoryInstructionResult Delete(T item); 
} 

public class Repository<T> : IRepository<T> where T : EntityObject 
{ 
    virtual RepositoryInstructionResult Add(T item) 
    { //implementation} 
    virtual RepositoryInstructionResult Update(T item); 
    { //implementation} 
    virtual RepositoryInstructionResult Delete(T item); 
    { //implementation} 
    } 

Nếu U Cần một số logic tùy chỉnh được thực hiện cho phương pháp cập nhật cho Bar Object chỉ cần tạo có nguồn gốc lớp Tên nó BarRepository và phương pháp cập nhật ghi đè của lớp Repositorybase đây u có thể gọi cơ sở thực hiện hoặc chỉ quá trình với mình logic riêng

public class BarRepository : Repositorybase<Bar> 
{ 
    public override RepositoryInstructionResult Update(Bar item); 
    { 
     //Call base method if needed 
     //Base.Update(item); 

     //implement your custom logic here 
    } 
    } 
+0

Ditto trả lời của tôi để đánh thức. Nó sẽ có được công việc làm, nhưng nó sẽ làm cho tiêu thụ khó khăn hơn. – daveharnett

+0

Ý bạn là gì? –

+0

Tôi có nghĩa là bạn cần instanciate 'mới BarRepository()' một cách rõ ràng. Nếu bạn gọi 'Kho lưu trữ mới ()', bạn sẽ nhận được thực thi chung (nghĩa là sai). Lý tưởng nhất là tôi đang tìm kiếm một giải pháp sẽ bị ẩn khỏi mã tạo kho lưu trữ. – daveharnett

0

Như một câu trả lời trực tiếp câu hỏi của bạn: điều gần nhất có thể với những gì bạn đã thể hiện được kiểm tra giá trị thực tế của T khi chạy. Trong phương pháp add của bạn, bạn có thể viết một cái gì đó như thế này:

if (typeof(T) == typeof(Bar)) { 
    // your Bar-specific code 
} 
// ... 

Lưu ý rằng điều này có thể không được rất tốt về hiệu suất, đặc biệt là nếu bạn có nhiều hơn một hoặc hai loại đặc biệt như vậy mà bạn muốn để điều trị khác nhau.

Ngoài ra, giải pháp duy nhất là một phân lớp chỉ định đối số kiểu thực tế cho lớp cơ sở, như được nêu trong các câu trả lời khác.

+0

Cảm ơn. Hiệu suất sang một bên, điều này sẽ rất lộn xộn nếu có nhiều hơn một vài trường hợp đặc biệt. – daveharnett

+0

@daveharnett: Không nhất thiết; trong trường hợp đó, bạn có thể muốn sử dụng một đối tượng 'Dictionary ' của 'Handler' (một lớp của riêng bạn) thực hiện các hành động kiểu cụ thể. Như thế này, về cơ bản nó chỉ có 3-4 dòng mã (có thể ít hơn với một phương pháp mở rộng) trong mỗi phương pháp cần điều trị đặc biệt. –

0

sử dụng một phương pháp khuyến nông:

public static void DoSomething(this repository<Bar> repo) 
{ 
    //your custom code goes here 
}