2010-03-16 20 views
6

Tôi có lớp cơ sở "Sản phẩm", một số lớp khác "ProductBookDetail", "ProductDVDDetail" kế thừa từ lớp này. Tôi sử dụng một lớp ProductService để thực hiện thao tác trên các lớp này. Nhưng, tôi phải làm một số kiểm tra tùy thuộc vào loại (ISBN cho Sách, ngôn ngữ cho DVD). Tôi muốn biết cách tốt nhất để truyền giá trị "productDetail", tôi nhận được trong SaveOrupdate. Tôi cố gắng GetType() và dàn diễn viên với (ProductBookDetail)productDetail nhưng điều đó không làm việcGeneric <T> cách truyền?

Cảm ơn,

var productDetail = new ProductDetailBook() { .... }; 
var service = IoC.Resolve<IProductServiceGeneric<ProductDetailBook>>(); 
service.SaveOrUpdate(productDetail); 

var productDetail = new ProductDetailDVD() { .... }; 
var service = IoC.Resolve<IProductServiceGeneric<ProductDetailDVD>>(); 
service.SaveOrUpdate(productDetail); 


public class ProductServiceGeneric<T> : IProductServiceGeneric<T> 
{ 
    private readonly ISession _session; 
    private readonly IProductRepoGeneric<T> _repo; 
    public ProductServiceGeneric() 
    { 
     _session = UnitOfWork.CurrentSession; 
     _repo = IoC.Resolve<IProductRepoGeneric<T>>(); 
    } 
    public void SaveOrUpdate(T productDetail) 
    {    
     using (ITransaction tx = _session.BeginTransaction()) 
     { 
      //here i'd like ot know the type and access properties depending of the class 
      _repo.SaveOrUpdate(productDetail); 
      tx.Commit(); 
     } 
    } 
} 
+0

có thể bạn nên thực hiện dịch vụ cụ thể và để lưu hoặc cập nhật chung nếu bạn không cần lưu bất kỳ dữ liệu nào khác hoặc bạn có thể sử dụng thừa kế trong orm của mình. Sự cần thiết của thực thể cụ thể có vẻ kỳ lạ: thông thường bạn làm điều gì đó như: Sản phẩm mớiServiceGeneric (). Và tất cả trong mã của bạn sẽ là sách, vì vậy bạn không cần phải biết. –

Trả lời

-2

Sử dụng:..

if(productDetail is ProductDetailBook) 
{ 
... 
... 
} 

và tương tự cho người khác

+0

Tại sao bỏ phiếu xuống? – logicnp

0

Nếu tôi hiểu bạn câu hỏi bạn đang cố gắng xác định lớp dẫn xuất bạn có từ một hàm trả về lớp cơ sở. Bạn cần sử dụng toán tử IS

bạn có thể xem cách sử dụng toán tử bên dưới.

class Base 
{ 
} 

class AB : Base 
{ 

} 
class AC : Base { } 

class Program 
{ 
    static Base GetObject() 
    { 
     return null; 
    } 
    static void Main(string[] args) 
    { 
     Base B = GetObject(); 
     if (B is AB) 
     { 
      AB DevClass =(AB) B; 
     } 
    } 


} 

}

+0

Có và bỏ vào đúng lớp –

+0

toán tử 'as' tốt hơn trong trường hợp này (và kiểm tra null sau đó) –

3

Nếu bạn cần biết về các lĩnh vực hoặc các thuộc tính của các loại để "tiết kiệm hoặc cập nhật", bạn có thể sử dụng phản ánh. Bằng cách đó, lớp học sẽ vẫn thật sự chung chung.

Nếu trong phương pháp SaveOrUpdate của bạn, bạn có nghĩa là để viết một công tắc không ngừng mở rộng tương đương với:

