Get Namespace, classname from a dll in C# 2.0

2019-05-06 20:01发布

问题:

I will get dll's dynamically. I need to load the dll and get the namespace, classname to invoke a method (the method name is static it will be always "OnStart()"). Basically I need to run a method by loading the dll. Can somebody help!!!.

回答1:

To load the assembly, you would do this:

Assembly assembly = Assembly.LoadFile(@"test.dll");

This assumes you have the assemblies on disk as files. If you don't, like if you get them from a database as a byte array, there are other methods on the Assembly that will help you give you an Assembly object after loading it.

To iterate through all the classes in the assembly, you would do this:

Assembly assembly = Assembly.LoadFile(@"test.dll");
foreach (Type type in assembly.GetTypes())
{
    if (type.IsClass)
    {
        ...
    }
}

To find the OnStart static method, you would do this:

Assembly assembly = Assembly.LoadFile(@"test.dll");
foreach (Type type in assembly.GetTypes())
{
    if (type.IsClass)
    {
        MethodInfo method = type.GetMethod("OnStart",
            BindingFlags.Static | BindingFlags.Public);
        if (method != null)
        {
            ...
        }
    }
}

To call the method, you would do this:

Assembly assembly = Assembly.LoadFile(@"test.dll");
foreach (Type type in assembly.GetTypes())
{
    if (type.IsClass)
    {
        MethodInfo method = type.GetMethod("OnStart",
            BindingFlags.Static | BindingFlags.Public);
        if (method != null)
        {
            method.Invoke(null, new Object[0]); // assumes no parameters
            break; // no need to look for more methods, unless you got multiple?
        }
    }
}

If you need to pass arguments to the method, you would put them in an object array:

Object[] arguments = new Object[] { arg1, arg2, arg3 ... };
method.Invoke(null, arguments);

The above code can be collapsed to the following by using Linq to find the method for us:

Assembly assembly = Assembly.LoadFile(@"test.dll");
var method = (from type in assembly.GetTypes()
              where type.IsClass
              let onStartMethod = type.GetMethod("OnStart",
                  BindingFlags.Static | BindingFlags.Public)
              where onStartMethod != null
              select onStartMethod).FirstOrDefault();
if (method != null)
{
    method.Invoke(null, new Object[0]); // assumes no parameters
}


回答2:

Check here: http://dotnetguts.blogspot.com/2008/12/reflection-in-c-list-of-class-name.html

And here for invoking a method: http://www.csharphelp.com/archives/archive200.html

If you search some more the terms in those links you'll find much more info.



回答3:

At runtime namespaces just become part of the type name.

So you need to:

  1. Load the assembly
  2. Get the Type instance for the type you want.
  3. Get the MethodInfo for the method you want to call.
  4. Call the method.

Of these 2–4 are easy. 1 might be easy or might not, depending where the assembly is. Assuming the assembly can be found via the normal assembly load ("probing"). This will call a public static method of a type that takes no arguments but does have a return value.

var asm = Assembly.Load(assemblyName);
var t = asm.GetType(typeName);
// Pass array of parameter types to resolve between overloads (here no arguments).
var m = t.GetMathod(methodName, BindingFlags.Static, null, new Type[] {}, null);
// Pass no "this" or arguments.
var res = (resultType) m.Invoke(null, null);

A number of the details here will depend on the details of the assembly, type and method you want to call.



回答4:

       object result = null;

        using (StreamReader reader = new StreamReader(ASSEMBLYPATH, Encoding.GetEncoding(1252), false))
        {
            byte[] b = new byte[reader.BaseStream.Length];
            reader.BaseStream.Read(b, 0, Convert.ToInt32(reader.BaseStream.Length));
            reader.Close();

            Assembly asm = AppDomain.CurrentDomain.Load(b);
            Type typeClass = asm.GetType(CLASSFULLNAME); // including namespace
            MethodInfo mi = typeClass.GetMethod("OnStart");
            ConstructorInfo ci = typeClass.GetConstructor(Type.EmptyTypes);
            object responder = ci.Invoke(null);

            // set parameters
            object[] parameters = new object[1];
            parameters[0] = null;  // no params


            result = mi.Invoke(responder, parameters);
        }

The advantage using this code is that the assembly is unloaded after use, so you can safely delete the dll after invoking the method.