参考了微软的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).