I am working on a side-project involving a small self-hosted Nancy server for the local network to remotely control a media player. To enable support for multiple players I implemented a simple plugin mechanism like it was outlined here:
http://code.msdn.microsoft.com/windowsdesktop/Creating-a-simple-plugin-b6174b62
The dynamic loading and execution works great, but the problem I am running into is how to tell TinyIoC which plugin implementation to use. At the moment I have a subdirectory named plugins where the .dlls are stored and at startup TinyIoC discovers the one test dll in this directory and wires up the dependency without me choosing anything explicitly.
I found the method Bootstrapper.ConfigureApplicationContainer to be the place to do DI configuration but since I want to use a dynamic system and do not have the server project a reference to all plugin assemblies that is not sufficient in my case.
Is this even possible with TinyIoC or do I need to look for another IoC container?
Thanks a lot in advance
Not sure if this suits your needs, but it's suggestion anyway: You could have each of the plugins do its own container configuration, by having each of them provide an implementation of IRegistrations in plugins .dll.
Nancy will pick implmentations of IRegistrations up automatically - as long the assemblies are loaded at startup - and execute them during application startup.
Alternatively you could scan the plugins directory yourself in the Bootstrapper.ConfigureApplicationContainer method and scan the plugin .dlls for either IRegistrations or your own custom hook.
Related
In my Asp.Net MVC application, i have some view file (.cshtml) which has reference to an external library which it will be loaded at runtime. so after app started, i load the assembly by Assembly.Load and i register the controllers by my own custom ControllerFactory and every thing is ok.
But, in some views which has references to the dynamically loaded assembly, throws the :
Compiler Error Message: CS0234: The type or namespace name 'MyDynamicNamespace' does not exist in the namespace 'MyApp' (are you missing an assembly reference?)
exception that tells the razor compiler cannot resolve the related assembly.
My question is that, is there a way to register the assembly at runtime, to able the razor compiler can access to it and resolve it?
Notice that i can't use BuildManager.AddReferencedAssembly method because my assembly have to be loaded after app start, and the BuildManager does not support it.
1) I wouldn't recommend having your views directly use external references or dynamically loaded external references. Abstract this by having your view interact with a controller. Make your controller feed a data object to your view that is known at build time by your application (in other words, an object known to your web application at build time). This is to completely isolate (abstract) plugin specific business from your view. Then make your controller interact with the "plugin".
2) I don't know how your "custom factory" works but nowadays we don't really build any "custom factories" anymore. Instead we leverage dependency injection containers such as Microsoft Unity(or Ninject, or Castle Windsor or etc..). Creating "custom factories" is very old fashioned and you're basically reinventing the wheel that has been solved with dependency injection.
3) As far as dynamically loading external assemblies, I don't know if you have it right but here's a link:
Dynamically load a type from an external assembly
4) Typically, a plugin design exposes interfaces that are known to your main web application at build time. What the plugin design hides is the implementation which can change from one plugin to another. The important thing is that each plugin implements the same public interfaces, those that are expected by your main web app. Usually, you will have those interfaces in a separate "Common" project that is referenced by both, your main web application and your plugin that implements those interfaces. Therefore, from your main web app, you will know what the public interfaces of your plugins are, you can dynamically load the external assembly and use C# reflection to find the classes that implements those interfaces and load them into your dependency injection container. Likewise, anyone who will want to develop of a plugin for your web app will have to implement the interfaces that are defined in your "Common" project.
Note: "Common" is just a random name I gave to the project. You can name it "PluginInterface" or whatever you want.
After that, having your controller grab whatever it needs from the dependency injection container is trivial.
Note: Your plugin interfaces will probably have input and output entities. These entities are shared between your main web app and your plugin. In such case, since these entities are part of your interfaces they need to be in the "Common" project. You may be tempted to have your controller return those entities directly to your view but then you won't have a perfect abstraction between your view and your plugin. Not having perfect abstractions is for another discussion.
Hope it helps!
As a Sys Admin, I would recommend a maintenance period, especially if the file you replace messes something else up. Even if your maintenance period is only a half hour it is good practice.
As for the DLL and recompile... typically the IIS Worker Process (the service running your application pool) will recycle at normal intervals based on the IIS configuration and memory usage. When this happens the application will recompile if anything requires the JIT. It also terminates all open user sessions as it physically stops and then re-starts. The worker process also monitors the root directory (like you mentioned) for any file changes. If any are found a recompile is forced. Just because a dependency is changed does not force a recompile. If you pre-compile your DLL the only thing left to compile is any code inside of your actual ASPX file and this uses the JIT which compiles each time. From what you described IIS should not need to recompile or restart, sounds like another problem where IIS is hanging when you swap out the file. Might need to get a sys admin involved to look at the IIS logs.
Good Luck!
http://msdn.microsoft.com/en-us/library/ms366723.aspx
http://msdn.microsoft.com/en-us/library/bb398860.aspx
Here is a note that may helps: If you are not loading your assemblies from the /bin directory, you need to ensure that the path to the assemblies is discoverable:
AppDomain.CurrentDomain.AppendPrivatePath(path_to_your-dyna_assembly);
I have 2 OCX's with 2 different versions. These are 3rd party ocx's. Each ocx have set of methods, properties and events which are almost same in both the version except few. I compile my projects twice for publishing. So I have 2 click once deployments - one with version 1 and another with version 2. I ask my users to use version if they have version 1 software installed on their system and so on.
I would like to know if there is a way where I compile and deploy only one version of my application and depending in the version of 3rd party software installed on user's system, my application will pickup that ocx version during runtime?
Or is there a way I implement an interface where I code/inherit all properties, methods and events and do a late binding?
Any suggestions are welcome.
You can use container like Structure Map or Castle or AutoFac.
When your app will start it will determine if the 3party software is installed and fill the container wiht proper implementation of an interfaces. Than when you will need the class object you call the container to give it to you.
You can use service locator pattern (static class to container) - it is simpler and requires less work but makes your code tied up to a container implementation or if you want you can resolve all classes at startup of your app.
Give it a try, there is a lot of help to this online.
I'm developing a .Net desktop app that interacts with scientific instruments. There are a number of variations of this instrument, each with different features, components, etc, so I've come up with a plugin/modular architecture where a "module assembly" contains all of the necessary business logic, UI, etc. to interact with that hardware component/feature.
Currently I have one solution that contains everything - the "core" application project, common libraries, plus the "module" projects. The idea is that we install the whole lot to a customer site (rather than cherry-picking which DLLs they need), and "activate" the relevant modules using a config file that contains a list of required modules.
The main application project loads the modules using Castle Windsor, using an AssemblyFilter and a custom InstallerFactory. It searches each module assembly looking for a class implementing IWindsorInstaller and decorated with a particular custom attribute (which has a property containing the module name). The module's installer will only be run if the attribute's module name is one of those requested. These installer classes are responsible for registering everything needed by that module with Windsor (business logic, views, view models, etc.).
This solution works fine in my proof of concept, however I can see a scenario where two or more modules are functionally very similar, and will therefore need to share common code. Let's say I have projects "ModuleA" and "ModuleB", and their Windsor installers registers the same IFooService class in project "ClassLibraryX". The app will fall over because IFooService has been reigstered twice, and Windsor won't know which one to resolve when requested by a constructor.
What's the best way to handle this? Thoughts so far:-
Find out if a particular component has already been registered with Windsor. This feels hacky (if possible at all)
Register components using a name, but how do I request a named instance with constructor injection?
In each module project create a new interface, such as public interface IModuleAFooService : IFooService, and register/use this throughout the project (rather than IFooService).
Any thoughts?
Edit: in fact Windsor won't fall over when it tries to resolve IFooService. It will fall over when the second module attempts to register the same interface/concrete implementation!
The way I see it, you have a couple options. I think you have two main issues. The first is that you are installing the shared interface twice (or more than that). The second is that you could have two different versions of the shared interface.
For the first issue, I would separate out the shared interfaces into their own assembly. Inside that assembly, I would have an installer that is scoped to that assembly. Then, you can tell Windsor to install that shared component and it knows how to wire itself up.
For the second issue, you have two options (as I see it). First option is that you keep your shared components backwards compatible. Second option is to isolate you runtime (through app domains or processes).
Can you not provide some meta-data for the plugin, i.e give each plugin implementation a name attribute which can be used by windsor to identify which of the implementations you want?
I have not used Castle too much recently but I am sure it did have the notion of named Bindings/Registrations, so you could use that as a way to distinguish things, if that is not going to be possible and there is no other meta data you can think of using which would make it less ambiguous for Windsor, then I would just opt with your 3rd option.
Having just read your 2nd option again (after writing the above) that seems the best option, I cannot remember EXACT syntax but in most DI frameworks you do something like:
var instance = Get<IMyInterface>("Named This");
There will be loads of syntax examples on their documentation somewhere, but you will need to know the name on both the Windsor side to register it AND on the client side to request it.
Named instances are ok. You can define dependency on concrete named service via DependsOn(Dependency.OnComponent("paramName", "serviceName")) method in fluent configuration.
I am just playing with Microsoft Unity 2 now, and need to know whether it's possible to configure a container so it loads up the assemblies from the file system, rather than having to configure it to load from config file (which contains all the mappings to the right assemblies) or register the type objects programatically. I need this to essentially load plugins. All plugins have implemented the same contract interface. What I want to achieve is that I can drop a new assembly (plugin) in the main app folder and that is automatically discovered by Unity. is that possible or I need to use MEF for that?
any help is very much appreciated, thank you very much.
Unity does not support that behavior out-of-the-box. But it is not difficult to implement it.
A FileSystemWatcher can notify your application whenever you drop a new assembly in your plugin folder. Then it is just a matter of conventions, what you do with that new file. Use Assembly.Load to load you DLL. Then you can scan it for implementations of your interface
assembly.GetExportedTypes().Where(t => typeof(IMyInterface).IsAssignableFrom(t))
and then you need to register your implementations with the container.
As this service is part of your infrastructure I think its OK to reference your container there which I would rather avoid otherwise.
I've written a program using Domain Driven Design in .NET 2.0 and I'm trying to implement a plugin framework for it.
I've implemented several types of plugins:
Domain Plugin
A domain aggregate composed of one or more domain classes
One or more View/Presenter pairs to display instances of the aggregate
An import/export service specific to the domain aggregate
A repository class
Service Plugins
Database Plugin (embedded or remote)
General import/export services (cvs, xml, competitor's data formats, etc)
As you can see, some plugins touch every layer of architecture. You could say that the domain plugins are miniature applications that simply depend on the main application to provide a framework in which to run. The ultimate goal is to let the user purchase and download only the plugins they need. I wrote them as static dependencies at first because I hadn't implemented a mechanism to load them dynamically. Now I'm trying to tackle the dynamic loading.
I'm trying to use an IoC container to manage the dependencies but I'm having difficulty working out how to find and load the plugins. In addition to the interfaces each plugin exposes to the main application, classes with each plugin also have their own interfaces they use to communicate with each other.
I'm using Castle Windsor as my IoC container and would like to take advantage of its autowiring capabilities both in the application and within each plugin as well.
How do I:
Find and load into Windsor implementations of a specific interface
Ensure Windsor resolves the correct one
If you think I'm going about this the wrong way feel free to say so. I still have time to change the design before my deadline.
I'm note sure I've understood you completly but consider looking at MEF (http://mef.codeplex.com/)
You could use something like the Managed Extensibility Framework to discover and enumerate your plugins at runtime. The plugins could then register the necessary types with your IoC container when they are discovered.