The idea is that there is a primary implementation of COM interface, which needs to handle different MIME types (MIME is just an example). Primary implementation handles several common MIME types that are expected to be on the customer site.
To handle new MIME type one has to implement the same COM interface, but only for that new MIME type (let's call it enhanced COM object). Client calls enhanced COM object first, which handles its MIME type or calls primary COM object if MIME type is not recognized. We can assume that the might be more than one enhanced COM implementation. Hence, there is a chain of responsibility.
Is COM chain-of-responsibility possible? Is it practical?
Thanks
In theory it could, but I think you might be better off with a Factory pattern here, which in COM can be implemented using Categories.
Related
I feel like I would benefit greatly from understanding the differences in how these functions work so that I could better understand when to use each one.
I'm having a very difficult time working with two different interops (Excel, and EPDM) which have both made extensive use of weak typed parameters. I keep running into problems using returned objects and casting them to the proper type (per the documentation). After wasting a ton of time, I've found that using TypeName, GetType, and a TypeOf operator with COM objects can yield different results, and in different circumstances each one can be more or less reliable than the next.
Now, in most cases TypeName() seems to be the most reliable for determining type with COM objects. However, avoiding the other two functions entirely seems quite cargo cultish to me, and besides that today I ran into an interesting problem where I can't seem to cast an object to the type reported by TypeName(). An interesting notion was brought up in the comments on that problem that objects which implement IDispatch may actually return the dispatched interface typename, which could partially explain the differences.
I'd really like to better understand how these functions actually work, but I get kind of lost running through the .NET ReferenceSource, so I'm offering a bounty on this question in hopes someone can explain how these different functions work and in what context each should be used.
Here is a code excerpt from working with the Excel interop.
Dim DocProps As Object
DocProps = WeeklyReports.CustomDocumentProperties 'WeeklyReports is a Workbook object
Debug.Print(DocProps Is Nothing)
Debug.Print(TypeName(DocProps))
Debug.Print(TypeOf (DocProps) Is DocumentProperties)
Debug.Print(DocProps.GetType.ToString)
The output is:
False
DocumentProperties
False
System.__ComObject
It is a long story and a bit doubtful that English is going to cut it. It does require understanding how COM works and how it was integrated into the Office products.
At breakneck speed, COM is very heavily an interface-based programming paradigm at its core. Interfaces are easy, classes are hard. Something you see back in the .NET design as well, a class can derive from only one single base class but can implement any number of interfaces. To make language interop work smoothly, it is important to take as few dependencies on language implementation details as possible.
There is a lot that COM does not do that you'd be used to in any modern language. It does not support exceptions, only error codes. No notion of generics at all. No Reflection. No support for method overloads. No support for implementation inheritance whatsoever, the notion of a class is completely hidden. It only appears as a number, the CLSID, a guid that identifies a class type. With a factory function implemented in the COM component that creates an object of the class. The COM component retains ownership of that object. The client code then only ever uses interfaces to make calls to use methods and get or set properties. CoCreateInstance() is the primary runtime support function that does this.
This was further whittled down to a subset called OLE Automation, the flavor that you use when you interop with Office. It strictly limits the kind of types you can use for properties and method arguments with prescribed ways to deal with the difficult ones like strings and arrays. It does add some capabilities, it supports late binding through the IDispatch interface, important to scripting languages. And VARIANTs, a data type that can store a value or object reference of an arbitrary type. And supports type libraries, a machine-readable description of the interfaces implemented by the COM server. .NET metadata is the exact analogue.
And important to this question, it limit the number of interfaces that a class can implement to just one. Important to languages that don't support the notion of interfaces at all, like VBA, scripting languages like Javascript and VBScript and early Visual Basic versions. The Office interop object model was very much designed with these limitations in mind.
So from the point of view from a programmer that uses such a language to automate an Office program, it is completely invisible that his language runtime is actually using interfaces. All he ever sees and uses in his program are identifiers that look like class names, not interface names. That DocumentProperties is actually an interface name is something you can see in Object Browser. Just type the name in the search box, it properly annotates "public interface DocumentProperties / Member of Microsoft.Office.Core" in the lower-right panel.
One specific detail of the Office object model matters a great deal here, many properties and method return types are VARIANTs. A OLE Automation type that can store an arbitrary value or object reference, it is mapped to System.Object when you use .NET. The Workbook.CustomDocumentProperties property is like that. Even though the property is documented to actually return a DocumentProperties interface reference. They probably did this to leave elbow room to some day return another kind of interface. Fairly necessary for "custom document properties".
That the property is a VARIANT doesn't matter that much in languages that support dynamic typing, they take them with stride. It is however pretty painful in a strongly typed language. And pretty unfriendly to programming editors that support auto-completion, like VS's IntelliSense. What you normally do is declare your variable to the expected interface type:
Dim DocProps As DocumentProperties
DocProps = CType(WeeklyReports.CustomDocumentProperties, Microsoft.Office.Core.DocumentProperties)
And now everything lights up. You don't need the CType() cast either if you favor programming VB.NET with Option Strict Off in effect. Which turns it into a programming language that supports dynamic typing well.
We're getting there. As long as you declare DocProps as Object then the compiler knows beans about the interface. Nor does the debugger, it isn't helped by the variable declaration and can only see that it is a __System.ComObject from the runtime type. So it isn't Nothing, that's easy enough to understand, the property getter did not fail and the document has properties.
The TypeName() function uses a feature of the IDispatch interface, it exposes type information at runtime. That happens to work in your case, it usually doesn't, the function first calls IDispatch::GetTypeInfo() to get an ITypeInfo interface reference, then calls ITypeLib::GetDocumentation(). That works, you get the interface name back. Otherwise pretty comparable to Reflection in .NET, just not nearly as powerful. Do not rely on it heavily, there are lots of COM components that don't implement this.
And crucial to your question, TypeOf (DocProps) Is DocumentProperties is a fail whale. Something you'll discover when you try to write the code I proposed earlier. You'll get a nasty runtime exception, System.InvalidCastException:
{"Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Core.DocumentProperties'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{2DF8D04D-5BFA-101B-BDE5-00AA0044DE52}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))."}
In other words, the Excel documentation is lying to you. You get an interface back that resembles DocumentProperties, it still has the members that this interface documents, but is no longer identical to the Microsoft.Office.Core.DocumentProperties. It probably once was, many moons ago. A nasty little detail that's buried inside this KB article:
Note The DocumentProperties and the DocumentProperty interfaces are late bound interfaces. To use these interfaces, you must treat them like you would an IDispatch interface.
I have a WCF service method that expects an object and then retrieves its properties using reflection.
On the client side I create an anonymous type object
var obj = new {FirstName="John", LastName="Doe"}
and pass it to the method. I'm getting an exception:
Type '<>f__AnonymousType0`2[System.String,System.String]' cannot be serialized.
Consider marking it with the DataContractAttribute attribute, and marking all
of its members you want serialized with the DataMemberAttribute attribute.
See the Microsoft .NET Framework documentation for other supported types.
I can't mark the type or its members with serialization attributes because there is really no type nor properties declared explicitly. Is there a way to overcome that problem?
The answers suggesting that you can't use an anonymous type over WCF are wrong.
If you are using the default DataContractSerializer to serialize your types on the channel, then yes, the answers are correct. This is because the DataContractSerializer supports the following scenarios:
Types serialized using the Serializable attribute
Types serialized using XML Serialization
Types serialized using the DataContract attribute
Plain-Old-C#-Object (POCO) Serialization
Respectively, they fail with anonymous types because of the following:
You can't apply attributes to anonymous types.
XML Serialization requires a default parameterless constructor, which anonymous types do not have.
Same as 1.
Same as 2.
However, you are not forced to use the DataContractSerializer to serialize your messages in WCF. You can create a custom message formatter which you can use to perform the serialization yourself.
You have a problem if the types you are sending out as the results of requests are anonymous types. When you get the results back, it's going to have a definite name within a namespace (not in a .NET sense, but in a SOA sense) and you are going to have to handle the mapping of that concrete type back to the anonymous type. However, because you don't have access to the actual anonymous type or ways of constructing it in code (at least in a dynamic way), you have no choice but to pass it along as an object if it's passed back to you, which makes it kind of worthless, since everyone will have to use bad practices such as dynamic (not a bad practice in itself, but to get around these limitations in this case, yes), or cast-by-example.
So in the end I will say that while it certainly is possible to serialize anonymous types and send them over the wire, the work invovled is usually not worth it.
Don't do this.
It's an attempt to be clever. Don't. Just declare the datatype you need, and use it. If you need a more loosely-defined datatype, just use a key-value mapping of some sort.
It will take you 5 minutes to write something that can handle this for good. Using any technique like this will cost you hours of debugging at some future point down the road.
You could serialize the object into a JSON string and send it through WCF, like so:
//in WCF Server
dynamic mysentclass = new { FirstName = "John", LastName = "Doe" };
string jsonstring = JsonConvert.SerializeObject(mysentclass, Newtonsoft.Json.Formatting.Indented);
//send the string through WCF
//in WCF client
dynamic myreceivedclass = JsonConvert.DeserializeObject<dynamic>(jsonstring);
MessageBox.Show(myreceivedclass.FirstName.ToString() + " " + myreceivedclass.LastName.ToString());
The example uses Json.Net, which can be obtained here:
http://www.nuget.org/packages/Newtonsoft.Json/
You could also use System.Web.Script.Serialization.JavaScriptSerializer (in System.Web.Extensions.dll), which is not as powerful as Json.Net, but would suffice for simple objects.
No, there is not. While there are tricks and techniques to return objects of an anonymous type from a method, you cannot send them over WCF.
WCF needs to know all of its concrete types that will be sent across, since you're not really just calling a .NET method. Instead, the message call gets converted into a serialized message, and therefore, any "thing" being passed over a WCF call must be serializable - no exceptions.
You've already got the answer. It can't be done.
In fact, you can't pass an instance of an anonymous type from one method to another within your program. You certainly can't pass them between programs.
As said before, the objects must be deserializable and so you will have to define the structure beforehand. However, you can use inheritance to defining them, and hence lower the pain. WCF provides the KnownType attribute to allow a Service Operation to receive an object of the base class and deserialize it into an object of a derived class. So you will still only have one (or a few) Service Operations that can handle all your scenarios.
I want to find a tool that can see all the interface, including the methods, properties, events, exposed by a COM(or ActiveX) component. Is such tool available?
It's not actually possible to build such a tool for ANY COM object, you might have some luck with specific objects. If a type library is available then you could use OLEView or you can programatically open and traverse the type library itself. Bear in mind that the contents of the type library is just what the developer wanted to include in it; there's nothing to stop objects implementing more interfaces than their type libraries say they do.
For objects without type libraries it's impossible to produce a general purpose tool:
Given the way that QueryInterface works you would have to ask the object under investigation if it supports every interface possible. Where would such a tool obtain a list of all possible interfaces that the object in question could support? Whilst it's true that some interfaces are registered in the registry due to proxy requirements not all interfaces are and it's by no means a requirement that they should be.
Once you know that an object supports a given interface how do you work out what methods that interface supports? If the interface derives from IDispatch then this is possible as that's the purpose of IDispatch, but for interfaces derived from IUnknown there is no way to programatically discover things about the interface.
You also have the added problem that some objects may have additional interfaces implemented for them by the proxy layer, for example, if an interface has been proxied then you will also be able to QueryInterface from it to IProxyManager though the object itself does not implement this interface (it's part of the proxy).
If the component has a typelib (in resources or shipped separately) you can use OLE View that comes with Visual Studio. You should use "View Typelib", not "Bind to File" there.
Problem:
WCF contract objects cannot implement 2 types of lists (ie: List and List).
Long-winded explanation:
I'm building a WCF service on top of an existing core system, and I'm trying to work out the best way to implement some of my business objects.
The core system utilizes interfaces for all business objects - Person management functionality, for instance, requires that I pass in an object which implements IPerson. Nothing out of the ordinary here.
The goal is to have a contact object (Person) which can be used on the service side of things, and also implements IPerson so that it can be passed into the core without requiring a conversion layer. This all works just fine for items like Person.
The issue comes in for lists: a method in the core, for instance, might require a IPersonList to be passed in, and as anyone who's dealt with inherited generics will know, List does not inherit from IList.
In our currently running ASMX service, we implement this with some up/down casting in the web objects. "WebPerson" will inherit from List, and implement IList explicitly so that the IList properties do not show up on the WSDL.
In WCF, however, if you try to use this same object, you will get the following error:
Type 'Cssi.IBroker.Service.Cssi.Contracts.PersonList' with CollectionDataContractAttribute attribute is an invalid collection type since it has multiple definitions of interface 'IList`1'.
Apparently, now that the new WCF serializer knows how to serialize IList, it's no longer able to ignore the second explicit implementation.
If possible, I'd like to avoid creating a PersonList object just for the contracts and then converting to and from an IPersonList object for each call. Changing the core business logic to use concrete objects designed just for the WCF services isn't an option.
Help!
I ended up deciding the best route was a set of dedicated objects used only for the contracts. With them being dedicated to one task, I was able to keep them cleaner without having to compromise my internal design for the sake of the WSDL. For the WSDL objects themselves, I ended up using arrays instead of IList.
The extra step of conversion is a bit cumbersome, but less than trying to keep my core objects WCF friendly would be.
I have a COM inproc DLL that we are using in our product.
Now if someone finds out which interface and APIs we have exposed from the DLL then those APIs can be called easily.
Is there a way to stop unknown applications from calling my APIs?
Can we add some signature in COM?
The formal way of controlling use of your object is by implementing IClassFactory2 on the class factory that creates your COM objects.
Here's a link at MSDN explaining the interface.
IClassFactory2 at MSDN
The benefit of creating an implementation is that nobody can fetch an instance without clearing the hurdles of registration through IClassFactory2.
The downside is that you'll have to inspect all the locations where you are creating an object, to make sure that they haven't broken. Creating instances becomes more burdensome, although some languages already have facilities to make the process less painful (ex. VB6).
If you are trying to protect an object that has a lot of instantiation activity, you might want to go with Mastermind's method of adding a key parameter, or add an unlock method of some sort to your interfaces that must be called correctly before the component behind it can be used.
You could make your interfaces inheriting directly from IUnknown (without IDispatch) and not include the type library into the DLL. This way only those who have access to the type library will be able to find what interfaces are supported and the only other way to discover the interfaces will be to just guess. If you go this way you might also wish to minimize the number of classes exposed to registry (those that can be created with CoCreateInstance()) and use a set of factory methods of some dedicated registry-exposed class instead.
This implies that only vtable early-binding will work with your component. You will also be unable to use default call marshaling with this component (since no type library is included). And this is not real protection, just a way to hide things.
Nothing prevents you from adding a "key" parameter to the methods which will just return if the key is wrong.
Very simple but will do for starters.
Other than some sort of 'key' param, you can't prevent the curious from discovering your function and then calling it. All it takes is a debugger and some patience. To be totally secure you'd have to require some sort of certificate that authorized code could obtain but all others couldn't but that would mean you're code would have to be able to verify the certificate.