Interface change between versions - how to manage? - c#

Here's a rather unpleasant pickle that we got into on a client site. The client has about 100 workstations, on which we deployed version 1.0.0 of our product "MyApp".
Now, one of the things the product does is it loads up an add-in (call it "MyPlugIn", which it first looks for on a central server to see if there's a newer version, and if it is then it copies that file locally, then it loads up the add-in using Assembly.Load and invokes a certain known interface. This has been working well for several months.
Then the client wanted to install v1.0.1 of our product on some machines (but not all). That came with a new and updated version of MyPlugIn.
But then came the problem. There's a shared DLL, which is referenced by both MyApp and MyPlugIn, called MyDLL, which has a method MyClass.MyMethod. Between v1.0.0 and v1.0.1, the signature of MyClass.MyMethod changed (a parameter was added). And now the new version of MyPlugIn causes the v1.0.0 client apps to crash:
Method not found: MyClass.MyMethod(System.String)
The client pointedly does not want to deploy v1.0.1 on all client stations, being that the fix that was included in v1.0.1 was necessary only for a few workstations, and there is no need to roll it out to all clients. Sadly, we are not (yet) using ClickOnce or other mass-deployment utilities, so rolling out v1.0.1 will be a painful and otherwise unnecessary exercise.
Is there some way of writing the code in MyPlugin so that it will work equally well, irrespective of whether it's dealing with MyDLL v1.0.0 or v1.0.1? Perhaps there's some way of probing for an expected interface using reflection to see if it exists, before actually calling it?
EDIT: I should also mention - we have some pretty tight QA procedures. Since v1.0.1 has been officially released by QA, we are not allowed to make any changes to MyApp or MyDLL. The only freedom of movement we have is to change MyPlugin, which is custom code written specifically for this customer.

The thing is that the changes you made have to be basically in addition and not the change. So if you want to be back compatible in your deployment (as much as I understood in current deployment strategy you have this is an only option) you should never change the interface but add a new methods to it and avoid tight linking of your plugin with shared DLL, but load it dynamically. In this case
you will add a new funcionality without disturbing a old one
you will be able to choose which version of dll to load at runtime.

I have extracted this code from an application I wrote some time ago and removed some parts.
Many things are assumed here:
Location of MyDll.dll is the current directory
The Namespace to get reflection info is "MyDll.MyClass"
The class has a constructor without parameters.
You don't expect a return value
using System.Reflection;
private void CallPluginMethod(string param)
{
// Is MyDLL.Dll in current directory ???
// Probably it's better to call Assembly.GetExecutingAssembly().Location but....
string libToCheck = Path.Combine(Environment.CurrentDirectory, "MyDLL.dll");
Assembly a = Assembly.LoadFile(libToCheck);
string typeAssembly = "MyDll.MyClass"; // Is this namespace correct ???
Type c = a.GetType(typeAssembly);
// Get all method infos for public non static methods
MethodInfo[] miList = c.GetMethods(BindingFlags.Public|BindingFlags.Instance|BindingFlags.DeclaredOnly);
// Search the one required (could be optimized with Linq?)
foreach(MethodInfo mi in miList)
{
if(mi.Name == "MyMethod")
{
// Create a MyClass object supposing it has an empty constructor
ConstructorInfo clsConstructor = c.GetConstructor(Type.EmptyTypes);
object myClass = clsConstructor.Invoke(new object[]{});
// check how many parameters are required
if(mi.GetParameters().Length == 1)
// call the new interface
mi.Invoke(myClass, new object[]{param});
else
// call the old interface or give out an exception
mi.Invoke(myClass, null);
break;
}
}
}
What we do here:
Load dynamically the library and extract the type of MyClass.
Using the type, ask to the reflection subsystem the list of MethodInfo present in that type.
Check every method name to find the required one.
When the method is found build an instance of the type.
Get the number of parameters expected by the method.
Depending on the number of parameters call the right version using Invoke.

My team has made the same mistake you have more than once. We have a similar plugin architecture and the best advice I can give you in the long run is to change this architecture as soon as possible. This is a maintainability nightmare. The backwards compatibility matrix grows non-linearly with each release. Strict code reviews can provide some relief, but the problem is you always need to know when methods were added or changed to call them in the appropriate way. Unless both the developer and reviewer know exactly when a method was last changed you run the risk of there being a runtime exception when the method is not found. You can NEVER call a new method in MyDLL in the plugin safely, because you may run on a older client that does not have the newest MyDLL version with the methods.
For the time being, you can do something like this in MyPlugin:
static class MyClassWrapper
{
internal static void MyMethodWrapper(string name)
{
try
{
MyMethodWrapperImpl(name);
}
catch (MissingMethodException)
{
// do whatever you need to to make it work without the method.
// this may go as far as re-implementing my method.
}
}
private static void MyMethodWrapperImpl(string name)
{
MyClass.MyMethod(name);
}
}
If MyMethod is not static you can make a similar non-static wrapper.
As for long term changes, one thing you can do on your end is to give your plugins interfaces to communicate through. You cannot change the interfaces after release, but you can define new interfaces that the later versions of the plugin will use. Also, you cannot call static methods in MyDLL from MyPlugIn. If you can change things at the server level (I realize this may be outside your control), another option is to provide some sort of versioning support so that a new plugin can declare it doesn't work with an old client. Then the old client will only download the old version from the server, while newer clients download the new version.

Actually, it sounds like a bad idea to change the contract between releases. Being in an object-oriented environment, you should rather create a new contract, possibly inheriting from the old one.
public interface MyServiceV1 { }
public interface MyServiceV2 { }
Internally you make your engine to use the new interface and you provide an adapter to translate old objects to the new interface.
public class V1ToV2Adapter : MyServiceV2 {
public V1ToV2Adapter( MyServiceV1 ) { ... }
}
Upon loading an assembly, you scan it and:
when you find a class implementing the new interface, you use it directly
when you find a class implementing the old interface, you use the adapter over it
Using hacks (like testing the interface) will sooner or later bite you or anyone else using the contract - details of the hack have to be known to anyone relying on the interface which sounds terrible from the object-oriented perspective.

In MyDLL 1.0.1, deprecate the old MyClass.MyMethod(System.String)and overload it with the new version.

Could you overload MyMethod to accept MyMethod(string) ( version 1.0.0 compatible) and MyMethod(string, string) (v1.0.1 version)?

Given the circumstances, I think the only thing you can do really is have two versions of MyDLL running 'side by side',
and that means something like what Tigran suggested, loading the MyDLL dynamically - e.g. as an a side example not related but might help you, take a look at the the RedemptionLoader http://www.dimastr.com/redemption/security.htm#redemptionloader (that's for an Outlook plugins which often have problems crashing to each other referencing different versions of a helper dll, just as a background story - that's a bit more complex cause of the COM involved but doesn't change much here) -
it's what you can do, something similar. Load dynamically the dll by it's location, name - you can specify that location internally, hard-code, or even set it up from config or something (or check and do that if you see that MyDll is not of the right version),
and then 'wrap' the objects, calls form the dynamically loaded dll to match what you normally have - or do some trick like that (you'd have to wrap something or 'fork' on the implementation) to make everything work in both cases.
Also to add on the 'no-nos' and your QA sorrows :),
they should not break the backward compatibility from 1.0.0 to 1.0.1 - those are (usually) the minor changes, fixes - not breaking changes, major version # is needed for that.

Related

Classes declared dynamically with GuidAttribute

I have a t4 template that creates many classes based on a database table. These classes need to be exposed to COM, so they are declared with the GuidAttribute attribute.
Whenever I compile the project, say to test something and register it in the test environment, new GUIDs are created for each class definition, and I'm starting to worry that I may be doing bad things to the Windows Registry...
If I compile the project and I have the definition of Class1 like
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[GuidAttribute("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
public class Class1
{
...
}
And tomorrow I want to test something else and Class1 now looks like
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[GuidAttribute("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB")]
public class Class1
{
...
}
Will the previous GUID remain in the registry, or is the registration process smart enough to remove everything from the previous registration?
This whole question may come from my ignorance of what are these GUIDs used for and how they relate to CLSIDs, but the fact that they are meant to be declared statically with the class definition, and I'm doing it dynamically makes me somewhat uneasy.
Will the previous GUID remain in the registry
If you don't explicitly unregister the component, yes. Easy to forget of course. You have to run Regasm.exe /uninstall from an elevated command prompt.
is the registration process smart enough to remove everything
Depends how you register. If you let MSBuild do it (Project + Properties, Build tab, Register for COM interop option) then it will automatically unregister the server before rebuilding the DLL. But since you use [Guid], it immediately writes it back of course :) Net effect is zero. If you do it by hand by running Regasm.exe then no unregistration takes place.
Do keep in mind that [Guid] is sacred in COM. Explicitly specifying like you do is quite risky, there is a rock-hard rule in COM that you must change the guid when you change the declaration. Not doing so causes very nasty DLL Hell problems. Using the [Guid] attribute is only reasonable when you have to write a replacement for an existing COM server. Or to avoid registry pollution when you don't let MSBuild clean up or want to avoid a client programming tool hassling you with constantly having to re-select the type library. But then it is very important that you remove the attribute again when you are done testing. Easy to forget of course :)

Basic implementation of AOP like attribute using standard .NET Framework [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# wrap method via attributes
I'd like to achieve such functionality:
[Atomic]
public void Foo()
{
/* foo logic */
}
Where [Atomic] attribute is an attribute, which wraps function logic within a transaction scope:
using(var scope = new TransactionScope())
{
/* foo logic */
scope.Complete();
}
How to write such an attribute?
I've asked before basically the same question, I know this can be done using AOP, but I didn't mention I'm searching for some simplest proof of concept implementation or helpful articles which can help me to write this using pure .NET Framework (I suppose using RealProxy and MarshalByRefObject types, about which I've read browsing related questions).
I need to solve exactly this shown example. It seems like a basic thing so I want to learn how to do it starting from scratch. It doesn't need to be safe and flexible for now.
It seems like a basic thing...
It's one of the (many) things which are simple to understand the concept, but not at all simple to implement.
As per Oded's answer, Attributes in .NET don't do anything. They only exist so that other code (or developers) can look at them later on. Think of it as a fancy comment.
With that in mind, you can write your attribute like this
public class AtomicAttribute : Attribute { }
Now the hard part, you have to write some code to scan for that attribute, and change the behaviour of the code.
Given that C# is a compiled language, and given the rules of the .NET CLR there are theoretically 3 ways to do this
Hook into the C# compiler, and make it output different code when it sees that attribute.
This seems like it would be nice, but it is simply not possible
right now. Perhaps the
Roslyn
project might allow this in future, but for now, you can't do it.
Write something which will scan the .NET assembly after the C# compiler has converted it to MSIL, and change the MSIL.
This is basically what PostSharp does. Scanning and rewriting MSIL is hard. There are libraries such as Mono.Cecil which can help, but it's still a hugely difficult problem. It may also interfere with the debugger, etc.
Use the .NET Profiling API's to monitor the program while it is running, and every time you see a function call with that attribute, redirect it to some other wrapper function.
This is perhaps the simplest option (although it's still very difficult), but the drawback is that your program now must be run under the profiler. This may be fine on your development PC, but it will cause a huge problem if you try deploy it. Also, there is likely to be a large performance hit using this approach.
In my opinion, your best bet is to create a wrapper function which sets up the transaction, and then pass it a lambda which does the actual work. Like this:
public static class Ext
{
public static void Atomic(Action action)
{
using(var scope = new TransactionScope())
{
action();
scope.Commit();
}
}
}
.....
using static Ext; // as of VS2015
public void Foo()
{
Atomic(() => {
// foo logic
}
}
The fancy computer science term for this is Higher order programming
Attributes are meta data - that's all they are.
There are many tools that can take advantage of such metadata, but such tooling needs to be aware of the attribute.
AOP tools like PostSharp read such metadata in order to know what and where to weave aspects into code.
In short - just writing an AtomicAttribute will give you nothing - you will need to pass the compiled assembly through a tool that knows about this attribute and do "something" to it in order to achieve AOP.
It is not a basic thing at all. No extra code is run just because a method has an attribute, so there is nowhere to put your TransactionScope code.
What you would need to do is at application start-up use reflection to iterate over every method on every class in your assembly and find the methods that are marked with AtomicAttribute, then write a custom proxy around that object. Then somehow get everything else to call your proxy instead of the real implementation, perhaps using a dependency injection framework.
Most AOP frameworks do this at build time. PostSharp for example runs after VisualStudio builds your assembly. It scans your assembly and rewrites the IL code to include the proxies and AOP interceptors. This way the assembly is all set to go when it is run, but the IL has changed from what you originally wrote.
Maybe resolve all objects using IoC container?
You could configure interceptors for your types and in them check if called method is decorated with that attribute. You could cache that information so that you don't have to use reflection on every method call.
So when you do this:
var something = IoC.Resolve<ISomething>();
something is not object you have implemented but proxy. In that proxy you can do whatever you want before and after the method call.

Referencing a class that may exist in one of two assemblies

I am currently working on a data harvester for a project. The way it works is it basically calls another program which collects the data, and that program returns a data structure containing a collection of queue information. The harvester then serializes out the data. The program that actually collects the data is maintained by another team, and recently they did an upgrade and decided to restructure their code. The method I am calling is still in the same location, however, the data structure I get back got moved to a different assembly (it's code remained the same). The fun part of this is that we have both versions of this product in the field right now, so depending on which version a client has, the data structure I need may be in one of two different assemblies. My boss wants to try to only have one version of the harvester program if possible.
So, my question is this: using C# and .NET 3.5, is there a way to pick which assembly to use at runtime? I think I could use reflections, but I'd like to know if there's any way I could write the code normally for compile time and then resolve the dependency at run time depending on the other program's version.
You could try using the Adapter (wrapper) design pattern.
interface IQueueInfoProvider
{
DataStructure FetchData();
}
class Version1QueueInfoProvider : IQueInfoProvider
{
DataStructure FetchData()
{
//Fetch using Version1 Assemblies.
}
}
class Version2QueueInfoProvider : IQueInfoProvider
{
DataStructure FetchData()
{
//Fetch using Version2 Assemblies.
}
}
I believe .NET won't attempt to load referenced assemblies if they aren't needed, but if i'm wrong, you can always use reflections.
You may want to investigate the assemblybinding tags.
http://msdn.microsoft.com/en-us/library/twy1dw1e.aspx
you should go for AppDomain
http://www.codeproject.com/KB/cs/Assemblies___Appdomains.aspx
And another one is most popular
http://www.west-wind.com/Weblog/posts/601200.aspx

How to organize code using an optional assembly reference?

I am working on a project and want to optionally use an assembly if available. This assembly is only available on WS 2008 R2, and my ideal product whould be a common binary for both computers with and without the assembly. However, I'm primarily developing on a Windows 7 machine, where I cannot install the assembly.
How can I organize my code so that I can (with minimum changes) build my code on a machine without the assembly and secondly, how do I ensure that I call the assembly functions only when it is present.
(NOTE : The only use of the optional assembly is to instantiate a class in the library and repeatedly call a (single) function of the class, which returns a boolean. The assembly is fsrmlib, which exposes advanced file system management operations on WS08R2.)
I'm currently thinking of writing a wrapper class, which will always return true if the assembly is not present. Is this the right way to go about doing this?
My approach would be to dynamically load the assembly, instead of hard-coding a reference. Your code could then decide whether to use the assembly (if it loaded) or return some other value. If you use the assembly, you'll need to use reflection to instantiate the class and use the method. That way your code will build and run on any platform, but it's behavior will change if it detects the presence of fsrmlib.
The System.Reflection.Assembly documentation has example code for doing this.
Hide the functionality behind an interface, say:
public interface IFileSystemManager
{
void Manage(IFoo foo);
}
Create two implementations:
An implementation that wraps the desired functionality from fsrmlib
A Null Object implementation that does nothing
Inject the IFileSystemManager into your consumers using Constructor Injection:
public class Consumer
{
private readonly IFileSystemManager fileSystemManager;
public Consumer(IFileSystemManager fileSystemManager)
{
if (fileSystemManager == null)
{
throw new ArgumentNullException("fileSystemManager");
}
this.fileSystemManager = fileSystemManager;
}
// Use the file system manager...
public void Bar()
{
this.fileSystemManager.Manage(someFoo);
}
}
Make the selection of IFileSystemManager a configuration option by delegating the mapping from IFileSystemManager to concrete class to the config file so that you can change the implementation without recompiling the application.
Configure applications running on WS 2008 R2 to use the implementation that wraps fsrmlib, and configure all other applications to use the Null Object implementation.
I would recommend that you use a DI Container for the configuration part instead of rolling this functionality yourself.
Alternatively you could also consider treating the IFileSystemManager as an add-in and use MEF to wire it up for you.

Plugin based application in C#

I have to make a graphical user interface application using the language of my choice. The application will run on Windows XP. It will be some sort of a complex windows form application.
I think and as per most suggestions, C# will be the best to use.
The tree structure on the left of the GUI will populate after reading from a configuration file which will be a binary file . (but initially I can work with a simple ASCII file to test my code.). The application will accept some inputs from the user through this GUI and will write the back to the same config file and will reflect the changes in the tree structure or the labels or any other pertaining field on the form.
There will be 3 tabs and 3 corresponding config files for each of the tabs.
I need some help designing the application for now. I am planning to make a host application (main application) and use the 3 tab controls as plugins. Is this workable ? If so can you please guide me on this. I mean how do I make 3 plugins in C# and how do I write the interfaces so that the main application knows which plugin to load and when to load it ? Will there be a separate “Plugin” folder under my project folder ? I hope you got my point though this is too little of an information for you to begin with.
Also there are some .cpp files already existing in the project. These files along with some .h files contain some important definitions and constants in them. These need to be integrated with my C# application. I have no clue how to do that but I am sure that it is possible by compiling the .cpp code in a .dll and then exposing the compiled .dll to my C# application. Please let me know if you need some more information for the top level design.
Thanks,
Viren
To implement a plugin interface manually, you will need a method something like this. I've left some TODOs in, where you would want to enhance the error handling and/or make the implementation a little more case specific.
public List<T> LoadPlugin<T>(string directory)
{
Type interfaceType = typeof(T);
List<T> implementations = new List<T>();
//TODO: perform checks to ensure type is valid
foreach (var file in System.IO.Directory.GetFiles(directory))
{
//TODO: add proper file handling here and limit files to check
//try/catch added in place of ensure files are not .dll
try
{
foreach (var type in System.Reflection.Assembly.LoadFile(file).GetTypes())
{
if (interfaceType.IsAssignableFrom(type) && interfaceType != type)
{
//found class that implements interface
//TODO: perform additional checks to ensure any
//requirements not specified in interface
//ex: ensure type is a class, check for default constructor, etc
T instance = (T)Activator.CreateInstance(type);
implementations.Add(instance);
}
}
}
catch { }
}
return implementations;
}
Example to call:
List<IPlugin> plugins = LoadPlugin<IPlugin>(path);
As for the c++ part of your question. There are few different ways you could approach this, though the correct choice depends on your specific situation. You can make a clr compliant .dll in c++, which your c# project could reference and call like any other .dll it references. Additionally, you could use P/Invoke to call into a native .dll.
One of the easiest plugin concepts I have ever used was certainly the Managed Extensibility Framework which will be part of .NET 4 (afaik). Unfortunately it is not yet finished and only a preview is available which may differ from the final version. That being said, we used MEF Preview 3 for a uni project and it worked without problems and it certainly made the whole plugin stuff a lot easier.
Look at the System.Addin namespace :
http://msdn.microsoft.com/en-us/library/system.addin.aspx
Otherwise you can do everything yourself. Before this namespace was available, I used a common interface "IPlugin" that every plugin/addin needed to use. I then had a loader which inspected all the *.dll in a folder then used reflection to check for the interface. I could then create instances of classes which implemented my plugin/addin interface
The cpp files will probably need converting to c#, or you could possibly create a dll to reference.
Take a look to Castle.
.NET Framework use COM model in its guts. See http://blog.caljacobson.com/2007/07/26/creating-a-plug-in-framework-in-c-resources/ for a list of plugin example using this techique.

Categories

Resources