Bạn có thể chuyển thành phần COM trong một cuộc gọi hàm, dưới dạng con trỏ. Vì vậy, giả sử bạn thực hiện một đối tượng trong EXE của bạn, và tải một đối tượng COM khác từ một DLL, bạn có thể truyền đối tượng dựa trên EXE cho đối tượng từ tệp DLL. Đối tượng được tải sẽ cần hỗ trợ giao diện có chức năng chấp nhận con trỏ, ví dụ:
interface ILoadedObject
{
HRESULT GiveObject(IUnknown *pObj);
};
Nếu đối tượng DLL-based thực hiện điều đó, bạn có thể gọi nó từ EXE của bạn và vượt qua nó một đối tượng mà không được đăng ký bất cứ nơi nào, vì vậy không có cần phải đăng ký các đối tượng trong một EXE để đạt được điều này .
Yêu cầu duy nhất là thực hiện đúng IUnknown
: không phá hủy đối tượng cho đến khi Release
được gọi đúng số lần và đảm bảo rằng có thể sử dụng QueryInterface
để chuyển giữa một bộ giao diện cố định trên đối tượng và truy vấn đó cho IUnknown
luôn trả về cùng một địa chỉ.
Mặt khác, bạn có thể đăng ký EXE như một máy chủ của các đối tượng, nhưng điều đó giới thiệu rất nhiều phức tạp; COM đã bắt đầu chạy EXE và sau đó gửi tin nhắn thông qua hàng đợi tin nhắn Windows. Điều này chỉ được sử dụng rộng rãi cho OLE; nó có thể khá mỏng manh.
Cập nhật
Một giải pháp hoàn chỉnh hơn là để xác định một cách tiêu chuẩn để tạo ra một thể hiện của một kiểu đối tượng, nhưng để cho phép các EXE để xác định cách thức hoạt động. Các EXE sẽ thực hiện:
interface IComponent;
interface IEnvironment : IUnknown
{
HRESULT CreateInstance(REFCLSID clsid, IComponent **ppNew);
}
Mỗi thành phần phải hỗ trợ giao diện này:
interface IComponent : IUnknown
{
HRESULT SetEnvironment(IEnvironment *pEnv);
}
Bây giờ, để có được những hành vi tiêu chuẩn nơi EXE muốn sử dụng registry để tìm thành phần, nó có thể thực hiện các CreateInstance
phương pháp như sau:
HRESULT Env::CreateInstance(REFCLSID clsid, IComponent **ppNew)
{
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
__uuidof(IComponent), (void **)&ppNew);
if (FAILED(hr))
return hr;
(*ppNew)->SetEnvironment(this);
return S_OK;
}
Nhưng dĩ nhiên nó có thể thay đổi điều này và "tiêm" một số thành phần. Vì vậy, thay vì (hoặc ngoài) đăng ký, một tập tin cấu hình có thể được sử dụng. Hoặc (như bạn đã hỏi) EXE có thể có sẵn trong triển khai của một số thành phần:
Bởi vì mỗi thành phần được thông báo về môi trường khi nó được tạo ra, nó có thể sử dụng môi trường để tạo ra các thành phần thêm:
// inside some component:
HRESULT Comp::SetEnvironment(IEnvironment *e)
{
m_env = e; // using a smart pointer for ref-counting
return S_OK;
}
// in some method of the component
ComPtr<IComponent> button;
m_env->CreateInstance(CLSID_Button, &button);
// now query button for more useful interface...
Vì vậy, bất cứ khi nào một thành phần được tạo ra, môi trường (được xác định trong EXE) có thể kiểm soát chính xác cách thức thực hiện thành phần được tìm thấy. Mọi sáng tạo đều đi qua EXE.
Điều này đôi khi được gọi là "tiêm phụ thuộc" hoặc "đảo ngược kiểm soát".
Tôi không chắc chắn đoạn đầu tiên là đúng như, trong bài viết nó liên kết đến, chỉ đề cập đến của các máy chủ EXE ngoài quy trình là để nói rằng họ không thể được sử dụng với COM đăng ký miễn phí. Chủ đề này cũng hữu ích và chỉ ra các vấn đề với ROT mà COM đăng ký miễn phí dường như bỏ qua để quản lý: http://social.msdn.microsoft.com/Forums/vstudio/en-US/3849f22d-c8b8-429e- a03a-37601411acec/registrationfree-exe-com-server- Dường như chỉ có các đối tượng COM cơ bản, trong quá trình (cũng không nâng cao) được hỗ trợ bởi cơ chế miễn phí và cho bất kỳ thứ gì lạ hơn bạn phải cuộn của riêng bạn . –
Câu trả lời chỉ có liên kết thực sự tồi vì liên kết có xu hướng biến mất ... giống như câu trả lời trong câu trả lời này. – Stephane