2012-07-03 27 views
7

Tôi chỉ mới bắt đầu với Khung công tác Spring Delphi và đã tự hỏi liệu phiên bản hiện tại của vùng chứa DI có cho phép ủy nhiệm việc xây dựng một phương thức nhà máy mà không chỉ định một kiểu triển khai không?Delphi Spring DI: Có thể ủy nhiệm instantiation giao diện mà không có một kiểu triển khai không?

Ví dụ: một cái gì đó tương tự như thế này:

GlobalContainer 
    .RegisterFactory<ISomeObject>(
    function: ISomeObject 
    begin 
     Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end) 
    .Implements<ISomeObject> // could probably be implied from the above 
    .AsSingletonPerThread; 

Như bạn có thể thấy, trường hợp sử dụng cụ thể của tôi là sự khởi tạo của các đối tượng COM. Trong trường hợp đó, lớp triển khai giao diện mà tôi quan tâm không phải là một phần của ứng dụng của tôi nhưng tôi vẫn có thể tạo các cá thể bằng cách gọi CreateComObject/CoCreateInstance. Tuy nhiên, có vẻ như tôi không may mắn vì đăng ký trong Container luôn xuất hiện để được ràng buộc với một lớp thực hiện thực tế.

Giả sử điều này là không thể vì vậy tại thời điểm này, các chuyên gia của bạn sẽ giải quyết vấn đề này như thế nào? Bạn có tạo một lớp bao bọc hoặc lớp giả hoặc bạn chỉ cần giữ đối tượng COM ra khỏi vùng chứa DI và đơn giản là khởi tạo chúng qua CreateComObject?

Trả lời

8

Thật không may thiết kế hiện tại của thùng chứa DI mùa xuân không cho phép điều đó. Nó nội bộ giả định rằng mọi loại dịch vụ (thường là giao diện, nhưng cũng có thể là một lớp) được thực hiện bởi một kiểu thành phần (một lớp). Vì vậy, có TObject tại một số nơi mà chúng tôi sẽ cần IInterface trong trường hợp này. Giống như đại biểu bạn đang chuyển đến phương thức DelegateTo trả về kiểu thành phần (hoặc TObject trong trường hợp không chung chung) và không phải là loại dịch vụ.

Đó cũng là vì bạn có thể đăng ký một loại thành phần với nhiều triển khai giao diện chỉ trong một cuộc gọi giao diện thông thạo. Giống như:

GlobalContainer 
    .RegisterType<TMyObject> 
    .Implements<IMyInterface> 
    .Implements<IMyOtherInterface>; 

container hiện kiểm tra nếu TMyObject tương thích với IMyInterfaceIMyOtherInterface. Khi gọi số Resolve, trình phân giải dịch vụ sử dụng GetInterface trên cá thể để nhận tham chiếu giao diện được yêu cầu. Mọi thứ vượt quá điểm đó được thực hiện trên một tham chiếu đối tượng.

Vì tôi có một số kế hoạch cho vùng chứa DI yêu cầu không phụ thuộc vào lớp triển khai khi đăng ký giao diện, vấn đề này sẽ được giải quyết trong tương lai nhưng không sớm.

Cập nhật (2012/11/08):

Kể từ r522 có thể đăng ký các loại giao diện theo cách sau:

GlobalContainer 
    .RegisterType<ISomeObject> 
    .DelegateTo(
    function: ISomeObject 
    begin 
     Result := CreateComObject(CLASS_SomeObject) as ISomeObject; 
    end) 
    .AsSingletonPerThread; 

Trong ví dụ này nó sẽ đăng ký ISomeObject như dịch vụ và giao diện bất kỳ với một GUID nó kế thừa từ.Ngoài ra, bạn có thể thêm các giao diện khác bằng cách gọi Implements<T> nhưng không giống như các lớp sẽ không có xác nhận tại thời điểm đăng ký nếu trường hợp được xây dựng thực sự thực sự hỗ trợ giao diện đó vì nó không thể thực hiện được. Hiện tại bạn sẽ nhận được nil khi gọi Resolve<T> với loại dịch vụ không được hỗ trợ. Nó có thể làm tăng ngoại lệ trong tương lai.

+3

Cảm ơn bạn đã cập nhật! Thật tuyệt vời! :) –

1

Không giống như kiến ​​trúc của khung công tác mùa xuân hiện đang hỗ trợ nó nhưng chắc chắn khả thi của nó. Nó đã được suggested trong nhóm hỗ trợ spring4d và có quan tâm đến ý tưởng này.

Có một lớp học chung là TFactory trong Spring.DesignPatterns có thể được sử dụng trong gói CreateComObject/COCreateInstance.

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