Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct Way to Load Assembly, Find Class and Call Run() Method

Sample console program.

class Program {     static void Main(string[] args)     {         // ... code to build dll ... not written yet ...         Assembly assembly = Assembly.LoadFile(@"C:\dyn.dll");         // don't know what or how to cast here         // looking for a better way to do next 3 lines         IRunnable r = assembly.CreateInstance("TestRunner");         if (r == null) throw new Exception("broke");         r.Run();      } } 

I want to dynamically build an assembly (.dll), and then load the assembly, instantiate a class, and call the Run() method of that class. Should I try casting the TestRunner class to something? Not sure how the types in one assembly (dynamic code) would know about my types in my (static assembly / shell app). Is it better to just use a few lines of reflection code to call Run() on just an object? What should that code look like?

UPDATE: William Edmondson - see comment

like image 847
BuddyJoe Avatar asked Jul 16 '09 13:07

BuddyJoe


People also ask

What is method to load assembly by name?

Loads an assembly given its AssemblyName. The assembly is loaded into the domain of the caller using the supplied evidence. Loads the assembly with a common object file format (COFF)-based image containing an emitted assembly. The assembly is loaded into the application domain of the caller.

What is the method to load assembly given its file name and its path?

LoadFrom(String) Loads an assembly given its file name or path.


2 Answers

Use an AppDomain

It is safer and more flexible to load the assembly into its own AppDomain first.

So instead of the answer given previously:

var asm = Assembly.LoadFile(@"C:\myDll.dll"); var type = asm.GetType("TestRunner"); var runnable = Activator.CreateInstance(type) as IRunnable; if (runnable == null) throw new Exception("broke"); runnable.Run(); 

I would suggest the following (adapted from this answer to a related question):

var domain = AppDomain.CreateDomain("NewDomainName"); var t = typeof(TypeIWantToLoad); var runnable = domain.CreateInstanceFromAndUnwrap(@"C:\myDll.dll", t.Name) as IRunnable; if (runnable == null) throw new Exception("broke"); runnable.Run(); 

Now you can unload the assembly and have different security settings.

If you want even more flexibility and power for dynamic loading and unloading of assemblies, you should look at the Managed Add-ins Framework (i.e. the System.AddIn namespace). For more information, see this article on Add-ins and Extensibility on MSDN.

like image 184
cdiggins Avatar answered Oct 13 '22 05:10

cdiggins


If you do not have access to the TestRunner type information in the calling assembly (it sounds like you may not), you can call the method like this:

Assembly assembly = Assembly.LoadFile(@"C:\dyn.dll"); Type     type     = assembly.GetType("TestRunner"); var      obj      = Activator.CreateInstance(type);  // Alternately you could get the MethodInfo for the TestRunner.Run method type.InvokeMember("Run",                    BindingFlags.Default | BindingFlags.InvokeMethod,                    null,                   obj,                   null); 

If you have access to the IRunnable interface type, you can cast your instance to that (rather than the TestRunner type, which is implemented in the dynamically created or loaded assembly, right?):

  Assembly assembly  = Assembly.LoadFile(@"C:\dyn.dll");   Type     type      = assembly.GetType("TestRunner");   IRunnable runnable = Activator.CreateInstance(type) as IRunnable;   if (runnable == null) throw new Exception("broke");   runnable.Run(); 
like image 29
Jeff Sternal Avatar answered Oct 13 '22 06:10

Jeff Sternal