NewLife/X

打算用ApiHook替换方法的方式,实现XmlIgnore作为默认忽略属性的特性,vs调试时成功,直接运行失败。
暂时放弃
Stone authored at 2016-02-15 03:22:46
9a0d6f3
Tree
1 Parent(s) 22d7d19
Summary: 5 changed files with 86 additions and 70 deletions.
Modified +1 -0
Modified +32 -50
Modified +23 -0
Modified +29 -20
Modified +1 -0
Modified +1 -0
diff --git a/NewLife.Core/NewLife.Core.csproj b/NewLife.Core/NewLife.Core.csproj
index d8f75a4..fa06e56 100644
--- a/NewLife.Core/NewLife.Core.csproj
+++ b/NewLife.Core/NewLife.Core.csproj
@@ -125,6 +125,7 @@
     <Compile Include="Model\IObjectContainer.cs" />
     <Compile Include="Model\ObjectContainer.cs" />
     <Compile Include="Model\IServer.cs" />
+    <Compile Include="Reflection\ApiHook.cs" />
     <Compile Include="Reflection\EmitReflect.cs" />
     <Compile Include="Reflection\IL\ILInstruction.cs" />
     <Compile Include="Reflection\IL\MethodBodyReader.cs" />
Modified +32 -50
diff --git a/NewLife.Core/Reflection/ApiHook.cs b/NewLife.Core/Reflection/ApiHook.cs
index 097f007..17a6125 100644
--- a/NewLife.Core/Reflection/ApiHook.cs
+++ b/NewLife.Core/Reflection/ApiHook.cs
@@ -3,6 +3,7 @@ using System.Diagnostics;
 using System.Reflection;
 using System.Reflection.Emit;
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 using NewLife.Log;
 
 namespace NewLife.Reflection
