2013-06-10 29 views
7

Tôi đã nhìn thấy các câu hỏi/câu trả lời tương tự cho bài đăng này trong quá khứ, nhưng tôi hơi khác so với những người khác mà tôi đã thấy.Lựa chọn phương pháp động dựa trên kiểu tham số thời gian chạy

Về cơ bản, tôi có một giao diện chung và một số lớp triển khai/kế thừa từ nó. Sau đó, trong một lớp riêng biệt, tôi có các phương thức phải hành động dựa trên các đối tượng được đưa ra bởi giao diện IObject. Tuy nhiên, mỗi người trong số họ phải được hành động theo những cách khác nhau, do đó tại sao có một tuyên bố riêng biệt của phương pháp cho từng loại cụ thể mở rộng IObject.

class IObject 
{ 
    ... 
} 

class ObjectType1 : IObject 
{ 
    ... 
} 

class ObjectType2 : IObject 
{ 
    ... 
} 

class FooBar 
{ 
    void Foo (ObjectType1 obj); 
    void Foo (ObjectType2 obj); 
} 

Bây giờ, với tôi, một giải pháp rõ ràng là tận dụng lợi thế của ràng buộc động bằng cách đặt phương thức Foo trong mỗi lớp riêng lẻ. Tuy nhiên, đây là không phải là một tùy chọn ở đây, bởi vì tôi xác định nhiều mô hình để hành động theo các đối tượng này và tôi muốn đóng gói từng mô hình riêng lẻ để xử lý các đối tượng trong lớp của riêng nó chứ không phải là tất cả các mô hình vào các lớp đối tượng.

Tôi đã tìm thấy this bài đăng hiển thị cách sử dụng từ điển để chọn động trong thời gian chạy thực hiện phương pháp chính xác. Tôi ổn với cách tiếp cận này; tuy nhiên, giả sử rằng tôi phải thực hiện một công văn như thế này một lần trong mỗi mô hình. Nếu tôi chỉ có IObject và triển khai cụ thể của nó, là có cách nào để khái quát hóa phương pháp này để tôi có thể gọi phương thức của bất kỳ tên dựa trên loại thời gian chạy của các đối tượng?

Tôi biết đây có lẽ là một câu hỏi không rõ ràng, nhưng tôi rất cảm kích mọi trợ giúp.

Trả lời

10

Từ khóa dynamic là thực sự rất giỏi này:

void Main() 
{ 
    var foobar = new FooBar(); 
    foreach(IObject obj in new IObject[]{ new ObjectType1(), new ObjectType2()}) 
    { 
     foobar.Foo((dynamic)obj); 
    } 
    // Output: 
    // Type 1 
    // Type 2 
} 

class IObject 
{ 
} 

class ObjectType1 : IObject 
{ 
} 

class ObjectType2 : IObject 
{ 
} 

class FooBar 
{ 
    public void Foo (ObjectType1 obj) { 
     Console.WriteLine("Type 1"); 
    } 
    public void Foo (ObjectType2 obj) { 
     Console.WriteLine("Type 2"); 
    } 
} 

Mã này là siêu đơn giản, và nó có pretty decent performance.

+0

Đây là câu trả lời đúng tôi nghĩ. – Ziffusion

+1

Oh wow, nếu điều này hoạt động như nó có vẻ như nó, sau đó là tuyệt vời! Tôi sẽ chơi xung quanh với một chút khi tôi nhận được một số cơ hội, nhưng cảm ơn cho giải pháp này. Trọng tâm trong mã của tôi là về khả năng đọc và bảo trì dễ dàng vì vậy điều này có vẻ khá tuyệt vời. – TSM

2

Có thể bạn muốn một cái gì đó rất gần với visitor patter.

Nếu bạn chỉ muốn chọn một phương pháp (Foo) của một đối tượng (FooBar) theo loại đối số bạn có thể sử dụng phản ánh để có được tất cả các phương pháp với tên được đặt (Foo) và làm trận đấu tay lập luận dựa trên loại đối tượng (ObjectTypeX) và lựa chọn đối số. Đừng quên xử lý các lớp có nguồn gốc đúng cách.

Để tránh phải trả chi phí phản ánh trên mọi cuộc gọi - kết quả bộ nhớ cache (tức là bằng cách tạo/biên soạn cây biểu hiện).

Lưu ý rằng phương pháp từ điển (hành động cho tên phương thức đã được lập chỉ mục theo loại) có thể sẽ dễ dàng hơn để hỗ trợ/gỡ lỗi để bắt đầu. Sau đó nếu bạn thấy nó chậm cho bạn cần bạn có thể thay thế nó bằng một cái gì đó phức tạp hơn như sự phản chiếu.

+0

Thú vị, cảm ơn phản hồi!Tôi hơi quen thuộc với Mẫu thiết kế của khách truy cập, nhưng tôi rất mới với C# và chỉ khám phá tất cả các tùy chọn của tôi. – TSM

0

bạn chỉ có thể thực hiện một phương pháp mà có các loại giao diện, sau đó bạn kiểm tra sự correcttype và đúc nó

ObjectType1 obj1 = new ObjectType1(); 

foo(obj1); 

void foo(IObject fm) 
     { 
      ObjectType1 cls; 
      if (fm is ObjectType1) 
      { 
       cls = fm as ObjectType1; 
       cls.ID = 10; 
       MessageBox.Show(cls.ID.ToString() + " " + cls.GetType().ToString()); 
      } 
     } 

Thats vì các lớp thực hiện IObject , cls.ID chỉ là ví dụ bạn có thể đặt một thuộc tính bạn thực hiện. Hãy thử và cho tôi biết .... những lời chúc tốt đẹp nhất.

+0

Đây là cách tiếp cận mất một vài ngày trước đó (vì tôi quen thuộc với nó và cần một bản demo làm việc). Bây giờ tôi đang giải quyết vấn đề này trên phạm vi rộng hơn, tôi đang khám phá các tùy chọn đơn giản khác có thể đặc trưng cho C#. Cách tiếp cận này không hoạt động, mặc dù! – TSM

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