Get a COM object from another COM object - com

I have to get the Command Interface and Status interface as given below from VBScript in an ASP Page. The COM will be deployed in a Windows CE device
Set polyColdObj=CreateObject("PolyCold.Main")
Set statusObj = polyColdObj.StatusInterface()
Set commandObj = polyColdObj.CommandInterface()
I am going to use Atl for developing the COM object. My doubts are
What should be the signature of `StatusInterface` and `CommandInterface` in ATL COM?
Should I call AddRef() on the `StatusInterface` and `CommandInterface` before returning the object to the automation client(VBScript)?
Should I create the object each time StatusInterface is called or when 'PolyCold.Main' object is created?
Is this the standard way of giving names for `StatusInterface` and `CommandInterface`?

What should be the signature of
StatusInterface and CommandInterface
in ATL COM?
By default, ATL methods will return an HRESULT value. In order to achieve what you want you can create a method without parameters using the ATL wizard. Then you can modify your IDL file manually, and the corresponding implementation, so that your method returns an CommandInterface instead. Using this approach your IDL file will look like this:
[id(1)] CommandInterface* GetCommandInterface();
And the method declaration on your ATL class will be:
CommandInterface* GetCommandInterface();
Another option could be to use one output parammeter of type CommandInterface**. A quick test using the ATL wizard shows that your IDL file will look like this:
[id(1)] HRESULT StatusInterface([out] CommandInterface** outStatusInterface);
Should I call AddRef() on the
StatusInterface and CommandInterface
before returning the object to the
automation client(VBScript)?
I would say yes, since VBScript/ASP is supposed to call Release() when your local variable goes out of scope.
Should I create the object each time
StatusInterface is called or when
'PolyCold.Main' object is created?
This one is up to you. Only you know the details and needs of your design.
Is this the standard way of giving
names for StatusInterface and
CommandInterface?
If these "elements" are supposed to be interface types, then I would say no. In general interfaces are named with a capital I as first letter. I would use IStatus and ICommand for example. Probably with some more info saying what kind of command and status, but this is argumentative.

Related

How to put class dynamically in <>

I know there are various capabilities in Java with reflection.
For example:
Class<?> clazz = Class.forName("java.util.Date");
Object ins = clazz.newInstance();
I wonder if I could pass class dynamicaly in some method declaration in <> tags (or there is other way to do it if it must be fixed). I would like to change that class declaration dynamicaly; because I would like to write generic method for all types of classes.
In there, I have this:
List<Country>
Can I write it something diffrent with reflection? For example can it be somehow be achieved to pass class as parameter (or how else should be this done):
List<ins>
? I would appreciate examples.
This cannot be done because generics are a compile time feature. Once code is compiled, the only place where generics are exists are at method signatures, and they are only used for compiling new code.
When working with reflection, you are basicly working with raw types, and need to code according to that, that means, you can cast the returned result of newInstance() to the list type your need, for example:
List<Country> ins = (List<Country>)clazz.newInstance();
This is a safe operation to do, because you know at that point its empty, and isn't passed to any outside code.
I don't think this is possible. Generics in Java are implemented in a way that prohibits runtime access.
Generics are there so that the compiler can verify correct typing, but are no longer present at runtime (this is called "type erasure"). Reflection deals with the runtime representation of types only. As far as I know the only case where reflection has to deal with generics is to find out "fixed" type parameters of sub-classes, e.g. when you have class Bar<T> and class Foo extends Bar<String>, you can find out that the T of Bar is fixed to String in Foo using reflection. However, this is information found in the class file, too. Except that, reflection can only see or create raw-types.

Late Binding in VB

From what I have read so far, late binding is defining a variable as Object and then assigning it to the actual object later which is actually done at run time. I don't understand the point to that. Maybe this is the Java in me, but doesn't that limit the functionality to what is just in Object? It is like saying, "I want the potential of the extra stuff, but I don't want to have access to it." Is there an actual purpose for late binding in VB, or Java for that matter, that I'm overlooking?
You have it backwards. By using early binding you are limiting yourself to just the members of the type of the variable. With Option Strict On, a variable declared as type Object will only allow you access to members of type Object, regardless of the type of the actually object it refers to. With Option Strict Off, you can access a member of any name on a variable of type Object and the compiler won't complain. It's only at run time that any type checking is done so, as long as the actual object assigned to the variable has a member with that name, the code will run.
Probably the most common use for late binding is Office Automation. There are other options now but, in the past, if you referenced an Office library and used the specific types it contained, facilitating early binding, then you were limited to that specific version of Office. In order to support multiple versions, you had to forgo the reference, declare all your variables as type Object and use late binding. As long as the version of Office present at run time included the specified members on the objects used, the code would run without issue.
By the way, late binding doesn't require using type Object, although it is probably the most common. It just means that the reference is a less derived type than the object and you use a member of the object's type that the reference's type doesn't have, e.g. you use type Control and then use a member specific to type Button.
What I seen - some early .NET adapters-developers were doing is - they were using late binding instead on interfaces. They would declare two or more types
Public Class Handler1
Public Sub Execute()
' do something
End Sub
End Class
Public Class Handler2
Public Sub Execute()
' do something else
End Sub
End Class
And they would stick this thing into session object
If someting = 1 Then
Session("Handler") = New Handler1()
Else
Session("Handler") = New Handler2()
End If
And then, to process something they would do
Session("Handler").Execute()
There we go. This is not pretty or smart. But that was instead of proper programming like this (Imagine handlers implement IHandler interface with method Execute)
Dim h As IHandler = TryCast(Session("Handler"), IHandler)
If h IsNot Nothing Then
h.Execute()
End If
Here is where downfall of late binding starts: In the case of late binding, someone, somewhere, can rename a method Execute and compile code nicely. Release. And only then, at runtime, get a problem.
Late binding was good when we used to deal with interop and COM. Other than this, it is detrimental.

