.NET Client supporting multiple versions of an unmanaged DLL - c#

I am developing a .NET 4.0 client that will utilize a C Library for data processing. The user will be able to specify the DLL file they wish to load for processing.
I am doing late binding / assembly loading as described here. http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_.aspx
For each DLL, the same method call sequences will be the same in my client, but the method signatures will change or the data structs passed in will change. The data populated with the structures will be different depending on the version of the DLL and other factors. Example, the definition of MyStruct will change depending on the version of the DLL.
public delegate int INTF_my_method(ref MyStruct pDataStruct);
What design patterns or design decision are recommended for this approach? I need to load the appropriate C method delegates and data definitions based on the version of the DLL that the user has specified, and populate the structures appropriately. Has anyone done something like this before?

There is no clean approach to this, neither in managed code nor native code. The best you could possibly do is to declare an interface type that tries to cover all possible versions and then write concrete wrapper classes for each individual version of the API. If there's at least some common functionality then you can shovel that in a base class.
Notable too is that you cannot just let the user pick a DLL, you have to pair the DLL with the concrete wrapper class instance.
Building this kind of flexibility in your program is obviously very expensive.

You can load different versions of your DLLs, but only from separate AppDomains. That is, for each DLL you want to load, you will have to create a new AppDomain.

Related

Why registering COM interfaces?

