I'm trying to implement a plug-in like application. I know there are already several solution out there but this is just going to be proof of the concept, nothing more. The idea would be to make the application main application almost featureless by default and then let the plugins know about each other, having them have implement all the needed features.
A couple of issues arise:
I want the plugins at runtime to know about each other through my application. That wouldn't mean that at code-time they couldn't reference other plugin's assemblies so they could use its interfaces, only that plugin-feature initialization should be always through my main app. For example: if I have both plugins X and Y loaded and Y wants to use X's features, it should "register" its interest though my application to use its features. I'd have to have a kind of "dictionary" in my application where I store all the loaded plugins. After registering for interest in my application, plugin Y would get a reference to X so it could use it. Is this a good approach?
When coding plugin Y that uses X, I'd need to reference X's assembly, so I can program against its interface. That has the issue of versioning. What if I code my plugin Y against an outdated version of plugin X? Should I always use a "central" place where all assemblies are, having there always the up to date versions of the assemblies?
Are there by chance any books out there that specifically deal with these kinds of designs for .NET?
Thanks
edit: I think people are drifting away from the 2 questions I made. I can take a look at both MEF and #develop, but I'd like to get specifics answers to the questions I made.
I recommend looking into MEF. This is a new way of doing plugins in .NET. It is the recommend way of doing new addins for VS2010, for example. I've not used it myself, but what I've looked into about it looks great. Adding this as an answer on prodding of others :)
Look into the System.AddIn namespace. It's a little lower-level than MEF, and so should give you the "implement it myself" experience you're looking for.
There is a good book on building what you are looking for: Dissecting a C# Application: Inside SharpDevelop. Here's a link: http://www.icsharpcode.net/OpenSource/SD/InsideSharpDevelop.aspx
The SharpDevelop application is fully plugin-based and the book talks about how they built it, the pitfalls they faced, and how they overcame it. The book is freely available from the site, or you can buy it too.
Once I done it using this example. I loved it, but it was couple years ago, I think there might be better solutions now. As long as I remember the basic idea was that there is abstract class in your program, and your plug-ins inherit that class and compiled as DLLs... or something similar using Interfaces. Anyways that approach worked great for me. Later I added a filesystemwatcher so it could load those DLL plugins while it is running.
To load an Assembly
To get the types the assembly exposes
About the two specific issues you exposed:
1) I'm not sure what are you trying to achieve, but my guess is that you want to have lazy initialization of features, and maybe lazy loading of add-ins. If that's the goal, what you are proposing might work. So it could work like this:
The Y plugin provides a list of features it needs to use (it could be done for example through a specific interface implementation or through an xml manifest).
The X add-in implements an API which allows initializing a feature, with a method like Initialize(featureId).
The host application gets the feature list required by Y, loads/initializes the X plugin, and calls Initialize for each feature.
The host application also provides a GetFeature() method which Y can use to get a reference to a 'feature' object, which would be implemented in X.
However, if the plugin Y has direct access to the X API, I think it is unnecessary to have all that infrastructure for registering features. Y can just access the X features by directly using the X API, and Y would take care of lazy initializing each feature when required. For example, Y could just call SomeXFeature.DoSomething(), and the implementation of that class would initialize the feature the first time it is used.
2) If the API of an assembly changes, any assembly depending on it may break. Plugins are just assemblies which depend on other assemblies, so they will also break. Here are some things you can do to alleviate this problem.
Assign a version number to each plugin. This could be just the assembly version.
When loading a plugin, ensure that all dependencies can be properly satisfied (that is, all plugins on which it depends must be present and have the required version). Refuse to load the plugin if dependencies can't be satisfied.
Implement a plugin management tool, to be used for all plugin install/uninstall operations. The manager can check dependencies and report errors when trying to install plugins with unsatisfied dependencies, or when trying to uninstall a plugin on which other plugins depend.
Similar solutions are used by the Mono.Addins framework. In Mono.Addins, each add-in has a version number and a list of add-ins/versions on which it depends. When loading an add-in, the add-in engine ensures that all dependent add-ins with the correct versions are also loaded. It also provides an API and a command line tool for managing the installation of add-ins.
Related
I have an assembly that provides an API and is used by some other assemblies. I need to verify that a newer version of API dll is still compatible with the older assemblies that were using the older version of API.
I've found a couple of questions that ask the same, but there are no answers that resolve my problem:
Tool to verify compatibility of a public APIs
Tool for backwards compatibility for the C#/.NET API
Suggested tools can only compare two assemblies and say if there are possible breaking changes in API, but not if the newest API really breaks the older assembly that uses it.
I'd like to find a tool or write a test that will be able to check whether each of the older dlls can work with my new API dll.
As for the changes in API more likely that I will only extend it, but even though it still can break the code in older assemblies. Some of the examples of such changes can be found here:
A definite guide to API-breaking changes in .NET
.NET: with respect to AssemblyVersion, what defines binary compatibility?
For now the only solution I see is to compile the source code of the older assemblies with the newest API, but I would like to do it only with assemblies and add them as part of my unit tests. Is there any better way I can handle that?
edit:
I'm looking for a tool that will be able to automate the process of verifying the backward compatibility between .net assemblies. (command line or with some api too)
What you want is to do a diff and generate a the list of breaking changes. Then you want to search if of your assemblies does use any of the broken APIs. You can do this with ApiChange tool to do the diff and to find any affected users of it.
To make it more concrete. If you have removed a method from an interface then you need to find all implementers and users of this method in classes which uses the interface method or any class that does implement this method.
ApiChange can search for implementers and users of specific methods on the command line with the commands -whoimplementsinterface and -whousesmethod. It is not automated at the command line but you can directly use the ApiChange.Api.dll to automate this queries.
Edit1:
I just forgot: The ApiChange tool has actually the functionality you are interested in already. It is the option
-ShowrebuildTargets -new -old [-old2 ] -searchin
We did use it in our department with good results. The only gotcha are the XML Intellisense files. If another target does not use the removed method but references it inside the XmlDoc the compiler will write a warning that a non existing method was referenced. This is quite hard to catch and would involve to parse the intellisense docu files as well. But this is quite an edge case.
I've spent the day looking around for an answer to this. It seems like the tools referenced on the related (unhelpfully closed) questions are now dead or as good as. But I've just taken a look at Telerik's assembly diff tool JustAssembly and this looks much better than rolling your own, which, if you look at their library seems to be a whole heap of work and likely to go wrong.
They have a UI which isn't of that much help from the point of view of integrating into your CI build, it is pretty basic, but you can build the library from source, which I've just done and the library looks like it has everything you need to get yourself up and running pretty quickly.
I've gotten to the point where I have made a few classes that I have found to be rather useful for a variety of different projects, they're either extensions of the already existing .Net ones or something entirely new.
Although I may not use them for EVERY project I would most certainly use them again at some point, my questions is what is the best way to keep these stored?
I was thinking about compiling them into a .dll that I can simply reference if necessary but at the moment there are only about 4 different classes, I've always thought that a .dll is more suited towards a larger amount of classes.
Would it just be simpler to store them somewhere in the cloud so I can access them from pretty much any computer?
What has worked best for you?
Edit: I'll be using more than one computer as I sometimes use the university computer facilities.
The classes range from memory management helper classes in XNA to niche functions in regular .Net/C#
If the classes don't fit together naturally as an assembly, keep the source files somewhere like Github and include them in your projects where needed. You can always rearrange them into components at a later date, when you feel it's worthwhile.
Are these classes in any way related? If you want to use one of them, do you need the others? If not, then those don't belong in a common package together.
Robert C. Martin provides some decent introduction in the chapter "Principles of Package and Component Design" of his book "Agile Software Development". There is also a C# adapted version with very similar content called "Agile Principles, Patterns and Practices in C#".
What I'm just saying is, packaging components is not only about thinking components X and Y are "cool enough" to be reused, but also about how you organize things and how well libraries or packages fit into the big picture.
You could compile them as a DLL and install them to the GAC. Then you can reference the DLLs from any project you need, just like any native C# library.
And I agree with Jim Brissom. Compile only the classes that go together as one assembly.
I keep my common classes in sourcegear and then share them into any projects as required.
I'm starting a new project which would greatly benefit from program add-ons. The program in its most basic form reads data from a serial port and parses it into database records. Examples of add-ons that could be written would be an auto-archive add-on, an add-on to filter records, etc. I'm writing both the program and the add-ons, but some customers need custom solutions, so instead of branching off and making a completely separate program, add-ons would be great. The simplest add-on would probably be a form who's constructor takes an object reference, manipulates the object in some way, then closes.
Unfortunately, I have absolutely no idea where to start coding, and almost as little idea where to search. Everything I search for turns up browser add-ons. From what I have gathered, I need to look into dynamic loading DLLs. Besides that, I'm clueless. Does anyone have any good resources or examples I that they know of?
I'm happy to provide more details, but this project is in its inception, so I don't have a ton of specific details (specifics kind of defeats the point of add-ons, too.)
You should seriously consider using the Managed Extensibility Framework (MEF) to handle your plugin architecture. It requires thinking about things a little differently, but it is well worth the mind-stretch.
This is a simple example to illustrate the basic technique.
codeproject.com - Plugin Architecture using C#
This article demonstrates to you how
to incorporate ... as a
plugin for another application or use
it as a standalone application.
in .NET 4 you now have the Managed Extensibility Framework (MEF) to do much of the plumbing.
In .NET 3.5 you had the System.AddIn but it was deemed by many to be far too complex.
codeproject.com - AddIn Enabled Applications with System.AddIn
AddIns (sometimes called Plugins) are
seperately compiled components that an
application can locate, load and make
use of at runtime (dynamically). An
application that has been designed to
use AddIns can be enhanced (by
developing more AddIns) without the
need for the orginal application to be
modified or recompiled and tested
You really need to look at Managed Extensibility Framework (MEF). This is specifically designed to help support add-ons and other extensibility.
A very basic description (basically, your plugins must implement a special interface):
http://martinfowler.com/eaaCatalog/plugin.html
Much better article, in C#:
http://www.drdobbs.com/184403942;jsessionid=TVLM2PGYFZZB1QE1GHPCKHWATMY32JVN
I think Reflection will play a major role.
I expirimented with an app that had a plugin folder. A filesystem watcher would watch the folder, and when a new DLL was placed in it, it would use reflection to determine which types of plugins it included, loaded them, and added them to the list of available classes, etc.
Try using the term 'add-in' or 'plug-in' for your research instead of 'add-on'. That should help some.
If you're using .Net 4, there's an add-in namespace in the framework that will get you partway there.
Writing plug-in support for an app is no simple task. You'll have to maintain pretty strict separation-of-concerns across your interfaces, you'll need to provide an interop library that defines ALL of the supported plug-in types, and you'll want to do some research into dependency injection & inversion of control, in addition to the previously-suggested reflection research.
It sounds like you might have a busy weekend doing research.
I just recently finished Michael Feathers' book Working Effectively with Legacy Code. It was a great book on how to effectively create test seams and exploit them to get existing code under test.
One of the techniques he talk about was using "link seams". Basically the idea was that if you had code that depending on another library you could use the linker to insert a different library for testing than for production. This would allow you to sense test conditions through a mock library, or avoid calling into libraries that have real world effects (databases, emails, etc.), etc.
The example he gave was in C++. I'm curious if this technique (or something similar) is possible in .NET / C#?
Yes it is possible in .Net. In the simplest case, you can just replace an assembly with another one of the same name.
With a strongly named assembly, you should change the version number and then configure assembly bindings to override the compile time "linked" version. This can be done on an enterprise, machine, user or directory level.
There are some caveats, related to security. If the assembly you wish to substitute has been strongly named, then you will need to recreate the same public key in signing the assembly.
In other words, if you as the application developer do not want your libraries "mocked" (or perhaps replaced with malicious code) then you must ensure that the assembly is signed and the private key is not publicly available.
That is why you cannot mock DateTime -- because Microsoft has strongly named the core libraries of .Net.
That sounds something a bit like the things Typemock isolator offers, in particular their claimed ability to rip out and mock existing types. But I've never used it ;-(
As an example, DateTime.Now is something that shouldn't be mockable, right?
alt text http://site.typemock.com/storage/feature-images/dateTime.png?__SQUARESPACE_CACHEVERSION=1252774490561
Problem
Language: C# 2.0 or later
I would like to register context handlers to create menues when the user right clicks certain files (in my case *.eic). What is the procedure to register, unregister (clean up) and handle events (clicks) from these menues?
I have a clue it's something to do with the windows registry, but considering how much stuff there is in .net, I wouldn't be surprised if there are handy methods to do this clean and easy.
Code snippets, website references, comments are all good. Please toss them at me.
Update
Obviously there is a slight problem creating context menues in managed languages, as several users have commented. Is there any other preferred way of achieving the same behaviour, or should I spend time looking into these workarounds? I don't mind doing that at all, I'm glad people have put effort into making this possible - but I still want to know if there is a "proper/clean" way of achieving this.
Resist writing Shell Extensions in managed languages - there are a multitude of things that could go bang if you pursue this route.
Have a browse through this thread for more details. It contains links to do it if really want, and sagely advice of why it can be done, but shouldn't.
http://social.msdn.microsoft.com/Forums/en-US/netfxbcl/thread/1428326d-7950-42b4-ad94-8e962124043e/
You're back to unmanaged C/C++ as your only real tools here.
This is not a good idea because of potential dependency issues between different versions of the .NET Framework. Your shell extension could be expecting one version, while a different version may have already been loaded by the application that's currently running.
This thread contains a good summary of the situation.
While others already mentioned that writing shell extensions in pure .NET is a bad idea due to framework conflicts, you should still note that:
There are 3rd party drivers out there (see Eldos or LogicNP) that do the unmanaged side for you, allowing you to write managed code that talks to the native driver, thus preventing shell-related CLR version conflicts.
A recent MSDN article mentioned that Microsoft has solved this problem for the CoreCLR, as used by Silverlight. They've accomplished this by allowing multiple versions of the CLR to run in the same process, thus fixing the problem. The author further stated that this fix in Silverlight will be rolled into future versions of the full CLR. (Meaning, in the future, it will be quite feasible to write shell extensions in managed code.)
I've done them before in C#. It ends up being a hell of a lot harder than it should be. Once you get the boilerplate code down, though, it is easy to roll out new items. I followed this link:
Link To Info
As the prior comments mention, it isn't the best idea to write shell extensions in managed languages, but I thought I'd share an Open Source project that is doing just that :)
ShellGlue is a managed shell extension that is actually quite helpful. The source also might be helpful to you if you're interested in pursuing writing a shell extension in C/C++.
Aside from the caveats that have been mentioned concerning the implementation of shell extensions in managed code, what you'd basically need to do is the following:
First, create a COM component in C# that implements the IShellExtInit IContextMenu interfaces. How to create COM components in C# is described here. How to implement the necessary interfaces is described in this article. While the description is for a C++ implementation, you can apply that knowledge to you C# version.
Your COM component will have GUID called the Class-ID or CLSID. You need to register that ID with your file type as a context-menu shell extension:
HKEY_CLASSES_ROOT\.eic\ShellEx\ContextMenuHandlers\MyShellExt
(Default) -> {YOUR-COMPONENTS-CLSID}
Also make sure that you registered your component correctly as described in the C# COM tutorial. You should find it in the registry under
HKEY_CLASSES_ROOT\CLSID\{YOUR-COMPONENTS-CLSID}
InprocServer32
(Default) -> C:\WINDOWS\system32\mscoree.dll
Class -> YourImplClass
assembly -> YourAssembly, version=..., Culture=neutral, PublicKey=...
...
Good luck...
As others have pointed out, shell extensions are not practical in windows development currently.
I asked a similar question recently which was answered with a link to a guide to do exactly what I wanted to do