Can define variables as references to local classes defined in another program?

I have a program ZPROG1_TEST where I define a local class LCL_PROG1_HELPER.
I have a second program ZPROG2_TEST where I'd like to define a variable reference to this class.
Isn't there a syntactic possibility for me to do this?
Or could this be in theory doable with the RTTI classes like CL_ABAP_CLASSDESCR ?
EXTRA
Why I'd like to do this is because I have a custom form ZMM_MEDRUCK that needs to know if the ME32N Document it's printing has been changed but not saved.
I've figures out the exact objects whose properties I need to interogate, but some of them are defined at design time as common interfaces, like IF_SERIALIZABLE_MM, and I need to cast them to the local classes whose instances I know these objects are going to be, like \FUNCTION-POOL=MEGUI\CLASS=LCL_APPLICATION.
I could of course try a dynamic method call and not care about anything, but since i'm here i thought i'd ask this thing first.
You could do it like that.
REPORT ZPROG1_TEST.
INTERFACE lif_prog1_helper.
METHODS:
test.
ENDINTERFACE.
CLASS LCL_PROG1_HELPER DEFINITION.
PUBLIC SECTION.
INTERFACES:
lif_prog1_helper.
ALIASES:
test FOR lif_prog1_helper~test.
ENDCLASS.
CLASS LCL_PROG1_HELPER IMPLEMENTATION.
METHOD test.
WRITE / sy-repid.
ENDMETHOD.
ENDCLASS.
REPORT ZPROG2_TEST.
DATA: g_test TYPE REF TO object.
START-OF-SELECTION.
CREATE OBJECT g_test TYPE ('\PROGRAM=ZPROG1_TEST\CLASS=LCL_PROG1_HELPER').
CALL METHOD g_test->('TEST').
CALL METHOD g_test->('LIF_PROG1_HELPER~TEST').
As far as I know, this is not possible. Accessing the local class dynamically is easy (well, relatively easy), but referring to it statically - not as far as I know. You'll probably have to call the methods dynamically.

How can I use an ITypeInfo pointer to get the name of the type?

Should be a simple question, but searching the documentation is driving me nuts. Suppose I have an ITypeInfo pointer for a coclass or an interface. How do I get the name of that class or interface?
Ok. It did turn out to be pretty simple. You just need to call the ITypeInfo.GetDocumentation method with the member id set to MEMBERID_NIL (−1). Like so:
CComBSTR typeName;
hr = typeInfo->GetDocumentation( MEMBERID_NIL, &typeName, NULL, NULL, NULL );
If you're programming in .NET, the above is conveniently performed for you by the Marshal.GetTypeInfoName method:
// using System.Runtime.InteropServices;
string typeName = Marshal.GetTypeInfoName(typeInfo);
The short answer: you can't using ITypeInfo. You can obtain the prog ID of class using the Win32 ProgIDFromCLSID API. In COM the name of the underlying C++, Visual Basic or .NET class implementing the COM interface or co-class is practically meaningless. Only interface IDs, class IDs and programmatic IDs have any significance beyond the source code of your co-class's implementation: only these can be used for activating COM objects using CoCreateInstance et al and runtime casting using QueryInterface.

Casting Early bound object type into Late bound object type

I've got a piece of code in a project (MyProject) that contains early bound object from a referenced assembly (We'll call it CommonAssembly):
Dim myObject As CommonAssembly.MyEarlyBoundType
now I have another assembly that is dynamically loaded because it is not present in all projects:
Dim myLateBoundObject As Object = AppDomain.CurrentDomain.CreateInstanceAndUnwrap("Utils", "Utils.MyLateBoundType")
MyLateBoundType derives from CommonAssembly.MyEarlyBoundType, and I want to cast myObject to myLateBoundObject and then programmatically invoke the additional member methods
via reflection.
I'd have thought that by extracting the type of myLateBoundOject and casting myObject into myLateBoundObject, that'd work, but both CType() and DirectCast() methods won't accept the extracted type citing a "Keyword does not name a type" error:
myLateBoundObject = DirectCast(myObject, GetType(myLateBoundObject))
I'm not entirely sure why a dynamically loaded type cannot be used against the DirectCast (pretty sure it's not type saftey checked?) method, since if Utils.MyLateBoundType was referenced in "MyPrjoect", I could execute:
myLateBoundObject = DirectCast(myObject, Utils.MyLateBoundType)
without any problems - but this is not a dynamic solution.
Any suggestions?
Cheers,
Yum.
Yeah, that's not going to work like that. Any attempt you'd make in your code to cast to the dynamically loaded type will make your program have a non-dynamic dependency on the assembly.
You should use an interface type. Declare that type, with all the properties and methods you'd want to have available in your main program, in a separate assembly. Both your main program and your plug-in will have a dependency on it. The dynamic type should inherit it to provide the implementation. You can now cast the return value of CreateInstance to that interface type.