閱讀994 返回首頁    go 微軟 go Office


C#動態方法調用

此篇將介紹C#如何在運行時動態調用方法。當某些類型是運行時動態確定時,編譯時的靜態編碼是無法解決這些動態對象或類的方法調用的。此篇則給你一把利劍,讓動態對象的方法調用成為可能。

1.動態調用dll裏的方法

/// <summary>
/// 該類將被獨立編入Class1.dll匯編
/// </summary>
class Class1
{
    public static string method1()
    {
        return "I am Static method (method1) in class1";
    }
    public string method2()
    {
        return "I am a Instance Method (method2) in Class1";
    }
    public string method3(string s)
    {
        return "Hello " + s;
    }
}

/// <summary>
/// 該類獨立放入Test.exe匯編
/// </summary>
class DynamicInvoke
{
    public static void Main(string[] args)
    {
        // 動態加載匯編
        string path = "Class1.dll";
        Assembly assembly = Assembly.Load(path);

        // 根據類型名得到Type
        Type type = assembly.GetType("Class1");

        // 1.根據方法名動態調用靜態方法
        string str = (string)type.InvokeMember("method1", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, new object[] { });
        Console.WriteLine(str);

        // 2.根據方法名動態調用動態對象的成員方法
        object o = Activator.CreateInstance(type);
        str = (string)type.InvokeMember("method2", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, new object[] { });
        Console.WriteLine(str);

        // 3.根據方法名動態調用動態對象的有參成員方法
        object[] par = new object[] { "kunal" };
        str = (string)type.InvokeMember("method3", BindingFlags.Default | BindingFlags.InvokeMethod, null, o, par);
        Console.WriteLine(str);

        // 帶out修飾的InvokeMember
        // System.Int32 中 public static bool TryParse(string s, out int result) 方法的調用
        var arguments = new object[] { str, null }; // 注意這裏隻能將參數寫在外麵,out參數為null也沒有關係
        typeof(int).InvokeMember("TryParse", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static,
             null, null, arguments);
        Console.WriteLine(arguments[1]);
    }
}

2.動態加載類文件並調用方法:

using System;
using System.CodeDom.Compiler;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using Microsoft.CSharp;

namespace _32.DynamicReflection
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            #region 內置標簽方法 (動態加載)

            const string className = "DynamicReflection.Test"; //類名稱一定要全稱
            string fileName = Thread.GetDomain().BaseDirectory + "Test.cs";

            if (File.Exists(fileName))
            {
                var sourceFile = new FileInfo(fileName);
                CodeDomProvider provider = new CSharpCodeProvider();
                var cp = new CompilerParameters();
                cp.ReferencedAssemblies.Add("System.dll"); //添加命名空間引用  

                cp.GenerateExecutable = false; // 生成類庫 
                cp.GenerateInMemory = true; // 保存到內存 
                cp.TreatWarningsAsErrors = false; // 不將編譯警告作為錯誤

                // 編譯
                CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile.FullName);
                if (cr.Errors.Count < 1)
                {
                    Assembly asm = cr.CompiledAssembly; // 加載 

                    //1.調用靜態方法
                    Type type = asm.GetType(className);
                    var str =(string)type.InvokeMember("SayHello1", BindingFlags.Default | BindingFlags.InvokeMethod, null, null, new object[] {});
                    Console.WriteLine(str);

                    //2.調用實例方法
                    object instance = asm.CreateInstance(className);
                    str =(string)type.InvokeMember("SayHello2", BindingFlags.Default | BindingFlags.InvokeMethod, null, instance,new object[] {});
                    Console.WriteLine(str);

                    //3.調用帶參數的方法
                    var par = new object[] {"zhangqs008"};
                    str =(string)type.InvokeMember("SayHello3", BindingFlags.Default | BindingFlags.InvokeMethod, null, instance,par);
                    Console.WriteLine(str);

                    Console.Read();
                }
                else
                {
                    string msg = null;
                    for (int index = 0; index < cr.Errors.Count; index++)
                    {
                        CompilerError error = cr.Errors[index];
                        msg += "【錯誤" + (index + 1) + "】" + Environment.NewLine;
                        msg += "[文件] " + error.FileName + Environment.NewLine;
                        msg += "[位置] 行" + error.Line + ",列" + error.Column + Environment.NewLine;
                        msg += "[信息] " + error.ErrorText + Environment.NewLine;
                        msg += Environment.NewLine;
                    }
                    MessageBox.Show(msg, "內置方法類編譯錯誤");
                }
            }

            #endregion
        }
    }
}
類文件:

namespace DynamicReflection
{
    public class Test
    {
        public static string SayHello1()
        {
            return "hello static method";
        }

        public string SayHello2()
        {
            return "hello instance method";
        }

        public string SayHello3(string args)
        {
            return "hello args " + args;
        }
    }
}



最後更新:2017-04-03 16:48:43

  上一篇:go CUDA從入門到精通(一):環境搭建
  下一篇:go CUDA從入門到精通(八):線程通信