2011-11-10 22 views
6

Các ứng dụng tôi đang làm việc trên là dựa vào Autofac như DI container và một trong những lý do khiến tôi quyết định sử dụng nó, trong số những người khác, là tính năng nhà máy đại biểu (xem here)Dịch vụ Định vị dễ sử dụng hơn là phụ thuộc Tiêm?

này làm việc tốt cho tất cả các trường hợp nơi tôi cần tạo lại các phần tử giống nhau nhiều lần như trường hợp của một số báo cáo và màn hình có liên quan. Một số báo cáo (thậm chí cả các báo cáo cùng loại) được thực thi đồng thời nhưng chúng chỉ thay đổi bởi các tham số do người dùng định nghĩa để tạo các trường hợp để tạo các cá thể, chuyển các tham số miễn phí và để phần còn lại ứng dụng.

Sự cố xảy ra với thực tế là mỗi báo cáo được tạo thành từ một số lượng báo cáo phụ (nhiệm vụ) khác nhau và mỗi tác vụ thực hiện giao diện ITask. Mỗi báo cáo có thể có tối đa 50 tác vụ khác nhau để sử dụng và mỗi tác vụ đóng gói một hoạt động kinh doanh chính xác. Một lựa chọn tôi có là tiêm các nhà máy ủy nhiệm và tạo chúng khi cần.

Những nhiệm vụ đã được tự động tạo ra bởi các nhà máy và một cái gì đó như:

var myTaskA = _taskFactoryConcreteTaskA(); 
var myTaskB = _taskFactoryConcreteTaskB(); 
var myTaskC = _taskFactoryConcreteTaskC(); 
... 
var myTaskZZ = = _taskFactoryConcreteTaskZZ(); 

đòi hỏi rất nhiều dây bằng tay (đại biểu, nhà xây dựng, ủng hộ các lĩnh vực vv) trong khi một cái gì đó giống như

var myTaskA = _taskFactory.Create<ConcreteTaskA>(); 
var myTaskB = _taskFactory.Create<ConcreteTaskB>(); 
var myTaskC = _taskFactory.Create<ConcreteTaskC>(); 
... 
var myTaskZZ = _taskFactory.Create<ConcreteTaskZZ>(); 

sẽ là công việc cực kỳ ít đặc biệt là nếu _taskFactory kết thúc tốt đẹp vùng chứa như được hiển thị trong this other post, nhưng về cơ bản nó có nghĩa là tôi đang sử dụng một trình định vị dịch vụ để tạo các nhiệm vụ của mình.

Tôi có các tùy chọn nào khác có thể phù hợp để giải quyết vấn đề này?

(Chú ý: có một cơ hội tốt cho tôi hoàn toàn khỏi đường đua và rằng tôi phải đọc nhiều hơn về DI, trong trường hợp bất kỳ đóng góp sẽ được thậm chí quan trọng hơn)

+0

Martin Fowler đã viết về vấn đề này một chút: http://martinfowler.com/articles/injection.html#UsingAServiceLocator – mwilson

+2

Cảm ơn, đây là những gì khiến tôi suy nghĩ lại về bài viết mà rất nhiều: http: //blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx (và thuyết phục tôi mua sách, vẫn đang đợi sách) – mhttk

Trả lời

3

Một cách tiếp cận đáng được nghiên cứu là phá vỡ into'units vấn đề của công việc' sử dụng một tập hợp các nhiệm vụ liên quan:

public class WorkItem1 : ISomeWork 
{ 
    public WorkItem1(Task1 t1, Task2 t2...) { } 
    public void DoSomething() { ... } 
} 

Sau đó, bạn sử dụng các nhà máy sẽ đi xuống về phía someWorkFactory().DoSomething(), có thể cho một vài loại khác nhau của 'cái gì'.

Lớp học có số lượng phụ thuộc lớn, trên các nhà máy hoặc bất kỳ thứ gì khác, thường chỉ vào các lớp học nhỏ hơn, tập trung hơn đang chờ khám phá để phá vỡ công việc.

