2

I will describe the problem as simple as i can.

alright, here goes the problem;

Lets suppose we have a com component class with 3 of constructors where a constructor takes at least two of parameters. As we already know we instantiate the components via QueryInterface rather calling the classes' constructors therefore it seems it is not possible for a com client to set the constructor's parameters.

alright, here goes the question;

What is the best practical approach to allow a com client to instantiate a com component which requires at least two of parameters to be initialized?

5 Answers 5

4

Instead of directly returning object instances, your QueryInterface call can return factories. For example, instead of:

// implements IMyClass1 interface
return new MyClass1();

You would do:

// pointer to member that implements IMyClassFactory interface
return &m_myClassFactory;
// this could also be a static class instead of an object instance

The IMyClassFactory interface would have a create method that takes in the constructor arguments and returns the ultimate MyClass1 instance.

Sign up to request clarification or add additional context in comments.

Comments

3

If its a pure COM component, the standard way of handling this is to implement Initialize(foo, bar) methods instead of separate constuctors and then call that immediately after COM instantiation. If the object has no sensible default state, then you can make it a member variable (pointer) in a COM object. From that COM object you will have your Initialize(foo, bar) functions. In each of these initialize function the correct version of your object will be instantiated. Every pass through function in your COM wrapper will need to check that your object is not NULL and return an appropriate HRESULT if it is.

Comments

2

One option would be to use a factory object; the creation functions would be all on the (stateless) factory object (on a different interface, of course), and pass back an initialized instance of the real object.

Comments

0

I like both Ates Goral's answer and Steve's and have upvoted both. Normally I would leave it at that, but I feel that this time I have to spell out my full take.

The "best", "right", "purest", "canonical" way to do this is undoubtely the factory pattern, as described by Ates. If you want to create a clean API, that's the road, hands down.

But... most of us are not busy creating public APIs for commercial products. For small internal projects with non-public APIs, I just want to get the job done. Having to implement an extra object just so I can expose a single factory method sounds rather overkill (particularly in C++). In most practical cases, I would just go for an Initialize(foo, bar) method as described by Steve. I would then make sure that every non-trivial method checks to see if the object has been initialized and returns a failure HRESULT if not.

Comments

0

When I write COM servers, I don't usually allow my components to be instantiated by CoCreateInstance. Instead I export some bare functions (these can be described in IDL as well inside a module) from my DLL which accept the constructor parameters and return an interface pointer to the newly created object in an output parameter.

3 Comments

Curious. How will one use such COM component via DCOM/COM+?
@sharptooth: Such components can be used in-process, which is useful in many applications but by no means all. I'm not sure if midl can generate proxies for module members, I never needed that. I basically just used COM as a friendly way to give RAD code (e.g. Classic VB) access to high-performance native functions, and high-performance demands in-process.
I see. MIDL will only generate proxies for interfaces in the IDL file and you won't be able to start an outproc server (either directly or as a COM+ surrogate) and get a hold on any of those entry function - COM subsystem must do that itself. So this just won't work. The only way to make that work is to have a class factory that can be created via CoCreateInstance().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.