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;
        }
    }
}



目录
相关文章
|
5月前
|
C# Python
C#如何用最简单方法调用Python?
本文介绍了如何在C#中通过命令行调用Python脚本,以解决Python.NET的版本兼容性和配置难题。方法是利用`System.Diagnostics.Process`类启动Python解释器并传递脚本路径。首先确保安装Python 3.0+,创建.NET控制台程序和Python测试脚本。然后,C#代码通过指定Python路径和脚本位置启动进程,重定向输出并读取结果。这种方法简单、依赖少,适合初学者,但可能牺牲性能,不适合频繁交互和处理大量数据。
|
C#
C# 子窗体中调用父窗体中的方法(或多窗体之间方法调用)
本文转载:http://www.csframework.com/archive/2/arc-2-20110805-1771.htm 文章侧重点主要是讨论“窗体”与“窗体”之间方法的调用,以及“MDI父窗体”与“Chilid子窗体”之间如何相互的调用方法。
1248 0
C#中关于使用POST方法调用Web Service发生的问题
今天使用HttpWebRequest类访问Web Service一直报“500服务器端错误”,一看Web Service可以正常访问没有问题,构造HttpWebRequest的参数也齐全,弄了半天终于发现,原来是Method的"post"小写了,改成大写"POST"就没问题了,不过也总结出一条经验,以后访问服务器发现"500服务器端错误",如果服务器端没有问题,就要仔细检查客户端的请求格式有没有问题。
685 0
|
5月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
169 3
|
5月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
181 3
|
9天前
|
API C#
C# 一分钟浅谈:文件系统编程
在软件开发中,文件系统操作至关重要。本文将带你快速掌握C#中文件系统编程的基础知识,涵盖基本概念、常见问题及解决方法。文章详细介绍了`System.IO`命名空间下的关键类库,并通过示例代码展示了路径处理、异常处理、并发访问等技巧,还提供了异步API和流压缩等高级技巧,帮助你写出更健壮的代码。
24 2
|
14天前
|
SQL 开发框架 安全
并发集合与任务并行库:C#中的高效编程实践
在现代软件开发中,多核处理器普及使多线程编程成为提升性能的关键。然而,传统同步模型在高并发下易引发死锁等问题。为此,.NET Framework引入了任务并行库(TPL)和并发集合,简化并发编程并增强代码可维护性。并发集合允许多线程安全访问,如`ConcurrentQueue&lt;T&gt;`和`ConcurrentDictionary&lt;TKey, TValue&gt;`,有效避免数据不一致。TPL则通过`Task`类实现异步操作,提高开发效率。正确使用这些工具可显著提升程序性能,但也需注意任务取消和异常处理等常见问题。
26 1
|
23天前
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
43 11
下一篇
无影云桌面