Hy vọng điều này sẽ hữu ích.

+0

+1 Tuy nhiên, hãy xem câu trả lời của tôi cho các tùy chọn khác. –

+0

cảm ơn, điều này là thú vị vì nó thực sự có thể làm việc cho tôi. thực tế của việc sử dụng một số nhiệm vụ trong một lớp báo cáo là phải có từng công việc để giải quyết các phần cụ thể của các báo cáo phức tạp, do đó làm giảm độ phức tạp của mã tổng thể bằng cách làm cho nó rõ ràng hơn. có thể bằng cách phân tích các báo cáo trong các phần phụ và sau đó cho phép các nhà máy làm các instantiation khi cần thiết. – mhttk

6

Vì các nhà máy được chỉ định trong câu hỏi không có bất kỳ đối số nào, sử dụng mùi nhà máy của Leaky Abstraction. Như Nicholas Blumhardt chỉ ra trong câu trả lời của anh ta, một cách tiếp cận tốt hơn có thể đơn giản là tiêm từng công việc vào người tiêu dùng.

Trong trường hợp này, vì tất cả các nhiệm vụ thực hiện cùng một giao diện, thay vì tiêm lên đến 50 ITask trường hợp khác nhau, bạn có thể soạn chúng:

public class MyConsumer 
{ 
    private readonly IEnumerable<ITask> tasks; 

    public MyConsumer(IEnumerable<ITask> tasks) 
    { 
     this.tasks = tasks; 
    } 

    public void DoSomething() 
    { 
     foreach (var t in this.tasks) 
     { 
      // Do something with each t 
     } 
    } 
} 

Ngoài ra, bạn có thể soạn chuỗi các ITasks thành một Composite, mà thực sự là giải pháp ưa thích của tôi:

public CompositeTask : ITask 
{ 
    private readonly IEnumerable<ITask> tasks; 

    public CompositeTask(IEnumerable<ITask> tasks) 
    { 
     this.tasks = tasks; 
    } 

    // Implement ITask by iterating over this.tasks 
} 

này sẽ đơn giản hóa cho người tiêu dùng và biến thực tế là có nhiều hơn một công việc được thực hiện vào một chi tiết thi hành :

public class MyConsumer 
{ 
    private readonly ITask task; 

    public MyConsumer(ITask task) 
    { 
     this.task = task; 
    } 

    public void DoSomething() 
    { 
     // Do something with this.task 
    } 
} 
+0

Cảm ơn bạn, tôi đã xem xét kịch bản này, nhưng tôi không chắc liệu tôi có hiểu những gì bạn đang đề xuất ở đây hay không. Nếu tôi tạo một tác vụ tổng hợp, tôi vẫn cần phải tiêm 'IEnumerable ' nhưng ai sẽ chèn các tác vụ chính xác vào bộ sưu tập? Có lẽ tôi đã không giải thích thực tế là các báo cáo khác nhau sử dụng các bộ công việc khác nhau và trong ví dụ bạn giả định để tiêm tất cả các tác vụ sẵn có? Tuy nhiên, các ví dụ từ cả bạn và Nicholas Blumhardt đều cung cấp thông tin chi tiết hữu ích, cảm ơn bạn. – mhttk

+2

Composer (Root Root) đưa ra quyết định về nhiệm vụ nào cần tiêm vào đâu. Trong khi bạn * có thể * tiêm tất cả các triển khai ITask trong * tất cả * báo cáo, bạn cũng có thể chọn chỉ một tập con cho mỗi báo cáo. Khi sử dụng DI Container, đó chỉ là câu hỏi về việc định cấu hình vùng chứa một cách chính xác. –

+0

Tôi hiểu, điều này rất thú vị. Điều này làm cho tôi hiểu đó là gợi ý của @ NicholasBlumhardt ngụ ý. Cảm ơn bạn. (ps Tôi đang háo hức chờ đợi [cuốn sách này] (http://manning.com/seemann/) để được giao, công việc tuyệt vời!) – mhttk

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