I've used COM for some years now but I keep learning new (and strange) things.
Recently I've realized that COM interfaces didn't had to be registered in the registry for components implementing them to work.
I've come to this conclusion after analysing the registry of a workstation where COM DLLs (implemented in .Net/C#) were registered with .reg files created by RegAsm because the user was not an administrator. And RegAsm only generates registry keys for COM classes and not interfaces.
If that's true my guess is that interfaces are important for early binding and have only to be present in TLB files. On the contrary registering implementations (classes) is essential because they are backed by physical code on the file-system that need to be referenced.
1) So am I crazy, missing something, or interfaces can be omitted?
2) If they can be omitted what are the consequences if any?
There are a lot things that you can't do without the interface being registered. Many of the features of COM -- marshaling, proxying, asynchronous calling -- have standard implementations that prevent you from having to roll this stuff yourself. For example, CoMarshalInterface is a standard way of taking any COM object interface and marshaling that interface into a stream so that it can be unmarshaled in another thread, process or machine. The interface information is critical in this -- without the interface metadata, the standard COM implementations of things like this won't work, as the infrastructure simply doesn't know enough about your interfaces to do what it needs to do in a generic way that works for all COM objects.
Additionally, while most automation clients (like VBA, C# and C++) can reference a type library file directly for purposes of early-binding, there are still limitations. For example, suppose you're working with a type library that contains some classes that implement interfaces from a different type library, or maybe the interfaces in the first type library accept parameters or return values that are defined by interfaces/enums/etc in another type library. In order for an automation client to work with these interfaces which contain cross-references, the cross-referenced type library must be discoverable somehow. Registration is the way this is accomplished.
Worth noting: In my experience, pretty much everything that works when a COM object is registered machine-wide (registered in HKLM) works exactly the same when registered per-user (in HKCU). This often makes COM registration more palatable in situations where machine-wide registration can't be performed (e.g. the user is not an admin). However, there are some significant gotchas, most notably https://techcommunity.microsoft.com/t5/Windows-Blog-Archive/Per-User-COM-Registrations-and-Elevated-Processes-with-UAC-on/ba-p/228531
Pretty vague, not sure I could read all the words between the bold ones. There is in general more than one way to skin this cat. COM requires using a class factory to get an object created, the generic work-horse one is CoCreateInstance(). CreateObject() is popular in scripting environments. You give it a number and it spits an interface pointer back. With the COM runtime taking care of the job to locate the executable file that contains the coclass, loading it and finding the proper class factory implementation.
Finding the executable is the tricky part, this is commonly done by info in the registry. Entered there when the component was registered. Not exclusively, a manifest can also be the source of this info. It needs to be embedded in the client app, one reason it is not a universal solution. More modern is the package manifest in a Windows Store/Phone/Universal application. Required, only very privileged components can still use the registry to let themselves be found. Microsoft components.
A completely different tack is having custom class factories. The way it is done in DirectX for example, it doesn't depend on the registry at all. You call CreateDevice() instead. Still calling this COM is a bit of a stretch, it is a more general technique called interface-based programming.
This all applies to objects, interfaces are different. You call IUnknown::QueryInterface() to obtain an interface pointer. No registration required, it is the coclass that handles it.
Nevertheless, you'll find lots and lots of registered interfaces with Regedit.exe in the HKLM\Software\Classes\Interface registry key. They take care of another COM detail, if the component does not live in the same machine or same process or the same thread as the client code then extra work must be done to get the call serialized across the machine/process/thread boundary. Same kind of thing that happens in .NET Remoting, it requires a proxy. An object that also implements the same interface but doesn't execute the method directly, passing the arguments to the stub instead so it can make the call.
Simple to do in .NET, Reflection makes it very easy. Not simple in COM, an extra component is required that knows how to serialize the arguments into an interop packet. And get the return value back the same way. Proxy/stubs are normally automatically built from the IDL. Or very common in .NET since it doesn't use IDL, you use the marshaller that digs out method details from the type library. A mechanism that's highly comparable to .NET Reflection, the type library plays the exact same role as .NET metadata does.
The ProxyStubClsId32 registry key inside the Interface key contains the CLSID of that component. You'll very commonly find {00000320-0000-0000-C000-000000000046} there, that's the system provided marshaller that uses the type library.
Regasm doesn't write the interface keys, it sets the ThreadingModel key for a .NET [ComVisible] class to "Both". So that the methods can be called both from an STA as well as an MTA thread without having to be marshaled. That's very optimistic and very rarely tested, writing thread-safe .NET code isn't that easy.
Regarding your first question, if the interface is not supposed to be used across COM contexts, or if the interface derives from IDispatch and you only use late-binding, you don't need to register it.
However, if you use early-binding, or if the interface is supposed to be used across COM contexts, you need to register it.
Just registering an interface doesn't enable marshaling, all argument types and return types must be marshalable too, i.e. not HANDLE or alike.
Regarding your second question, my hope is that you can answer yourself after reading the answer thus far. If not,
if you don't register an interface, you can't use it directly across COM contexts. If it derives from some registered interface, you can use that interface, such as the case of IDispatch-based interfaces.
However, very few interfaces are as general as IDispatch, so for any other base interface, you won't be able to use your derived interface's new methods.
In type libraries, if you don't register event dispinterfaces, then development tools (typically IDEs) won't be able to show you which events can be fired, or any event at all. The only other option is to implement the dispinterfaces by hand, if your programming language has that option, which requires documentation equivalent to the missing IDL in the first place.
One common extreme of this is to have all objects simply implement IDispatch and no other interface, but again this will hinder any effort a development tool might do towards method listing, code completion and/or argument choice (e.g. IntelliSense). Note that sometimes this is enough, such as when implementing a window.external object for IE's JScript, but it's a bit of lazyness when done in more general objects.
In general, if you're required very few extra effort to have interfaces registered, given you're already targeting COM, do so.

Reading MSDN pages [duplicate]

What is the necessity for the GUID attribute? why don't just let the compiler handle this automatically?!
If the compiler handled this automatically, you'd end up with one of two situations.
A new GUID every time you compiled - since GUIDs are supposed to be published, this would fail.
Collisions - if the GUID was the same every time, based on (say) a Hash of the name, multiple projects would end up using the same GUID for different purposes.
The existing approach - an explicit GUID gives developers the power to control these as required.
These are attributes that matter a great deal to COM. Which was the predecessor of .NET and had its heyday in the nineties, before Java stole the show. .NET needed to be compatible with COM to have a chance of succeeding. Or in other words, you needed to be able to write a COM server in a .NET language that a large legacy program could use.
The [ComVisible] attribute ensures that a COM client program can see and use the IEnumerable interface. Essential to allow the client program to enumerate .NET collections.
The [Guid] attribute is crucial in COM, it identifies an interface. Which is done by a guid, not a name, to ensure that it is unique across multiple applications written by different programmers. .NET has this too, but however uses a name to make it easier on humans. "System.Collections.IEnumerable, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".
IEnumerable<>, the generic version, doesn't have a [Guid]. Generics are not compatible with COM. It doesn't much matter these days, not much visible COM around anymore, most of it has been wrapped by friendly .NET classes. But still very core in Windows, notably in the brand-new WinRT (aka Metro, aka Modern UI, aka UWP). You don't use that directly either, making COM somewhat like the assembly language of Windows programming.
You can do it (just omit the attribute) but then the compiler will generate a new GUID on each recompile even if the interface has not changed. That's unfortunate because the users of that interface don't know about the change and will retrieve the interface by it's old GUID and will therefore fail to retrieve it.
Sometimes you want to give certain classes or modules a unique identifier that is constant and hard coded inside your source.
To read this definition you would need to look up the meaning of each of those attributes. The first, ComVisibleAttribute, is described as this:
Controls accessibility of an individual managed type or member, or of all types within an assembly, to COM.
That tells us that ComVisible is something to do with COM, and lets us specify whether a particular type is visible to COM programs. Further down on the page is a link to more details on what the attribute is for and how its used by the type library exporter.
The second, GuidAttribute, is a bit less helpful at first:
Supplies an explicit System.Guid when an automatic GUID is undesirable
but again, you have to read the rest of the way down, and you will see another mention of the type library exporter.
Putting these two together, it starts to become clear that these two attributes control how IEnumerator is processed when exported to a type library. If you don't know what a type library is, this will probably not mean much to you. If you are not using COM interop, then those attributes can safely be ignored. If you are using COM interop, you would need to know the Guid to properly access the interface from unmanaged COM code.
Microsoft puts these on every interface definition in case you need them; part of the skill in reading the MSDN pages is to recognize this type of information and know when it isn't any use to you. Now that you know what those two attributes are for, you should be able to figure out if they are relevant to you, and ignore them otherwise.

Interface for plugins to implement in .Net

I want to implement a plug-in system in my .net application, without the use of MEF.
My application loads and creates instances of types, that are contained in the DLLs.
There is an interface (IPluginContract) that the main application assembly uses to load dll types, and this very same interface is used by the dll projects (the plug-ins) to implement it.
So different projects need access to the same interface.
I can realize this requirement by pushing the interface class into a separate Class Library, that both main app and the plug-ins will reference.
Is it a correct way to work around the described problem?
Yes, pushing your interfaces out into a shared library is a preferred solution. You then only need to distribute this library to plugin developers, which could be considered as lightweight, but the plugin will be coupled to an exact version of the interface.
Another solution is a convention based solution, where plugin writers have types that "conform" to an interface e.g. have appropriate methods on a class which they can point to via a config file. You can then use reflection, IL generation, etc, to wire this up to a concrete internal interface\proxy. The benefit here is that plugins are then not hard-wired to a specific interface version, so there is more flexibility in versioning.
You could also consider versioning by maintaining all versions of your interface e.g. IPlugin_1, IPlugin_2, etc. It's then up to plugin writers to implement whichever version, and for you to be able to handle each version.
We have successfully taken two different approaches to this issue depending on the circumstances at the time (time to market, implementation difficulty, internals exposure concerns, etc):
1) Move the interface into its own DLL. This works well if the plugins don't need any other support objects/functions/data embedded in your main application DLL or if you don't want to expose public members in your main DLL to plugin writers.
2) Leave the interface in the main DLL. We have primarily used this when the refactoring cost to move the interface and associated classes was too high or when the plugins were completely self-contained (i.e. we author them for customers).

