C# dynamic & COM objects - c#

from here
A very big advantage of dynamic types comes when you start to think
about C#’s relationship with external and non-native objects – COM
objects in particular. In this case a dynamic type is resolved using
the COM IDispatch interface and this in turn means that you can use
COM objects “raw”, i.e. without a Primary Interop Assembly (PIA). As
many COM objects make extensive use of the variant type, which can
store any of a number of standard data types, being able to use
dynamic types in place of variants is a big simplification.
I already know how dynamic is used in C# , However - I want to know how it is done.(generally with COM)
looking at Office COM object model example :
(Excel.Range)excel.Cells[1,1]).Value= "some string"
The cast has to be included because the PIA uses object types to represent variants
Now (2010 ...), with dynamic it can be done with :
excel.Cells[1,1].Value= "some string"
But
An object can provide its binding semantics by implementing DynamicObject
such as :
public class MyClass: DynamicObject
{
public override bool TryInvokeMember ( InvokeMemberBinder binder, object[] args, out object result)
{
...
}
}
So my question :
Did MS [changed] or [added code] or [now-inherit-DynamicObject] the COM objects in order to allow excel.Cells[1,1].Value= "some string" to work ?
Did they re-build this whole mechanism ?

No, the secret sauce is COM here. This is done with only 2 interfaces and 5 methods. The first one is IUnknown, an interface implemented by all COM objects. It has 3 methods:
AddRef(), increments the reference count on a COM object. This is a memory management function, as long as the count is non-zero the object stays alive. Storing a pointer to a COM object requires calling IUnknown.AddRef().
Release(), decrements the reference count. The opposite of AddRef and must be called when an interface pointer is no longer used. The COM object is released when the count reaches zero. This function is the core reason behind the rather infamous use of Marshal.ReleaseComObject() in .NET code that uses Office. It normally gets called by the finalizer of a COM wrapper.
QueryInterface(), asks the COM object to return a pointer to another interface. In the scope of this question, that's how C# gets the IDispatch interface pointer.
The IDispatch interface is the one that implements dynamic binding, the rough equivalent to DynamicObject. It has 4 methods, 2 of which are important in this context:
GetIDsOfNames(), converts a name to a number, a dispid. This is how an identifier in a C# program can be matched to a method or property name on the COM object.
Invoke(), calls the COM method of property getter/setter, using the dispid
That's the big picture, use the MSDN Library if you want to know more about these interfaces.

