Short answer is: you need to load the assembly from file using
System.Reflection.Assembly.LoadFrom(string fileName)
. This is the simplest case. You can load assembly placed in CAG and use other
Load
of
LoadFrom
methods. Please see:
http://msdn.microsoft.com/en-us/library/system.reflection.assembly.aspx[
^].
When this is done, you can use the obtained reference to the
Assembly
object and use Reflection to find one or more classes you want to use and ultimately use
ConstructorInfo.Invoke
to instantiate one or more classes, or use
MethodInfo.Invoke
to call some static method(s) immediately (apparently, you don't need an instance to call a static class); the same way, you can use
PropertyInfo
and its getter or setter methods to set/get a static property value. You can call non-static methods/properties using the reference to the instance of the class obtained on the previous step. Please see:
http://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.aspx[
^],
http://msdn.microsoft.com/en-us/library/system.reflection.propertyinfo.aspx[
^].
Selection of proper schema for such operations needs some thinking. In particular, it's pretty bad to use names of the classes or members, because this is not supportable: the compiler won't detect an error if you misspell such name or change it later. The safest approach is to define some plug-in interface accessible by both host application and the plug-in and search for the classes implementing this interface. Please see this method to be used to check is some class or structure implements some interface or not:
http://msdn.microsoft.com/en-us/library/system.type.isassignablefrom.aspx[
^].
When you use the method
System.Type.IsAssignableFrom
, you should use it on the interface type:
System.Type type =
if (typeof(IMyPlugin).IsAssignableFrom(type)
I usually make one more step to avoid scanning all available types. I introduce a custom assembly-level attribute which claims which types implement what interface — it saves time and eliminates the problem where several classes/structures implement the same interface, so it would not be clear which one to use. At the same time, this claim should be validated during run time, but this is unavoidable in all cases.
The above techniques are fairly easy as soon as you don't want to unload and assembly. This is not possible, so the only way of unloading anything is loading the assembly in a separate Application Domain. It would force you to work through the Application Domain boundary, which means using IPC. I analyze this problem and overview the architecture in further detail in my past answers:
Create WPF Application that uses Reloadable Plugins...[
^],
AppDomain refuses to load an assembly[
^],
code generating using CodeDom[
^],
Create WPF Application that uses Reloadable Plugins...[
^],
Dynamically Load User Controls[
^],
C# Reflection InvokeMember on existing instance[
^] (invocation is explained in further detail here),
Projects and DLL's: How to keep them managable?[
^].
—SA