@@ -17,13 +18,11 @@ namespace NewLife.Reflection
     public class ApiHook : DisposeBase
     {
         #region 属性
-        private MethodBase _OriMethod;
         /// <summary>原始方法</summary>
-        public MethodBase OriMethod { get { return _OriMethod; } set { _OriMethod = value; } }
+        public MethodBase OriMethod { get; set; }
 
-        private MethodBase _NewMethod;
         /// <summary>新方法</summary>
-        public MethodBase NewMethod { get { return _NewMethod; } set { _NewMethod = value; } }
+        public MethodBase NewMethod { get; set; }
         #endregion
 
         #region 构造
@@ -40,9 +39,6 @@ namespace NewLife.Reflection
 
         #region 方法
         private Boolean ishooked;
-        //private IntPtr[] addresses;
-        //private uint ori;
-        //private ulong ori64;
 
         /// <summary>挂钩</summary>
         public void Hook()
@@ -110,61 +106,26 @@ namespace NewLife.Reflection
         /// <returns></returns>
         unsafe public static IntPtr GetMethodAddress(MethodBase method)
         {
-            var isAboveNet2Sp2 = Environment.Version.Major >= 2 && Environment.Version.MinorRevision >= 3053;
-
             // 处理动态方法
             if (method is DynamicMethod)
             {
-                //byte* ptr = (byte*)GetDynamicMethodRuntimeHandle(method).ToPointer();
-
-                //FieldInfo fieldInfo = typeof(DynamicMethod).GetField("m_method", BindingFlags.NonPublic | BindingFlags.Instance);
-                //byte* ptr = (byte*)((RuntimeMethodHandle)FieldInfoX.Create(fieldInfo).GetValue(method)).Value.ToPointer();
                 var ptr = (byte*)((RuntimeMethodHandle)method.GetValue("m_method")).Value.ToPointer();
 
-                if (isAboveNet2Sp2)
-                {
-                    // 确保方法已经被编译
-                    RuntimeHelpers.PrepareMethod(method.MethodHandle);
+                // 确保方法已经被编译
+                RuntimeHelpers.PrepareMethod(method.MethodHandle);
 
-                    if (IntPtr.Size == 8)
-                        return new IntPtr((ulong*)*(ptr + 5) + 12);
-                    else
-                        return new IntPtr((uint*)*(ptr + 5) + 12);
-                }
+                if (IntPtr.Size == 8)
+                    return new IntPtr((ulong*)*(ptr + 5) + 12);
                 else
-                {
-                    if (IntPtr.Size == 8)
-                        return new IntPtr((ulong*)ptr + 6);
-                    else
-                        return new IntPtr((uint*)ptr + 6);
-                }
+                    return new IntPtr((uint*)*(ptr + 5) + 12);
             }
 
+            ShowMethod(new IntPtr((int*)method.MethodHandle.Value.ToPointer() + 2));
             // 确保方法已经被编译
             RuntimeHelpers.PrepareMethod(method.MethodHandle);
+            ShowMethod(new IntPtr((int*)method.MethodHandle.Value.ToPointer() + 2));
 
-            if (isAboveNet2Sp2) return new IntPtr((int*)method.MethodHandle.Value.ToPointer() + 2);
-
-            // 要跳过的
-            var skip = 10;
-
-            // 读取方法索引
-            var location = (UInt64*)(method.MethodHandle.Value.ToPointer());
-            var index = (int)(((*location) >> 32) & 0xFF);
-
-            // 区分处理x86和x64
-            if (IntPtr.Size == 8)
-            {
-                // 获取方法表
-                var methodTable = (ulong*)method.DeclaringType.TypeHandle.Value.ToPointer();
-                return new IntPtr(methodTable + index + skip);
-            }
-            else
-            {
-                // 获取方法表
-                var methodTable = (uint*)method.DeclaringType.TypeHandle.Value.ToPointer();
-                return new IntPtr(methodTable + index + skip);
-            }
+            return new IntPtr((int*)method.MethodHandle.Value.ToPointer() + 2);
         }
 
         static readonly Type mbroType = typeof(MarshalByRefObject);
@@ -200,6 +161,10 @@ namespace NewLife.Reflection
 
         unsafe private static void ReplaceMethod(IntPtr src, IntPtr dest)
         {
+            XTrace.WriteLine("0x{0}=>0x{1}", src.ToString("x"), dest.ToString("x"));
+            //ShowMethod(src);
+            //ShowMethod(dest);
+
             // 区分处理x86和x64
             if (IntPtr.Size == 8)
             {
@@ -212,6 +177,23 @@ namespace NewLife.Reflection
                 *d = *((uint*)dest.ToPointer());
             }
         }
+
+        private static void ShowMethod(IntPtr mt)
+        {
+            XTrace.WriteLine("ShowMethod: {0}", mt.ToString("x"));
+            var buf = new Byte[8];
+            Marshal.Copy(mt, buf, 0, buf.Length);
+            //XTrace.WriteLine(buf.ToHex("-"));
+
+            var ip = new IntPtr((Int64)buf.ToUInt64());
+            XTrace.WriteLine("{0}", ip.ToString("x"));
+
+            if (ip.ToInt64() <= 0x1000000 || ip.ToInt64() > 0x800000000000L) return;
+
+            buf = new Byte[32];
+            Marshal.Copy(ip, buf, 0, buf.Length);
+            XTrace.WriteLine(buf.ToHex("-"));
+        }
         #endregion
     }
 }
\ No newline at end of file
Modified +23 -0
diff --git a/NewLife.Core/Serialization/Json/IJson.cs b/NewLife.Core/Serialization/Json/IJson.cs
index 5d9cbcb..a7fca21 100644
--- a/NewLife.Core/Serialization/Json/IJson.cs
+++ b/NewLife.Core/Serialization/Json/IJson.cs
@@ -5,6 +5,8 @@ using NewLife.Web;
 using NewLife.Log;
 using System.Collections.Generic;
 using System.Text;
