Click here to Skip to main content
15,880,608 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have been going through examples the whole night, cant seem to find anything simple enough to exmplain what I am looking for.

I need to dynamically add a dll to my project, create an instance of it, and invoke it's methods. Let's say I have the follwing dll file with the following method, but I do not know the namespace, or the name of the class.

C#
public string Greeting(string Name)
{
   return "Hello " + Name;
}


How would I go about loading the dll into an assembly/app domain, and create an instance of the unknown class that is in the dll, in my project, and access the method Greeting that is within the dll?

Can anyone please help me?
Posted

1 solution

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:
C#
System.Type type = //get from Reflection, from the assembly in question
if (typeof(IMyPlugin).IsAssignableFrom(type)
   //it means that type implements IMyPlugin


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
 
Share this answer
 
v2
Comments
Andrew797 30-Apr-12 17:51pm    
When I use the following: Assembly a = Assembly.LoadFrom("C:\\temp\\HELLO.dll");

Console.WriteLine(a.ToString());
Console.WriteLine(a.GetName().Name);

output: HELLO, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
HELLO

where should I go from here? What does all of these ouputs mean?

I understand how to invoke the methods, but seem a bit lost with finding the class name, and the namespace name
Sergey Alexandrovich Kryukov 30-Apr-12 18:10pm    
It has nothing to do with what you need to do. When you print something, the object.ToString is called. Very often, this is just a type name, not really usable.
When you call GetName, it returns the assembly name object, a structure with different assembly attributes.
It's useful to see what is there, but you could do in in the debugger. You need to do Assembly.GetTypes() and traverse all the types. Of create an assembly-level attribute to consider just one type and use Assembly.GetType(...).
Then, you have type. Use Type.GetMembers, Type.GetFields, Type.GetConstructors -- the last one important for activation. I already explained where to go, but you need to go with MSDN help pages on each type/method I mentioned, + see what else is relevant. This is all Reflection, where your work should start. Learn it all as you need it step by step. You can really walk it through in one day even if you are a beginner in Reflection. Just do it.

And, if you agree this makes sense, please accept the answer formally (green button).
If you still feel you are lost, try to ask further questions, but better try to exercise this API -- with MSDN help page, it's surprisingly easy to do.
--SA
Sandeep Mewara 1-May-12 3:25am    
5++ :thumbsup:
Sergey Alexandrovich Kryukov 1-May-12 10:58am    
Thank you, Sandeep.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900