if (it's type A) { deal with type A } 
else if (it's type B) { deal with type B } 
... and so on 

Sau đó, bạn đang làm nó "sai". Lớp đó không thực sự phổ biến trong tham số kiểu của nó. Nó chỉ hoạt động với tập hợp các loại cụ thể mà bạn đã chỉ định. Tôi nói "sai" trong dấu ngoặc kép bởi vì nó có thể tốt hơn so với các lựa chọn thay thế có sẵn trong một số tình huống, nhưng nó không mong muốn. Nếu bạn có một trở lại cho tất cả các loại khác, vì vậy nó luôn luôn hoạt động, sau đó nó có thể là một cách okay để có trường hợp đặc biệt cho một số loại.

Tuy nhiên, bạn có thể thực hiện phép thử hoặc truyền như vậy. Với một số loại không bị giới hạn, T, bạn cần phải bỏ nó vào object đầu tiên:

var eitherStringOrNull = (string)((object)somethingOfTypeT); 

với từ khóa as bạn không nên cần có thêm dàn diễn viên để object.

var eitherStringOrNull = somethingOfTypeT as string; 
if (eitherStringOrNull != null) 
{ 
    .. it was a string, so we can use it as such 
} 

Nhưng thậm chí tốt hơn, nếu có một lớp cơ sở chung, ProductDetail, cho tất cả các loại lớp chi tiết sản phẩm, sau đó sử dụng như một cản trở đối T:

public class ProductServiceGeneric<T> : IProductServiceGeneric<T> 
     where T : ProductDetail 

Tôi nghĩ đó là thực hành tốt khi thực hiện điều đó để sử dụng tên có ý nghĩa hơn cho tham số kiểu, chẳng hạn như TProductDetail.

Nếu bạn thực hiện việc này, trình biên dịch sẽ cho phép bạn "truyền xuống" thành nội dung bắt nguồn từ ProductDetail, mà không phải truyền trước object trước tiên.

+0

Trình ghi đè - làm thế nào về nhận xét? –

3

Nooooo

Nếu bạn có đặc tính phi generic (theo quy định tại hợp đồng giao diện phổ biến) thì bạn nên có một chức năng phổ biến khai báo trong giao diện được gọi bằng SaveOrUpdate để xử lý này

Mỗi thể hiện của các giao diện chung (ProductDetailBook, productDetail vv) sẽ xác định chức năng này theo yêu cầu của "// ở đây tôi muốn ot biết loại và thuộc tính truy cập tùy thuộc vào lớp"

Bạn đang kéo mã cụ thể của lớp và đưa nó vào một chức năng phổ biến, đây là sự khởi đầu của spaghetti đang

Đây là một trong nhiều lý do không có dịch vụ chung

3

Tôi không có ý là quan trọng, nhưng mô hình mà chỉ cảm thấy xấu với tôi.

Tôi đã nghe những người khác nói rằng nếu bạn đang dùng một loại trong một phương pháp chung, thì bạn có thể làm điều gì đó sai trái.

tôi sẽ cấu trúc lại mã của bạn bằng cách tuyên bố một phương pháp lớp cơ sở để giúp đỡ với các SaveOrUpdate phương pháp, sau đó có các lớp thừa kế override rằng phương pháp. Bây giờ khi bạn gọi phương thức lớp cơ sở theo phương thức chung, bạn sẽ nhận được các lớp dẫn xuất có nghĩa là

0

Trong các phương thức chung, bạn phải đúc as từ khóa để làm phôi như thế này. Có những lý do chính đáng tại sao nhưng đó là một câu chuyện dài ...

Nếu bạn làm rất nhiều với Generics, hãy đọc Bill Wagners "Hiệu quả hơn C#" cho các cách khác để giải quyết vấn đề này một cách rõ ràng hơn.

public void SaveOrUpdate(T productDetail) 
{    
    using (ITransaction tx = _session.BeginTransaction()) 
    { 
     ProductDetailBook bookDetail = productDetail as ProductDetailBook; 
     if (bookDetail != null) 
      _repo.SaveOrUpdate(bookDetail); 
     tx.Commit(); 
    } 
} 
0

Có lẽ bạn nên cấu trúc lại mã của bạn như sau:

abstract class Product 
{ 
    public abstract bool CheckProduct(); 
} 
class ProductBookDetail : Product 
{ 
    public override bool CheckProduct() 
    { 
     //Here we can check ProductBookDetail 
    } 
} 

class ProductDetailDVD : Product 
{ 
    public override bool CheckProduct() 
    { 
     //Here we can check ProductDetailDVD 
    } 
} 

public class ProductServiceGeneric<T> : IProductServiceGeneric<T> where T : ProductDetail 
{ 
    public void SaveOrUpdate(T product) 
    { 
     if (!product.CheckProduct()) 
     { 
      //product checking failes. Add necessary logic here 
     } 
    } 
} 

Mã này là nhiều hơn nữa phù hợp với OOP. Nó đơn giản hơn nhiều, nó dễ mở rộng hơn và ít bị lỗi hơn.

P.S. Đừng quên về S.O.L.I.D.

0

Tôi sẽ tra cứu Strategy pattern và có thể sử dụng kết hợp với kho lưu trữ chung của bạn. Sau đó, bạn có thể xác định chiến lược của mình trong một số giao diện cho các thực thể của bạn, điều này buộc chúng thực hiện một số phương thức như CheckConstraints. Trong kho lưu trữ chung của bạn, bạn gọi CheckConstraints trước khi thực hiện SaveOrUpdate.

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