The DLR (which is what the dynamic keyword offers interface to) uses "binders" to interface with the dynamic object proper (there is a C# binder, VB binder, COM binder etc.). The COM binder is a separate component that uses the "traditional" COM interop, which is not replaced and can still be used without dynamic. It was enhanced for .NET 4.0, but not just for dynamic.

You can use dynamic with any type. You need to derive from DynamicObject only when you want your classes to provide a dynamic interface.
The following line works, without requiring DateTime to inherit from DynamicObject:
dynamic myDate=DateTime.Now;
EDIT
As to how COM+ supports dynamic binding - it always did. In fact, the documentation explains exactly how this is done.
COM always supported its own kind of dynamic binding through the IDispatch interface which works roughly like DynamicObject. IDispatch allows an object to respond to queries for specific interfaces and the methods it supports.
dynamic can use the IDispatch interface for raw COM objects, where you don't have a type library or a proxy. In other cases, dynamic will call the proxy methods without going through the IDispatch interface.
Dynamic binding in COM introduces a performance hit, due to the multiple calls needed to extracta a specific interface and invoke its methods. In the VB6 days people tried to minimize or eliminate the use of dynamic binding by using type libraries. This is sound advice for .NET as well.

Related

Unable to cast COM object of type 'System.__ComObject' to class type AgentInfo

I have two C# projects, one is a dll and another is a windows forms app.
I have a CoClass defined in the dll as follows` '
[ComVisible(true),
Guid("1620BE13-A68F-4FA3-B5C8-31092D626CDA"),
ProgId("AgentDLLServer.AgentInfo"),
ClassInterface(ClassInterfaceType.AutoDispatch),
ComSourceInterfaces(typeof(IAgentInfoEvents))
]
public class AgentInfo : _IAgentInfo {}
It implements the interface _IAgentInfo, which is defined as follows
[
ComVisible(true),
Guid("CF803265-AE9D-4308-B790-560FCF63DD4C"),
InterfaceType(ComInterfaceType.InterfaceIsDual)
]
public interface _IAgentInfo{}
Both are defined in a dll, which is registered successfully using
regasm /tlb
In another C# windows client application, I try to access AgentInfo by casting an object obtained from either the Running Object Table, or from another interface as follows`
_IAgentInfo info =(_IAgentInfo) RotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");`.
where the above code retrieves the object from the ROT
or , I have another interface obtained from the ROT, as defined as follows
[
ComVisible(true),
Guid("9B539A5F-5671-48AD-BF9B-7A9AF150CE39"),
InterfaceType(ComInterfaceType.InterfaceIsDual)
]
public interface _IAgentDLLServer
{ AgentInfo GetAgentInfo();}
where I get a reference to the interface _IAgentDLLServer from the ROT, and then call the method GetAgentInfo() on it
`_IAgentDLLServer server= (_IAgentDLLServer)RotNativeMethods.GetObject("BizBrainAgentService.AgentServer") `AgentInfo info=server.GetAgentInfo();
I can cast it to _IAgentInfo, but when I try to cast the returned object to AgentInfo, as follows
AgentInfo info =(_IAgentInfo) rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");
I get the following error
Unable to cast COM object of type 'System.__ComObject' to class type 'AgentDLLService.AgentInfo'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
I tried the following solutions
a. STAThread on the main method, because a post suggested that the thread on
which this object was running did not have access to type information
as per
Why cannot I cast my COM object to the interface it implements in C#?
b. Changed the app config file as follows
<configuration>
<startup>
<supportedRuntime version="v4.0.30319" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
and the version matches that in the InProcServer32 of the registry
HKEY_CLASSES_ROOT\Wow6432Node\CLSID\{1620BE13-A68F-4FA3-B5C8-31092D626CDA}\InprocServer32\1.0.0.0\RuntimeVersion,
as per
.NET Framework 4.5 is default and .NET Framework 3.5 is optional
andThe strange case of System.InvalidCastException (“Unable to cast COM object of type ‘System.__ComObject’ to class type System.Windows.Forms.UserControl”) showing toolwindow
c. I tried the ComImport method
[ComImport,
Guid("1620BE13-A68F-4FA3-B5C8-31092D626CDA")]
public class AgentInfo { }
in the class where I want to use this object, as per
A lean method for invoking COM in C#
d. Double casting the object
AgentInfo info=(AgentInfo)(object)rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");
as per
Why can't I cast this interface to a concrete class?
e Using the as operator
object obj=rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");
AgentInfo info=obj as AgentInfo
f. Implementing the IProvideClassInfo and IProvideClassInfo2 interfaces [Importing them using the ComImport attribute] on the agentInfoClass
After all these attempts, I wonder whether it is possible to return a COM CoClass from a COM Interface, or the Running Object Table, as opposed to a COM Interface.
Also, another question is, is AgentInfo being treated as a C# /dot net type instead of a COM type, according to the message. Is this really so? In that case, the cast would fail.
I am aware that returning a CoClass rather than an interface may not be good practice, but I need to be able to listen to events from the AgentInfo object, and that does not appear to be possible from interfaces.
How is BizBrainAgentService.AgentInfo defined? What methods of AgentInfo you need access to and ones not available in _IAgentInfo?
AgentInfo info =(_IAgentInfo) rotNativeMethods.GetObject("BizBrainAgentService.AgentInfo");
You seem to be casting BizBrainAgentService.AgentInfo to an interface _IAgentInfo which will be fine as long as BizBrainAgentService.AgentInfo implements it.
You can't cast this back to AgentInfo because the object type is still
BizBrainAgentService.AgentInfo.
In COM, QueryInterface is used to navigate to a different interface https://learn.microsoft.com/en-us/cpp/atl/queryinterface
The error you see explains this -
Unable to cast COM object of type 'System.__ComObject' to class type 'AgentDLLService.AgentInfo'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
Would COM event sink implementation using Connection Points help instead?

C# COM visible type: is GUID needed?

I have the following class:
[ComVisible(true)]
[Guid("F8351C66-7F0E-4E38-AE64-9A262202E230")]
[ProgId("CarProject.CarFactory")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class CarFactory
{
public CarFactory()
{}
[DispId(0)]
public Car CreateCar(int tyres)
{
return new Car(tyres);
}
}
[ComVisible(true)]
[Guid("83f622b9-74f4-4700-9167-52c4ce9e79aa")]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class Car
{
[DispId(0)]
public int NumberOfTyres { get; private set; }
public Car(int tyres)
{
this.NumberOfTyres = tyres;
}
}
The Car object is created by a factory therefore the COM client uses only the _Car interface autogenerated. Note that there isn't a default constructor so the class cannot be instantiated through COM.
My question is: is the Guid attribute needed? I cannot find its value in the registry.
No, it is not needed since it will never be used. In fact, it is never needed and applying [Guid] is a pretty bad practice.
There are several other problems with this declaration style, discussing them all requires me to write a book and that is not very practical. It will be a lot easier for you to look at the decompiled type library so you can see what the client compiler sees. Use the Visual Studio Developer Command prompt, generates the type library if you don't have one yet with Tlbexp.exe. Run Oleview.exe, File > View Typelib and select the .tlb file. Highlighting the relevant details you now see:
importlib("mscorlib.tlb");
This is pretty awkward, the client programmer doesn't just have to add a reference to your type library but also the .NET type library for mscorlib.dll. Stored in the c:\windows\microsoft.net\framework\v4.0.30319 directory. Or v2.0.50727, the older version. Pretty unintuitive and does not often come to a good end. Note how you got in trouble with it in your previous question. Read on to find out why this happened.
[
odl,
uuid(BD7A2C0E-E561-3EBC-8BB7-1C72EE61D5B0),
hidden,
dual,
nonextensible,
oleautomation,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ClassLibrary171.Car")
]
interface _Car : IDispatch {
// etc..
}
This is the auto-generated "class interface", you already now about it. This is the one that the client compiler actually uses to make calls. Note the [uuid] attribute, same as the [Guid] attribute in C#. But it has a pretty random value. It was auto-generated, like the interface was. So using [Guid] in your declaration did not actually accomplish anything at all.
The [hidden] attribute as well as the leading underscore on the interface name tell an type browser tool (like Object Browser in VS) to hide the declaration. Made it important to use OleView to see the details. Otherwise a quirk that goes back to the kind of languages that don't have support for interfaces, old versions of Visual Basic (like VB6 and VBA) and scripting languages (like VBScript and JavaScript) being the primary examples. Such languages need to emulate them by making the interface look like a class, the only reason why you'd consider exposing the class at all.
[
uuid(83F622B9-74F4-4700-9167-52C4CE9E79AA),
version(1.0),
noncreatable,
custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, "ClassLibrary171.Car")
]
coclass Car {
[default] interface _Car;
interface _Object;
};
Note the [noncreatable] attribute. The type library exporter could see that client code can never create a Car instance since it has no default constructor. That in turn helps Regasm.exe figure out that registering the CLSID for Car is not necessary, that's why you could not find it back in the registry.
And note the _Object interface. Appeared because every .NET class derives from System.Object. And, likewise, the _Car interface also has the methods of Object (ToString, Equals, GetHashCode, GetType) since Car inherited them. This is how you ended up with the dependency on mscorlib.tlb. They might be useful to the client programmer, but that is not common and you generally certainly don't want to have to document them. The less you expose, the better.
Long story short, this happened because you used ClassInterfaceType.AutoDual. It is a convenience, but not a very good one and Microsoft strongly discourages it, recommending ClassInterfaceType.AutoDispatch instead. But that's only useful for scripting languages.
You avoid all this by declaring the ICar interface explicitly instead of letting the type library exporter generate it for you. It needs to be [ComVisible(true)] and the class needs to implement it. Now you can use ClassInterfaceType.None.
And now you can give the interface a [Guid]. But beware the bad practice this is, COM demands that interfaces are immutable. Once you exposed one in the wild, you can never change it again. Very important, COM has a nasty DLL Hell problem, caused by registration being machine-wide and you in general have no guarantee whatsoever that you can get the client programs recompiled. The crashes this can cause a very hard to diagnose. If you do have to change it then the interface needs a new [Guid] so both the old and the new interface can co-exist. Most trivially done by simply omitting the attribute entirely, the CLR already auto-generates it. Using [Guid] does allow creating interfaces that are binary compatible with an old interface declaration, but that's pretty hard to do correctly.

Is there any advantage in disallowing interface implementation for existing classes?

In static OOP languages, interfaces are used in order to declare that several classes share some logical property - they are disposable, they can be compared to an int, they can be serialized, etc.
Let's say .net didn't have a standard IDisposable interface, and I've just came up with this beautiful idea:
interface IDiscardable { void Discard(); }
My app uses a lot of System.Windows.Forms, and I think that a Form satisfies the logical requirements for being an IDiscardable. The problem is, Form is defined outside of my project, so C# (and Java, C++...) won't allow me to implement IDiscardable for it. C# doesn't allow me to formally represent the fact that a Form can be discarded ( and I'll probably end up with a MyForm wrapper class or something.
In contrast, Haskell has typeclasses, which are logically similar to interfaces. A Show instance can be presented (or serialized) as a string, Eq allows comparisons, etc. But there's one crucial difference: you can write a typeclass instance (which is similar to implementing an interface) without accessing the source code of a type. So if Haskell supplies me with some Form type, writing an Discardable instance for it is trivial.
My question is: from a language designer perspective, is there any advantage to the first approach? Haskell is not an object oriented language - does the second approach violates OOP in any way?
Thanks!
This is a difficult question, which stems from a common misunderstanding. Haskell type classes (TC), are said to be "logically similar" to the interfaces or abstract classes (IAC) from object-oriented programming languages. They are not. They represent different concepts about types and programming languages: IAC are a case of subtyping, while TC is a form of parametric polymorphism.
Nevertheless, since your questions are methodological, here I answer from a methodological side. To start with the second question:
does the second approach [that of extending the implementation of a class outside the class] violate OOP in any way
Object oriented programming is a set of ideas to describe the execution of a program, the main elements of an execution, how to specify these elements in the program's code, and how to structure a program so as to separate the specification of different elements. In particular, OOP is based in these ideas:
At any state of its execution, a process (executing program) consists of a set of objects. This set is dynamic: it may contain different objects at different states, via object creation and destruction.
Every object has an internal state represented by a set of fields, which may include references to other related objects. Relations are dynamic: the same field of the same object a may at different states point to different objects.
Every object can receive some messages from another object. Upon receiving a message, the object may alter its state and may send messages to objects in its fields.
Every object is an instance of a class: the class describes what fields the object has, what messages it can receive, and what it does upon receiving a message.
In an object a, the same field a.f may at different states point to
different objects, which may belong to different classes. Thus, a needs not to know to what class those objects b belong; it only needs to know what messages do those objects accept. For this reason, the type of those fields can be an interface.
The interface declares a set of messages that an object can receive. The class specifies explicitly what interfaces are satisfied by the objects of that class.
My answer to the question: in my opinion yes.
Implementing an interface (as suggested in the example) outside a class breaks one of these ideas: that the class of the object describes the complete set of messages that objects in that class can receive.
You may like to know, though, that this is (in part) what "Aspects", as in AspectJ, are about. An Aspect describes the implementation of a certain "method" in several classes, and these implementations are incorportated (weaved) into the class.
To answer back the first question, "is there any advantage to the first approach", the answer would be also yes: that all the behaviour of an object (what messages it answers to) is only described in one place, in the class.
Well, the Haskell approach does have one disadvantage, which is when you write, for example, two different libraries that each provides its own implementation of interface Foo for the same external type (provided by yet a third library). In this case now these two libraries can't be used at the same time in the same program. So if you call lack of a disadvantage an advantage, then I guess that would be one advantage for the OOP language way of doing this—but it's a pretty weak advantage.
What I would add to this, however, is that Haskell type classes are a bit like OOP interfaces, but not entirely like them. But type classes are also a bit like the Strategy and Template Method patterns; a type class can be simulated by explicitly passing around a "dictionary" object that provides implementations for the type class operations. So the following Haskell type class:
class Monoid m where
mempty :: m
mappend :: m -> m -> m
...can be simulated with this explicit dictionary type:
data Monoid_ m = Monoid_ { _mempty :: m, _mappend :: m -> m -> m }
...or an OOP interface like this:
interface Monoid<M> {
M empty();
M append(M a, M b);
}
What type classes add on top of this is that the compiler will maintain and pass around your dictionaries implicitly. Sometimes in the Haskell community you get arguments about when and whether type classes are superior to explicit dictionary passing; see for example Gabriel Gonzalez's "Scrap your type classes" blog entry (and keep in mind that he doesn't 100% agree with what he says there!). So the OOP counterpart to this idea would be instead of extending the language to allow external implements declarations, what are the drawbacks to just explicitly using Strategies or Template Methods?
What you are describing is the adapter pattern. The act of composing an object in a new type that provides some additional behavior to the underlying type, in this case the implementation of another interface.
As with so many design patterns, different languages choose different design patterns to incorporate directly into the language itself and provide special language support, often in the form of a more concise syntax, while other patterns are need to be implemented through the use of other mechanisms without their own special syntax.
C# doesn't have special language support for the adapter pattern, you need to create a new explicit type that composes your other type, implements the interface, and uses the composed type to fulfill the interface's contract. Is it possible for them to add such a feature to the language, sure. Like any other feature request in existence it needs to be designed, implemented, tested, documented, and all sorts of other expenses accounted for. This feature has (thus far) not made the cut.
What you are describing is called duck typing, after the phrase "If it walks like a duck, swims like a duck, and quacks like a duck, then it's a duck".
C# actually does allow dynamic (run-time) duck typing through the dynamic keyword. What it doesn't allow is static (compile-time) duck typing.
You'd probably need somebody from Microsoft to come along and provide the exact reasons this doesn't exist in C#, but here are some likely candidates:
The "minus 100 points" philosophy to adding features. It's not just enough for a feature to have no drawbacks, to justify the effort put into implementing, testing, maintaining and supporting a language feature, it has to provide a clear benefit. Between the dynamic keyword and the adapter pattern, there's not many situations where this is useful. Reflection is also powerful enough that it would be possible to effectively provide duck typing, for example I believe it'd be relatively straightforward to use Castle's DynamicProxy for this.
There are situations where you want a class to be able to specify how it is accessed. For example, fluent APIs often control the valid orderings and combinations of chained methods on a class through the use of interfaces. See, for example, this article. If my fluent class was designed around a grammar which stated that once method A was called, no other methods except B could be called, I could control this with interfaces like:
public class FluentExample : ICanCallAB
{
public ICanCallB A()
{
return this;
}
public ICanCallAB B()
{
return this;
}
}
public interface ICanCallA
{
void A();
}
public interface ICanCallAB : ICanCallA
{
void B();
}
Of course, a consumer could get around this using casting or dynamic, but at least in this case the class can state its own intent.
Related to the above point, an interface implementation is a declaration of meaning. For example, Tree and Poodle might both have a Bark() member, but I would want to be able to use Tree as an IDog.

