首页 » Web前端 » phpget_instance技巧_dotNet开拓之反射技能详解高级篇

phpget_instance技巧_dotNet开拓之反射技能详解高级篇

访客 2024-12-10 0

扫一扫用手机浏览

文章目录 [+]

在前面的文章中先容了dotNet开拓之反射技能的根本篇和动态库的加载,我们将深入磋商反射的其他用法,除了常规的利用办法,反射还可以实现一些高等功能,如动态创建类型、调用私有方法,访问泛型类型,自定义序列化和反序列化,动态代理等。
下面先容一些 C# 反射的高等用法:

动态创建类型

Emit 是 C# 中的一个动态代码天生工具,可以通过 Emit 在运行时动态天生 MSIL 代码,从而实现高效的动态代码天生和实行。
在反命中,我们可以利用 Emit 来动态创建类型、方法、属性等元素,并在运行时进行操作。
反射可以利用 System.Reflection.Emit 命名空间供应的类型动态创建类。

phpget_instance技巧_dotNet开拓之反射技能详解高级篇

以下示例代码演示了如何利用反射动态创建一个大略的类型:

phpget_instance技巧_dotNet开拓之反射技能详解高级篇
(图片来自网络侵删)

using System;using System.Reflection;using System.Reflection.Emit;class Program{ static void Main(string[] args) { // 创建一个动态程序集 AssemblyName assemblyName = new AssemblyName("DynamicAssembly"); AssemblyBuilder dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("DynamicModule", "DynamicAssembly.dll"); // 创建一个动态类型 TypeBuilder dynamicType = dynamicModule.DefineType("DynamicType", TypeAttributes.Public); // 添加一个字段 FieldBuilder dynamicField = dynamicType.DefineField("dynamicField", typeof(int), FieldAttributes.Private); // 添加一个方法 MethodBuilder dynamicMethod = dynamicType.DefineMethod("DynamicMethod", MethodAttributes.Public, typeof(void), null); ILGenerator ilGenerator = dynamicMethod.GetILGenerator(); ilGenerator.Emit(OpCodes.Ldc_I4, 42); ilGenerator.Emit(OpCodes.Stfld, dynamicField); ilGenerator.Emit(OpCodes.Ret); // 创建类型 Type type = dynamicType.CreateType(); // 调用方法 object instance = Activator.CreateInstance(type); MethodInfo methodInfo = type.GetMethod("DynamicMethod"); methodInfo.Invoke(instance, null); // 保存程序集 dynamicAssembly.Save("DynamicAssembly.dll"); }}

在上述示例代码中,我们利用反射动态创建了一个名为 DynamicType 的类型,并向个中添加了一个私有整型字段和一个名为 DynamicMethod 的公共方法。
在该方法内部,我们将数字 42 存储到该类型的私有字段中。
末了,我们调用 Invoke 方法来实行该方法并输出结果。

调用私有方法

反射可以利用 BindingFlags.NonPublic 标志访问工具的私有成员。
以下示例代码演示了如何利用反射调用私有方法:

using System;using System.Reflection;class Program{ static void Main(string[] args) { Example obj = new Example(); MethodInfo methodInfo = typeof(Example).GetMethod("PrivateMethod", BindingFlags.NonPublic | BindingFlags.Instance); methodInfo.Invoke(obj, null); }}class Example{ private void PrivateMethod() { Console.WriteLine("This is a private method."); }}

在上述示例代码中,我们定义了一个名为 Example 的类,并向个中添加了一个私有方法 PrivateMethod。
然后,我们利用反射获取该方法并调用它。
由于该方法是私有方法,因此须要利用 BindingFlags.NonPublic 标志访问它。

访问泛型类型

反射可以利用 MakeGenericType 方法创建泛型类型的实例。
以下示例代码演示了如何利用反射访问泛型类型:

using System;using System.Reflection;class Program{ static void Main(string[] args) { Type genericType = typeof(MyGenericClass<>).MakeGenericType(typeof(int)); object instance = Activator.CreateInstance(genericType); MethodInfo methodInfo = genericType.GetMethod("MyMethod"); methodInfo.Invoke(instance, null); }}class MyGenericClass<T>{ public void MyMethod() { Console.WriteLine($"Type: {typeof(T)}"); }}

在上述示例代码中,我们定义了一个泛型类 MyGenericClass<T>,个中包含一个名为 MyMethod 的公共方法。
然后,我们利用 typeof(MyGenericClass<>) 获取泛型类型,并利用 MakeGenericType 方法指定类型参数为整型 int。
末了,我们创建该泛型类型的实例,并调用 MyMethod 方法,输出结果。

自定义序列化和反序列化

在 C# 中,序列化和反序列化是将工具转换为二进制格式或其他格式以便于存储和传输的主要技能。
在反命中,我们可以利用自定义序列化和反序列化来掌握工具的序列化和反序列化过程,以实现更高等的功能。

例如,下面的代码演示了如何利用反射和自定义序列化将一个工具序列化为 JSON 格式:

using System;using System.Collections.Generic;using System.IO;using System.Reflection;using System.Reflection.Emit;using System.Runtime.Serialization;using System.Text;using Newtonsoft.Json;class Program{ static void Main() { Person person = new Person { Name = "Alice", Age = 25 }; string json = SerializeToJson(person); Console.WriteLine(json); Person deserialized = DeserializeFromJson<Person>(json); Console.WriteLine(deserialized.Name); Console.WriteLine(deserialized.Age); } static string SerializeToJson(object obj) { Type type = obj.GetType(); PropertyInfo[] properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); Dictionary<string, object> dict = new Dictionary<string, object>(); foreach (PropertyInfo property in properties) { dict[property.Name] = property.GetValue(obj); } return JsonConvert.SerializeObject(dict); } static T DeserializeFromJson<T>(string json) { Type type = typeof(T); Dictionary<string, object> dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json); object instance = Activator.CreateInstance(type); foreach (KeyValuePair<string, object> kvp in dict) { PropertyInfo property = type.GetProperty(kvp.Key, BindingFlags.Public | BindingFlags.Instance); if (property != null && property.CanWrite) { property.SetValue(instance, Convert.ChangeType(kvp.Value, property.PropertyType)); } } return (T)instance; }}class Person{ public string Name { get; set; } public int Age { get; set; }}

