Geeks With Blogs

News




What I do:

Identity Mine

MVVM Light

GalaSoft


What I am:

Microsoft Most Valuable Professional, Client Application Development

Microsoft Certified Technology Specialist, Windows Presentation Foundation

WPF disciples


Social:


View my profile on LinkedIn

XING
Creative Commons License
Diary of a Code Trotter by Laurent Bugnion is licensed under a Creative Commons Attribution 3.0 Unported License

All source code on this blog is licensed under the MIT license.

Copyright (c) 2006 - 2011 GalaSoft Laurent Bugnion

Laurent Bugnion (GalaSoft) Diary of a Code Trotter
Introduction
(Note: This article is not strictly speaking for WPF only, the technique described works for any type of .NET application. In next articles, we'll study WPF-specific techniques, for example loading XAML resource assemblies dynamically.)
There are many scenarios where an application doesn't know at build time exactly which DLLs are going to be available at runtime. For example, you may want to provide a UI framework and then develop components at a later time running in that framework.
In .NET (WinForms or WPF), this is made possible by the following features:
  • UserControls (or CustomControls) derive from a well known UI component (Control), which can be loaded in a panel.
  • Assemblies can be loaded dynamically in the current AppDomain, using the methods Assembly.Load, Assembly.LoadFile, Assembly.LoadFrom.
Note: there are differences between LoadFile and LoadFrom. See here for details.
LoadFrom must be used with care, because the assembly's identity check is less strict than when the assembly is linked at build time, or when it is loaded using LoadFile. However, for scenarios where the loaded assembly references other assemblies, LoadFile doesn't work. Also, Assembly.LoadFrom can be used to load assemblies over HTTP, which is useful for applications running as web clients (either embedded in IE like WPF XBAPs, or for web-enabled rich internet applications.)
Also, this quote from MSDN:
"Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly."
Design
To allow the "UI framework" to load and use the user controls located in the dynamically loaded assembly, an interface must be defined. To allow greater flexibility, this interface is defined in a separate assembly called Interfaces.dll. The user controls must implement this interface.
Additionally, the user controls may throw events, which can be caught by the containing UI framework. These events must also be defined in the interface, so that the contract is clear between both parties.
So we have the following design:
Design for UI framework and plug-ins
To load the plug-in assembly in the framework, we can use the following code:
// assemblyPath is "c:\\..." or "http://..." Assembly plugInAssembly = Assembly.LoadFrom( assemblyPath ); IComponent plugIn = plugInAssembly.CreateInstance( "GalaSoftLb.Wpf.PlugIn.MyComponent" ) as IComponent; plugIn.ValueChanged += new ValueChangedHandler( plugIn_ValueChanged ); this.Content = plugIn;
After we load the plug-in assembly, we instantiate the plug-in, subscribe to its event and then (in WPF), we assign the newly created plug-in to be the window's content. This is possible without casting, because the Content property is of type object. Of course, if the plug-in is not of a suitable type, an exception will be thrown at runtime.
Because LoadFrom is very versatile, you can use it to load files located on the file system (you'll need FileIOPermission) or files located on the web (you'll need WebPermission). Note however that you can only load DLLs located on the XBAP's server-of-origin).
In WPF, we have one more very important reason to want to load assemblies dynamically: Styles! With WPF, a new workflow between software developers and graphics designers is made possible by the separation of content and design information. The developer concentrates on the application's functionality, and the designer on the look&feel. To allow a smooth workflow, it makes sense to store the resources which the designers will work on in separate assemblies. These assemblies will typically be compiled at a later time. Also, we may have various themes, so various assemblies with different versions of the same resources. This is what we will concentrate on in the next article (coming soon ;-)
Posted on Wednesday, March 7, 2007 6:31 PM Technical stuff , .NET , WPF | Back to top


Comments on this post: WPF musings: UI framework and plug-ins

# re: WPF musings: UI framework and plug-ins
Requesting Gravatar...
Hi,

I am trying to do something very similar to you, I have a plugin architecture and if you install a plugin into the plugin directory then a listener picks this up and loads it.

This was all working find in WinForms but when I switched to WPF I started having problems. If the DLL was present in the plugins folder when starting the application then everything would be fine. If however, you put the dll into the folder once the main application was loaded then I receive an exception:

"The component 'xyzControl' does not have a resource identified by the URI '/Assemblyname;component/directory/xyzControl.xaml'."

Do you have any idea whats happening here?
Left by Mike J on Apr 24, 2007 11:30 PM

# re: WPF musings: UI framework and plug-ins
Requesting Gravatar...
Hi,

I am trying to do something very similar to you, I have a plugin architecture and if you install a plugin into the plugin directory then a listener picks this up and loads it.

This was all working find in WinForms but when I switched to WPF I started having problems. If the DLL was present in the plugins folder when starting the application then everything would be fine. If however, you put the dll into the folder once the main application was loaded then I receive an exception:

"The component 'xyzControl' does not have a resource identified by the URI '/Assemblyname;component/directory/xyzControl.xaml'."

Do you have any idea whats happening here?
Left by Mike J on Apr 24, 2007 11:30 PM

# re: WPF musings: UI framework and plug-ins
Requesting Gravatar...
Hi Laurent,
Did you considered the new AddIn extensibility model in .NET 3.5??

We made quite some complex interfaces by using this model (even from B2 stages, and adapted to the latest).

Please see our movie at www.sobees.com. Tell me what you think about it. It's totally WPF, WCF and AddIn based.

Later on, anyone would develop addIns for it.

Kind regards,
C. Marius
Left by C. Marius on Nov 28, 2007 11:08 PM

# re: WPF musings: UI framework and plug-ins
Requesting Gravatar...
Hi,

When I wrote this, the add-ins model was quite unclear. We considered using it, but we were approximately 1 year too early. That said, we are considering porting our current architecture to that model, for various reasons, especially the stability brought by the AddIn model, and the possibility to unload AppDomains. I am happy to hear that you used it for SoBee, Vincent and I had quite a few discussions in that direction. Send him my regards!

Laurent
Left by Laurent on Nov 29, 2007 12:16 AM

Comments have been closed on this topic.
Copyright © Laurent Bugnion | Powered by: GeeksWithBlogs.net