MessageBox(IntPtr.Zero, "你好extern!", "信息", 0); [DllImport("user32.dll")] static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);运行结果:
using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // 堆代码 duidaima.com var test = new TestClass(); //调用私有方法 Console.WriteLine(GetTime(test)); //读取私有字面 Console.WriteLine(GetNo(test)); //赋值给私有字段 GetNo(test) = 20; Console.WriteLine(GetNo(test)); [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTime")] static extern DateTime GetTime(TestClass test); [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_no")] static extern ref int GetNo(TestClass test); public class TestClass { int _no = 10; DateTime GetTime() { return DateTime.Now; } }现在,UnsafeAccessorKind支持的类型如下:
namespace System.Runtime.CompilerServices { public enum UnsafeAccessorKind { Constructor = 0, Method = 1, StaticMethod = 2, Field = 3, StaticField = 4 } }单看这个功能,有点像反射,但要比反射简单,只需要标志签名即可。
using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using static System.Net.Mime.MediaTypeNames; BenchmarkRunner.Run<Test>(); public class Test { [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GetTime")] public static extern DateTime GetTime(TestClass test); [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_no")] public static extern ref int GetNo(TestClass test); [Benchmark] public void UnsafeTest() { var test = new TestClass(); var t = GetTime(test); } [Benchmark] public void RefTest() { var test = new TestClass(); var type = test.GetType(); var method=type.GetMethod("GetTime", BindingFlags.NonPublic | BindingFlags.Instance); var t = method?.Invoke(test, new object[0]); } } public class TestClass { int _no = 10; DateTime GetTime() { return DateTime.Now; } }
下面是用BechamrkDotNet比较反射和UnsafeAccessor方式的性能,还是要好上很多的。