+using System.Reflection;
+using System.Xml.Serialization;
 
 namespace NewLife.Serialization
 {
@@ -68,6 +70,27 @@ namespace NewLife.Serialization
 
     class JsonDefault : IJson
     {
+        //static JsonDefault()
+        //{
+        //    // 用XmlIgnore特性作为忽略属性的方法
+        //    var src = typeof(JavaScriptSerializer).GetMethodEx("CheckScriptIgnoreAttribute");
+        //    var dst = typeof(JsonDefault).GetMethodEx("CheckScriptIgnoreAttribute");
+        //    if (src != null && dst != null)
+        //    {
+        //        //new JavaScriptSerializer().Invoke(src, src);
+        //        //new JsonDefault().CheckScriptIgnoreAttribute(dst);
+        //        ApiHook.ReplaceMethod(src, dst);
+        //    }
+        //}
+
+        private bool CheckScriptIgnoreAttribute(MemberInfo memberInfo)
+        {
+            if (memberInfo.IsDefined(typeof(ScriptIgnoreAttribute), true)) return true;
+            if (memberInfo.IsDefined(typeof(XmlIgnoreAttribute), true)) return true;
+
+            return false;
+        }
+
         #region IJson 成员
         public String Write(Object value, Boolean indented)
         {
Modified +29 -20
diff --git a/Test/Program.cs b/Test/Program.cs
index 30e5972..fdacf2e 100644
--- a/Test/Program.cs
+++ b/Test/Program.cs
@@ -4,6 +4,7 @@ using System.Diagnostics;
 using System.IO;
 using System.Reflection;
 using System.Threading;
+using System.Xml.Serialization;
 using NewLife.Common;
 using NewLife.Compression;
 using NewLife.Log;
@@ -102,27 +103,35 @@ namespace Test
 
         static void Test4()
         {
-            var obj = new TT();
-            obj.ID = 123;
-            obj.Name = "Test";
+            var user = UserX.FindByName("admin");
+            Console.WriteLine(user.ToJson(true));
 
-            var bn = new Binary();
-            bn.EncodeInt = true;
-            bn.Write(obj);
-            var buf = bn.GetBytes();
-            Console.WriteLine(buf.ToHex("-"));
-
-            bn.Stream = new MemoryStream(buf);
-            var obj2 = bn.Read<TT>();
-            Console.WriteLine(obj2.ID);
-            Console.WriteLine(obj2.Name);
-
-            var js = obj.ToJson();
-            Console.WriteLine(js);
-            Console.WriteLine(obj.ToJson(true));
-            var obj3 = js.ToJsonEntity<TT>();
-            Console.WriteLine(obj3.ID);
-            Console.WriteLine(obj3.Name);
+            //var type = typeof(UserX);
+            //var pi = type.GetPropertyEx("Extends");
+            //var ng = pi.GetCustomAttribute<NonSerializedAttribute>();
+            //Console.WriteLine(ng);
+
+            //var obj = new TT();
+            //obj.ID = 123;
+            //obj.Name = "Test";
+
+            //var bn = new Binary();
+            //bn.EncodeInt = true;
+            //bn.Write(obj);
+            //var buf = bn.GetBytes();
+            //Console.WriteLine(buf.ToHex("-"));
+
+            //bn.Stream = new MemoryStream(buf);
+            //var obj2 = bn.Read<TT>();
+            //Console.WriteLine(obj2.ID);
+            //Console.WriteLine(obj2.Name);
+
+            //var js = obj.ToJson();
+            //Console.WriteLine(js);
+            //Console.WriteLine(obj.ToJson(true));
+            //var obj3 = js.ToJsonEntity<TT>();
+            //Console.WriteLine(obj3.ID);
+            //Console.WriteLine(obj3.Name);
         }
 
         class TT
Modified +1 -0
diff --git a/Test/Test.csproj b/Test/Test.csproj
index b6580ee..34e1f50 100644
--- a/Test/Test.csproj
+++ b/Test/Test.csproj
@@ -30,6 +30,7 @@
     <DefineConstants>TRACE;NET4</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <PlatformTarget>AnyCPU</PlatformTarget>
+    <UseVSHostingProcess>true</UseVSHostingProcess>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="Microsoft.VisualBasic" />