上述代码利用反射和 JsonConvert 类将一个 Person 工具序列化为 JSON 格式,并将其反序列化为一个新的工具。
在实际运用中,你可以利用类似的技能实现自定义的序列化和反序列化逻辑,并将工具转换为任何你想要的格式。

动态代理

动态代理是一种在运行时创建代理工具的技能,可以用于实现各种高等功能,例如 AOP(面向切面编程)和远程调用。
在反命中,我们可以利用动态代理来动态天生代理工具并在运行时进行操作。

Castle.Core 库利用了反射技能来实现动态代理。
动态代理是通过在运行时创建代理工具来实现的,而反射是一种在运行时获取和操作类型、工具、方法等元素的技能。
在动态代理的实现中,Castle.Core 利用了反射来天生代理类,并通过拦截器(Interceptor)来截获方法调用,并在调用前后实行额外的逻辑。

详细来说,Castle.Core 利用反射来天生代理类的 IL 代码,然后通过 Emit 将其编译为可实行代码。
这些动态天生的代码会在运行时被加载到内存中,并根据须要创建代理工具。

在代理工具被调用时,Castle.Core 利用反射来获取被代理工具的方法信息,并利用 Emit 动态天生 IL 代码,将方法调用委托给拦截器。
拦截器可以在调用前后实行自定义的逻辑,例如输出日志、实现事务管理等。
通过这种办法,Castle.Core 实现了动态代理的功能。

例如,下面的代码演示了如何利用 Castle.Core 库来创建一个动态代理工具,该工具会在调用方法前后输出日志:

using System;using System.Reflection;using Castle.DynamicProxy;class Program{ static void Main() { ICalculator calculator = CreateProxy<ICalculator>(new Calculator()); int result = calculator.Add(1, 2); Console.WriteLine(result); } static TInterface CreateProxy<TInterface>(object target) where TInterface : class { ProxyGenerator generator = new ProxyGenerator(); return generator.CreateInterfaceProxyWithTarget<TInterface>(target, new LoggingInterceptor()); }}interface ICalculator{ int Add(int x, int y);}class Calculator : ICalculator{ public int Add(int x, int y) { return x + y; }}class LoggingInterceptor : IInterceptor{ public void Intercept(IInvocation invocation) { Console.WriteLine($"Before calling {invocation.Method.Name}"); invocation.Proceed(); Console.WriteLine($"After calling {invocation.Method.Name}"); }}

上述代码利用 Castle.Core 库中的 ProxyGenerator 类动态天生一个实现 ICalculator 接口的代理工具,并在调用方法前后输出日志。
在实际运用中,你可以利用类似的技能来实现各种高等功能,例如性能剖析、事务管理等。

总结来说,C# 反射供应了许多强大的功能,可以帮助我们实现各种高等功能和扩展性。
在利用反射时,须要把稳安全性和性能问题,并遵照良好的编程实践。

参考文档:C# 反射(Reflection)详解-Assembly_system.reflection-CSDN博客C#高等--反射详解_c# 反射-CSDN博客

#文章首发寻衅赛#

#跨年幸运签#

#寻衅30天在头条写日记#

#自律学习操持#

标签:

相关文章