What are the CoClass interfaces in imported assemblies exactly for?

Importing a basic type library using the tlbimp.exe tool allways creates an interface for each coclass. For example this IDL-description
interface IFoo : IUnknown
{
HRESULT DoSomething();
}
coclass Bar
{
[default] interface IFoo;
}
results in:
an interface IFoo as a representation of the COM interface,
a class BarClass as a representation of the COM coclass and
an interface Bar, annotated with the CoClassAttribute.
Where the GUIDs of Bar and IFoo are equal. The MSDN states on this topic:
This interface has the same IID as the default interface for the coclass. With this interface, clients can always register as event sinks.
That's the only thing I found on this topic. I know that, due the CoClassAttribute, I can use the interface to create instances of the actual class. I also know that (practically) I can simply use BarClass to create a new instance of the class. What I don't understand is, why the import process generates the Bar interface, even if the coclass does not define an event source and thus no event sink can be connected to it.
Would it be possible to remove the Bar interface 1 in this example or are there some other risks, I have not yet considered?
1 For example by disassembling the interop assembly.
You got the names wrong, that doesn't help understanding what's going on. The Bar coclass in the type library generates a Bar interface and a BarClass class, there is no "FooBar".
This is just extra glue that the type library auto-generates to make porting code easier. Particularly important for VB6 code, it took lots liberties with the COM object model. A VB6 program uses a coclass as though it is a real class with an implementation. No such thing exists in COM, the coclass is an opaque place-holder for the class, it is the interfaces that do all the work. VB6 never supported the notion of interfaces so directly modeling COM in the code wasn't possible.
The VB6 compiler itself generates a coclass from the Class keyword in the code and generates an interface that carries the actual methods and properties. That interface is hidden, it has the same name of the class but with a leading underscore. By convention, that causes object browsers to hide the interface. So your Bar coclass, when written in VB6, would generate a _Bar interface.
So a converted VB6 program would use Bar everywhere. This would not compile unless "Bar" was replaced by "IFoo". The synthesized Bar interface comes to the rescue, avoiding the need for that.
Still two problems left to solve, fixed by the synthetic BarClass type. New Bar() will not compile since it is not legal to create an instance of an interface. The compiler solves that problem, it automatically substitutes "Bar" with "BarClass". Which is the actual role of the [CoClass] attribute, it provides the name for the class associated with the interface. And events are a problem, they are implemented in COM by a dispinterface. Again a separate interface with a convoluted mechanism under the hood that subscribes events (IConnectionPoint et al). The synthetic BarClass makes them true-blooded .NET events.

