.net 动态代理的泛型方法支持问题
2016-02-01 11:43
363 查看
最近一直在做.net平台下的高速服务框架。其中有一个问题一直困扰着我:通过动态代理RealProxy创建的服务代理,不支持泛型方法调用。比如:
接口声明:
public interface IMetedataService
{
string GetData<T>(T p);
string GetDataWithHSF<T>(T p);
}
接口实现:
public class EventMetadataService:IMetedataService
{
public string GetData<T>(T p)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
return ser.Serialize(p);
}
public string GetDataWithHSF<T>(T p)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
string data = ser.Serialize(p);
string getdata = HSFService.Proxy<IMetedataService>().GetData<string>(DateTime.Now.ToLongTimeString());
return getdata + " " + data;
}
}
EventMetadataService被部署到HSF的Container中。在HSF的Consumer端,调用代码如下。此代码在执行时会出现异常:不能对containsgenericparameters为true的类型或方法执行后期绑定操作
EventData dd = new EventData();
dd.ID = Guid.NewGuid().ToString();
dd.Code = "Good boy";
dd.Names = data;
List<EventData> res = new List<EventData>();
res.Add(dd);
var result = HSFService.Proxy<IMetedataService>().GetData<List<EventData>>(res);
在HSFService中,通过动态代理远程调用HSF的Container服务。重载了RealProxy,其的核心代码如下:
public override IMessage Invoke(IMessage msg)
{
DateTime start = DateTime.Now;
RemoteInvokeMessage requestMessage = null;
var message = msg as IMethodCallMessage;
if (message == null)
{
return null;
}
try
{
requestMessage = new RemoteInvokeMessage
{
ServiceClassName = typeof(TProxy).FullName,
MethodName = message.MethodName,
Parameters = message.InArgs,
Version = this._serviceVersion,
Properties = new System.Collections.Generic.Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
};
var responseMessage = tcpClient.SendMessageAndWaitForResponse(requestMessage) as RemoteInvokeReturnMessage;
if (responseMessage == null)
{
return null;
}
if (responseMessage.RemoteException != null)
{
return new ReturnMessage(responseMessage.RemoteException, message);
}
else
{
return new ReturnMessage(responseMessage.ReturnValue, null, 0, message.LogicalCallContext, message);
}
}
catch (Exception ex)
{
return new ReturnMessage(ex, message);
}
}
}
为了解决上述异常,修改了RealProxy的Invoke代码,并在RemoteInvokeMessage中加入了记录泛型方法的属性:
public string[] GenericTypes { get; set; }
Invoke方法的代码更新如下:
public override IMessage Invoke(IMessage msg)
{
DateTime start = DateTime.Now;
RemoteInvokeMessage requestMessage = null;
var message = msg as IMethodCallMessage;
if (message == null)
{
return null;
}
try
{
requestMessage = new RemoteInvokeMessage
{
ServiceClassName = typeof(TProxy).FullName,
MethodName = message.MethodName,
Parameters = message.InArgs,
Version = this._serviceVersion,
Properties = new System.Collections.Generic.Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
};
if (message.MethodBase!= null && message.MethodBase.IsGenericMethod)
{
var tps= message.MethodBase.GetGenericArguments();
if (tps != null)
{
List<string> strTypes = new List<string>();
foreach (var item in tps)
{
strTypes.Add(JsonConvert.SerializeObject(item));
}
requestMessage.GenericTypes = strTypes.ToArray();
}
}
var responseMessage = tcpClient.SendMessageAndWaitForResponse(requestMessage) as RemoteInvokeReturnMessage;
if (responseMessage == null)
{
return null;
}
if (responseMessage.RemoteException != null)
{
return new ReturnMessage(responseMessage.RemoteException, message);
}
else
{
return new ReturnMessage(responseMessage.ReturnValue, null, 0, message.LogicalCallContext, message);
}
}
catch (Exception ex)
{
return new ReturnMessage(ex, message);
}
}
}
上面标记代码,主要是提取了泛型方法的类型。只要把类型传递到HSF Container中,就可反射加载相关类型,并在反射调用方法时,通过MakeGenericMethod方法设置泛型类型,从而解决异常“不能对containsgenericparameters为true的类型或方法执行后期绑定操作”。
MethodInfo m = null;
if (methodMap.ContainsKey(methodName) == true)
{
if (methodMap.TryGetValue(methodName, out m) == false)
m = InternalGetMethod(typeName, methodName, m, arg);
}
else
m = InternalGetMethod(typeName, methodName, m, arg);
if (m.IsGenericMethod)
{
List<Type> typs = new List<Type>();
if (message.GenericTypes != null)
{
foreach (string item in message.GenericTypes)
{
typs.Add(GetDataType(item));
}
}
m = m.MakeGenericMethod(typs.ToArray());
}
顺便说一句,HSF Container拿到泛型方法的类型后,需要转换为Type类型对象,这里也有很多的问题和技巧,贴一下我的解决方案把。
private Type GetDataType(string item)
{
string asmName = string.Empty;
string tName = string.Empty;
var citem = item.Replace("\"", "");
Type result = Type.GetType(citem, false, true);
if (result != null)
return result;
if (result == null)
result = Type.ReflectionOnlyGetType(citem, false, true);
if (result != null)
return result;
throw new HSFException(ErrorCode.InvalideParam, "无法找到类型:" + item);
}
一定要确保类型对应的程序集已经被加载。
魏亮 2016-2-1
接口声明:
public interface IMetedataService
{
string GetData<T>(T p);
string GetDataWithHSF<T>(T p);
}
接口实现:
public class EventMetadataService:IMetedataService
{
public string GetData<T>(T p)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
return ser.Serialize(p);
}
public string GetDataWithHSF<T>(T p)
{
JavaScriptSerializer ser = new JavaScriptSerializer();
string data = ser.Serialize(p);
string getdata = HSFService.Proxy<IMetedataService>().GetData<string>(DateTime.Now.ToLongTimeString());
return getdata + " " + data;
}
}
EventMetadataService被部署到HSF的Container中。在HSF的Consumer端,调用代码如下。此代码在执行时会出现异常:不能对containsgenericparameters为true的类型或方法执行后期绑定操作
EventData dd = new EventData();
dd.ID = Guid.NewGuid().ToString();
dd.Code = "Good boy";
dd.Names = data;
List<EventData> res = new List<EventData>();
res.Add(dd);
var result = HSFService.Proxy<IMetedataService>().GetData<List<EventData>>(res);
在HSFService中,通过动态代理远程调用HSF的Container服务。重载了RealProxy,其的核心代码如下:
public override IMessage Invoke(IMessage msg)
{
DateTime start = DateTime.Now;
RemoteInvokeMessage requestMessage = null;
var message = msg as IMethodCallMessage;
if (message == null)
{
return null;
}
try
{
requestMessage = new RemoteInvokeMessage
{
ServiceClassName = typeof(TProxy).FullName,
MethodName = message.MethodName,
Parameters = message.InArgs,
Version = this._serviceVersion,
Properties = new System.Collections.Generic.Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
};
var responseMessage = tcpClient.SendMessageAndWaitForResponse(requestMessage) as RemoteInvokeReturnMessage;
if (responseMessage == null)
{
return null;
}
if (responseMessage.RemoteException != null)
{
return new ReturnMessage(responseMessage.RemoteException, message);
}
else
{
return new ReturnMessage(responseMessage.ReturnValue, null, 0, message.LogicalCallContext, message);
}
}
catch (Exception ex)
{
return new ReturnMessage(ex, message);
}
}
}
为了解决上述异常,修改了RealProxy的Invoke代码,并在RemoteInvokeMessage中加入了记录泛型方法的属性:
public string[] GenericTypes { get; set; }
Invoke方法的代码更新如下:
public override IMessage Invoke(IMessage msg)
{
DateTime start = DateTime.Now;
RemoteInvokeMessage requestMessage = null;
var message = msg as IMethodCallMessage;
if (message == null)
{
return null;
}
try
{
requestMessage = new RemoteInvokeMessage
{
ServiceClassName = typeof(TProxy).FullName,
MethodName = message.MethodName,
Parameters = message.InArgs,
Version = this._serviceVersion,
Properties = new System.Collections.Generic.Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
};
if (message.MethodBase!= null && message.MethodBase.IsGenericMethod)
{
var tps= message.MethodBase.GetGenericArguments();
if (tps != null)
{
List<string> strTypes = new List<string>();
foreach (var item in tps)
{
strTypes.Add(JsonConvert.SerializeObject(item));
}
requestMessage.GenericTypes = strTypes.ToArray();
}
}
var responseMessage = tcpClient.SendMessageAndWaitForResponse(requestMessage) as RemoteInvokeReturnMessage;
if (responseMessage == null)
{
return null;
}
if (responseMessage.RemoteException != null)
{
return new ReturnMessage(responseMessage.RemoteException, message);
}
else
{
return new ReturnMessage(responseMessage.ReturnValue, null, 0, message.LogicalCallContext, message);
}
}
catch (Exception ex)
{
return new ReturnMessage(ex, message);
}
}
}
上面标记代码,主要是提取了泛型方法的类型。只要把类型传递到HSF Container中,就可反射加载相关类型,并在反射调用方法时,通过MakeGenericMethod方法设置泛型类型,从而解决异常“不能对containsgenericparameters为true的类型或方法执行后期绑定操作”。
MethodInfo m = null;
if (methodMap.ContainsKey(methodName) == true)
{
if (methodMap.TryGetValue(methodName, out m) == false)
m = InternalGetMethod(typeName, methodName, m, arg);
}
else
m = InternalGetMethod(typeName, methodName, m, arg);
if (m.IsGenericMethod)
{
List<Type> typs = new List<Type>();
if (message.GenericTypes != null)
{
foreach (string item in message.GenericTypes)
{
typs.Add(GetDataType(item));
}
}
m = m.MakeGenericMethod(typs.ToArray());
}
顺便说一句,HSF Container拿到泛型方法的类型后,需要转换为Type类型对象,这里也有很多的问题和技巧,贴一下我的解决方案把。
private Type GetDataType(string item)
{
string asmName = string.Empty;
string tName = string.Empty;
var citem = item.Replace("\"", "");
Type result = Type.GetType(citem, false, true);
if (result != null)
return result;
if (result == null)
result = Type.ReflectionOnlyGetType(citem, false, true);
if (result != null)
return result;
throw new HSFException(ErrorCode.InvalideParam, "无法找到类型:" + item);
}
一定要确保类型对应的程序集已经被加载。
魏亮 2016-2-1
相关文章推荐
- SWIFT学习笔记 2016/02/01
- JSP学习 —— 开篇:JSP,servlet容器,Tomcat,servlet容器之间的关系
- iis 重启命令
- fseek、ftell和rewind函数详解
- Unity3D命令行Build
- Tmux -- linux终端复用器
- iOS线程
- iOS 核心动画 代码详解
- hdu3018 Ant Trip
- ant 如何实现流程控制,遍历等操作
- 微信登录授权开发
- LintCode : 逆波兰表达式求值
- SELECT INTO FROM mysql Undeclared variable
- Unity3D使用经验总结 优点篇
- 微服务年度总结,看完这个你应该知道如何回答别人的问题了
- Delete Duplicate OpenStack Hypervisors and Services
- dubbo 的monitor监控中心 配置过程_linux
- adb 查看cpu使用率
- Python第一讲从安装到入门
- .net 动态代理的泛型方法支持问题