打算用ApiHook替换方法的方式,实现XmlIgnore作为默认忽略属性的特性,vs调试时成功,直接运行失败。 暂时放弃Stone authored at 2016-02-15 03:22:46
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" />
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
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)
{
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
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" />