Working with managed COM object from unmanaged code

Let's say I have a well-known interface IWellKnownInterface, which is known to be COM-visible and registered.
I also have a managed (C#, to be exact) implementation of this object:
public class MyWellKnownClass : IWellKnownInterface { ... }
And, finally, I have an extern method, which accepts the object of this interface:
[Whatever]
private static extern void ExternMethod(IWellKnownInterface veryWellKnown);
Question 1:
I would like to know what happens beneath the following code from the CLR point of view:
IWellKnownInterface a = new MyWellKnownClass();
ExternMethod(a);
I'm aware that if we're talking about calling unmanaged COM object from managed code, it's all about constructing an appropriate Runtime Callable Wrapper and delegating the calls via it with appropriate argument conversion. However, I could not find any information about the situation when we've got a managed COM object and it's being used in unmanaged code.
Question 2:
How does the dynamic type affect the behavior of the CLR in the same situation? Would it somehow change the internal managed-to-unmanaged interop logic? Maybe add some additional wrappers for the MyWellKnownClass instance?
dynamic a = new MyWellKnownClass();
ExternMethod(a);
Question 1:
The first line does nothing but create an object. There is nothing special or different that is happening from any other CLR object. This is because nothing has been actually marshaled to unmanaged code.
However, on the second line, a COM callable wrapper is created and marshaled across to unmanaged code. Think of this as the reverse of the runtime callable wrapper, handling the calls from unmanaged code back to your managed implementation of a COM interface.
Question 2:
The dynamic type doesn't impact the call at all. In this particular case, you're passing the managed reference to unmanaged code. The type of a is MyWellKnownClass, the only thing that dynamic does is change how calls to that are resolved in managed code. When the COM callable wrapper is created, it has a hard reference to the instance of MyWellKnownClass, not to the dynamic variable; the only thing that changes is that when ExternMethod is called, the resolution of the method that is called occurs at runtime and not at compile-time.

Categories

Resources