参考了微软的realproxy设计模式,使用相同的IMessage结构,重写了整个proxy。
使用了emit技术,性能得到了极大提升。
模仿旧的pojo代码,得到:
{
Dictionary<string, object> dict = new Dictionary<string, object>();
public MyProxy()
: base(typeof(T))
{
}
public T Value
{
get
{
return (T)base.GetTransparentProxy();
}
}
public override IDynamicMethodReturnMessage Invoke(IDynamicMethodCallMessage msg)
{
string methodname = msg.MethodInfo.Name.Trim().ToUpper();
if (methodname.StartsWith("GET_"))
return InvokeGetter(msg);
if (methodname.StartsWith("SET_"))
return InvokeSetter(msg);
return base.CreateReturnMessage(new Exception("only support property."), msg);
}
private IDynamicMethodReturnMessage InvokeGetter(IDynamicMethodCallMessage methodCall)
{
IDummyMethodInfo method = methodCall.MethodInfo;
string invokeid = GetInvokeMessageId(method);
if (dict.ContainsKey(invokeid))
{
return base.CreateReturnMessage(dict[invokeid], methodCall);
}
if (method.ReturnType.PropertyType == DotNetPropertyType.Enum)
{
return base.CreateReturnMessage(0, methodCall);
}
switch (Pixysoft.Tools.ParserHelper.GetDataTypeByTypeName(method.ReturnType.Name))
{
case DotNetDataType.Boolean:
{
return base.CreateReturnMessage(false, methodCall);
}
case DotNetDataType.Byte:
{
return base.CreateReturnMessage(byte.MinValue, methodCall);
}
case DotNetDataType.Char:
{
return base.CreateReturnMessage(char.MinValue, methodCall);
}
case DotNetDataType.DateTime:
{
return base.CreateReturnMessage(DateTime.MinValue, methodCall);
}
case DotNetDataType.Decimal:
{
return base.CreateReturnMessage(decimal.MinValue, methodCall);
}
case DotNetDataType.Double:
{
return base.CreateReturnMessage(double.MinValue, methodCall);
}
case DotNetDataType.Int32:
{
return base.CreateReturnMessage(int.MinValue, methodCall);
}
case DotNetDataType.Int64:
{
return base.CreateReturnMessage(Int32.MinValue, methodCall);
}
case DotNetDataType.Single:
{
return base.CreateReturnMessage(Single.MinValue, methodCall);
}
case DotNetDataType.String:
case DotNetDataType.UNKNOWN:
default:
{
return base.CreateReturnMessage(null, methodCall);
}
}
}
private IDynamicMethodReturnMessage InvokeSetter(IDynamicMethodCallMessage methodCall)
{
if (methodCall.InArgCount == 0)
return base.CreateReturnMessage(null, methodCall);
string invokeid = GetInvokeMessageId(methodCall.MethodInfo);
if (dict.ContainsKey(invokeid))
dict.Remove(invokeid);
dict.Add(invokeid, methodCall.InArgs[0]);
return base.CreateReturnMessage(null, methodCall);
}
private string GetInvokeMessageId(IDummyMethodInfo method)
{
StringBuilder builder = new StringBuilder();
builder.Append(method.Name.Substring(4));
builder.Append(method.DeclaringType.FullName);
//return builder.ToString();
return Pixysoft.Security.MD5.GetMD5(builder.ToString());
}
}
public interface IproxyWithProperty
{
string Name { set;get;}
}
测试代码如下:
public void test002()
{
IproxyWithProperty pojo = Pixysoft.Tools.PojoHelper.GetPojo<IproxyWithProperty>();
IproxyWithProperty proxy = new MyProxy<IproxyWithProperty>().Value;
Pixysoft.Tools.CodeTimer.Initialize();
Pixysoft.Tools.CodeTimer.Time("pojo", 100000, delegate()
{
pojo.Name = "123";
object name = pojo.Name;
});
Pixysoft.Tools.CodeTimer.Time("proxy", 100000, delegate()
{
proxy.Name = "123";
object name = proxy.Name;
});
}
测试结果如下:
------ Test started: Assembly: Pixysoft.Framework.Reflection.dll ------
pojo
Time Elapsed: 7,997ms
CPU time: 7,796,875,000ns
Gen 0: 760
Gen 1: 0
Gen 2: 0
proxy
Time Elapsed: 5,651ms
CPU time: 5,484,375,000ns
Gen 0: 398
Gen 1: 0
Gen 2: 0
1 passed, 0 failed, 0 skipped, took 13.77 seconds (Ad hoc).
性能提高了1.415倍。
如果把初始化proxy的代码放入循环,得到结果:
------ Test started: Assembly: Pixysoft.Framework.Reflection.dll ------
pojo
Time Elapsed: 8,569ms
CPU time: 8,015,625,000ns
Gen 0: 800
Gen 1: 0
Gen 2: 0
proxy
Time Elapsed: 6,263ms
CPU time: 5,843,750,000ns
Gen 0: 475
Gen 1: 0
Gen 2: 0
性能提高了1.368倍。
可以看出,微软的Realproxy本质上并不弱。 内部实现应该使用了类似emit的技术了。。。
因此,一天的努力几乎有点白费了。。。竟然没有提高一个数量级。。。
1 passed, 0 failed, 0 skipped, took 14.92 seconds (Ad hoc).