Greetings! I've been fooling around (a bit) with C# and its assemblies. And so i've found such an interesting feature as dynamic loading assemblies and invoking its class members. A bit of google and here i am, writing some kind of 'assembly explorer'. (i've used some portions of code from here, here and here and none of 'em gave any of expected results).
But i've found a small bug: when i tried to invoke class method from assembly i've loaded, application raised MissingMethod exception. I'm sure DLL i'm loading contains class and method i'm tryin' to invoke (my app ensures me as well as RedGate's .NET Reflector):
The main application code seems to be okay and i start thinking if i was wrong with my DLL... Ah, and i've put both of projects into one solution, but i don't think it may cause any troubles. And yes, DLL project has 'class library' target while the main application one has 'console applcation' target.
So, the question is: what's wrong with 'em?
Here are some source code:
DLL source:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ClassLibrary1
{
public class Class1
{
public void Main()
{
System.Console.WriteLine("Hello, World!");
}
}
}
Main application source:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Assembly asm = Assembly.LoadFrom(@"a\long\long\path\ClassLibrary1.dll");
try
{
foreach (Type t in asm.GetTypes())
{
if (t.IsClass == true && t.FullName.EndsWith(".Class1"))
{
object obj = Activator.CreateInstance(t);
obj开发者_如何转开发ect res = t.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, obj, null); // Exception is risen from here
}
}
}
catch (Exception e)
{
System.Console.WriteLine("Error: {0}", e.Message);
}
System.Console.ReadKey();
}
}
}
UPD: worked for one case - when DLL method takes no arguments:
DLL class (also works if method is not static):
public class Class1
{
public static void Main()
{
System.Console.WriteLine("Hello, World!");
}
}
Method invoke code:
object res = t.InvokeMember("Main", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, null);
You are likely getting the InvokeMember() arguments wrong. Here's a sample that works:
using System;
using System.Reflection;
class Program {
static void Main(string[] args) {
if (args.Length > 0) Console.WriteLine(args[0]);
else {
Assembly asm = Assembly.LoadFrom(Assembly.GetEntryAssembly().Location);
foreach (Type t in asm.GetTypes()) {
if (t.IsClass == true && t.FullName.EndsWith(".Program")) {
//object obj = Activator.CreateInstance(t);
object res = t.InvokeMember("Main",
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod,
null, null,
new object[] { new string[] { "Invoked" } });
}
}
}
}
}
- Note how the Main() method isn't public, thus BindingFlags.NonPublic
- Note how the Main() method is static, thus BindingFlags.Static
- For the same reason, pass null for the target parameter
- For the same reason, CreateInstance isn't necessary
- Note how the Main() method takes a string[] argument, you have to pass it to get Reflection to find the correct method overload.
Follow the same logic for your Main() method:
object res = t.InvokeMember("Main",
BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod,
null, obj,
new object[] { });
Why are you craeting an instance (Activator.CreateInstance(t)
) in order to invoke a static method???? It should be:
t.InvokeMember(
"Main",
BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod,
null,
null,
new object[] { new string[0] }
);
Also this method as defined doesn't return any value so no need to assign it a return variable.
And in order to clear all misunderstandings I've created a full working demo here: http://www.mediafire.com/?n7h9b8ghomfv17d
The last parameter to InvokeMember
is an array of Objects containing the arguments to the method.
You're passing null
there, you should be passing an array of objects containing a single element (an array of strings).
精彩评论