How to create a loosely coupled architecture with hot-swap capability?

I'm interested in creating a desktop application composed of modules such that the source code to those modules is embedded in the application itself, allowing the user to edit the application as they are running it and have the updated modules put into use without restarting the application. Can anyone suggest a good architecture for this?
I'm looking to use Microsoft.Net and C# for this. DLR is not an option.
Thanks!
It's not easy to suggest a good architecture for this in a short posting.
At first, i'd define a contract (an Interface) every module the user writes/modifies must implement. It should contain at least an Execute method.
Then I'd create a Wrapper-Class for these modules which:
loads the source code from a file
The wrapper compiles the file and also makes sure it implements the contract
Contains an indicator of whether the file could be compiled sucessfully
It should also implement the contract, for easy calling and handling
Then I'd have some kind of shell which contains a collection of all the module-wrappers. Any wrapper that sucessfully compiled would then let the Shell call the Execute method of the module interface.
When it comes to compiling and executing code on the fly, this link should provide all the information you need:
http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm
Well, a dynamic language certainly would have been the best fit...
You can use the types in the System.Reflection.Emit namespace to dynamically create assemblies.
However, it's going to be really painful because you'd need to load those dynamic assemblies into custom AppDomains because otherwise you'll not be able to unload them again.
This again means that you must address marshalling and assembly resolution issues related to cross-AppDomain communication.
What you are probably looking for is the concept of Dependency Injection.
Dependency Injection means that instead of having module X use module Y directly, module X only relies on an interface, and the application tells module X which implementation should use for it, e.g. using module Y.
There are several ways of implementing Dependency Injection. One is to have references to the interfaces in each of your modules, and explicitly let the application configure each of its modules with the right implementation of the interface.
The second wahy of implementing it (and probably the most useful in your case) is by using a central registry. Define all the interfaces that you want to have in your application. These are the interface for which you want to dynamically change the implementation. Then define identifications for these interfaces. These could be strings or integers or GUID's.
Then make a map in your application that maps the identifications to the interfaces, and fill the map with the correct implementations of the interfaces. In a C++ application (I'm not very skilled in C# yet) this could work like this:
std::map<std::string,IInterface> appInterfaces;
appInterfaces["database"] = new OracleDatabaseModule();
appInterfaces["userinterface"] = new VistaStyleUserInterface();
Make all modules go to this central registry whenever they want to use one of the modules. Make sure they don't access the modules directly, but they only pass via the registry. E.g.
MyModule::someMethod()
{
IDatabaseInterface *dbInterface = dynamic_cast<IDatabaseInterface *>(appInterfaces["database"]);
dbInterface->executeQuery(...);
}
If you now want to change the implementation for an interface in the application, you can simply change the entry in the registry, like this:
IInterface *iface = appInterfaces["database"];
if (iface) delete iface;
appInterface["database"] = new SqlServerDatabaseInterface();

How can I prevent the referencing of a certain assembly when running in Mono

I know how to branch the code based on Mono (Type.GetType("Mono.Runtime") != null) but even when the Mono code path is taken, Mono is attempting to load assemblies that would be required by the non-Mono code path. This is not all that surprising, but how do I get around the problem? I have tried putting the call to the non-Mono assembly in a different class, but that didn't help.
The only option to do it directly is Reflection all the way, so far as I can see.
I'd suggest a more roundabout approach: refactor all your code that is dependent on Mono or .NET into separate assemblies, one for each platform - let's call them MA and NA. Make sure that the entire API surface of your classes there is covered by common interfaces, which should be in the 3rd assembly, IA. After that, your main application references IA for interfaces, and uses Reflection just once to load either MA or NA depending on whether it's running on Mono or .NET, and obtain the instance of "top-level factory class". Once there, it just uses normal calls via IA interfaces to instantiate all other objects via that factory and work with them.
Expanding on Pavel's answer you can use a plugin framework to help with the conditionality of loading bits of code that are specific to a platform. You can use Mono.Addins or MS' own open sourced Managed Extensibility Framework known as MEF (http://www.codeplex.com/MEF)
Don't add the reference in the command-line compiler options. If you are using a high level IDE tool then you might have to play with its project settings to effect the same thing.
There are other files that come into play too like AssemblyInfo.cs and might contain instructions about assemblies that you are considering. Also the program might be using types from App.Config (Configuration file) or Web.Config (ASP.NET) / dynamic type loading.
Don't rely for your dependencies on the fact that your code is JITted and that only called code is JITted.
Best is always to assume, that whatever is referenced will be loaded and has to be available.
You user might choose to use AOT, which is Mono's counterpart of NGEN.
Or subtle differences in how newer runtime versions handle things like serialization, remoting, security, reflection, etc. can lead to your references being loaded even your code does not use anything directly. (But the serializer might have pulled all types, which then loaded other assemblies)
Use interfaces or classic inheritance, or maybe events or other means of indirection to load the .Net parts only when they are appropriate. And by hat I mean an assembly that you don't reference but load dynamically.

Categories

Resources