C# 将方法调用序列化为JSON,然后反序列化并调用该方法
我需要找到一种序列化方法调用及其关联参数的方法。这是因为我们将有效负载传递到队列(如MSMQ),然后稍后一个进程将获取消息并需要对有效负载进行反序列化并调用所需的方法 队列的两侧使用相同的C#库,但一个在Web上下文中,另一个在批处理/控制台应用程序中 我已经在下面演示了我想做什么,但是,我意识到这可能是不可能的。我知道我总是可以封装目标方法调用的元数据,并且有一些巨大的switch语句将参数/负载映射到方法,但是,如果我可以调用我想要的任何方法(不管它是否是静态的),那将是非常酷和简洁的C# 将方法调用序列化为JSON,然后反序列化并调用该方法,c#,serialization,json.net,system.reflection,C#,Serialization,Json.net,System.reflection,我需要找到一种序列化方法调用及其关联参数的方法。这是因为我们将有效负载传递到队列(如MSMQ),然后稍后一个进程将获取消息并需要对有效负载进行反序列化并调用所需的方法 队列的两侧使用相同的C#库,但一个在Web上下文中,另一个在批处理/控制台应用程序中 我已经在下面演示了我想做什么,但是,我意识到这可能是不可能的。我知道我总是可以封装目标方法调用的元数据,并且有一些巨大的switch语句将参数/负载映射到方法,但是,如果我可以调用我想要的任何方法(不管它是否是静态的),那将是非常酷和简洁的 命名
命名空间序列化方法调用
{
公共类DTO
{
公共字符串MyData{get;set;}
公共整数{get;set;}
}
公共级DTO2
{
公共字符串MyData2{get;set;}
公共整数2{get;set;}
}
班级计划
{
私有静态队列_Queue=new Queue();
静态void Main(字符串[]参数)
{
DTO有效负载=新DTO
{
整数=45678,
MyData=“测试”
};
DTO2有效载荷2=新DTO2
{
整数2=534653,
MyData2=“test2”
};
剂量测量(有效载荷);
剂量测量(有效载荷2);
_排队(序列化(DoSomething,payload));
而(_queue.Count>0)
{
var message=_queue.Dequeue();
反序列化和调用方法(消息);
}
}
私有静态void反序列化和调用方法(字符串消息)
{
//以某种方式反序列化方法调用,然后使用序列化的负载调用该方法!
}
公共静态无效剂量测定(DTO2有效载荷2)
{
WriteLine(“Done2!{0},{1}”,payload2.AnInteger2,payload2.MyData2);
}
公共静态空隙剂量测量(DTO-DTO)
{
WriteLine(“Done!{0},{1}”,dto.AnInteger,dto.MyData);
}
公共静态字符串序列化(方法、对象参数)
{
//以某种方式序列化方法调用!?
}
}
}
我很想听听你的想法
非常感谢
KRI使用演示的
从/到…
方法在DTO和反射对象之间转换:
class TypeDTO {
public string AssemblyName;
public string ClassName;
public static TypeDTO FromType(Type type) {
return new TypeDTO() {
AssemblyName = type.Assembly.FullName,
ClassName = type.FullName
};
}
public Type ToType() {
return ToType(AppDomain.CurrentDomain);
}
public Type ToType(AppDomain domain) {
Assembly assembly = domain.GetAssemblies().Where(t => t.FullName == AssemblyName).Single();
return assembly.GetType(ClassName);
}
}
class MethodSignatureDTO {
public TypeDTO DeclaringType;
public string MethodName;
public TypeDTO[] ParameterTypes;
public static MethodSignatureDTO FromMethod(MethodInfo method) {
return new MethodSignatureDTO() {
DeclaringType = TypeDTO.FromType(method.DeclaringType),
MethodName = method.Name,
ParameterTypes = method.GetParameters().Select(t => TypeDTO.FromType(t.ParameterType)).ToArray()
};
}
public MethodInfo ToMethod() {
return ToMethod(AppDomain.CurrentDomain);
}
public MethodInfo ToMethod(AppDomain domain) {
Type[] parameterTypes = ParameterTypes.Select(t => t.ToType(domain)).ToArray();
return DeclaringType.ToType(domain).GetMethod(MethodName, parameterTypes);
}
}
class MethodCallDTO {
public MethodSignatureDTO Method;
public object Instance;
public object[] Arguments;
public object Invoke() {
return Invoke(AppDomain.CurrentDomain);
}
public object Invoke(AppDomain domain) {
return Method.ToMethod(domain).Invoke(Instance, Arguments);
}
}
我将列出为保存的方法调用序列化所需的内容:AssemblyId・类名・方法名・ArgumentTypes(意思是AssemblyId・在泛型和特殊方法的支持下,这变得有点复杂。
class TypeDTO {
public string AssemblyName;
public string ClassName;
public static TypeDTO FromType(Type type) {
return new TypeDTO() {
AssemblyName = type.Assembly.FullName,
ClassName = type.FullName
};
}
public Type ToType() {
return ToType(AppDomain.CurrentDomain);
}
public Type ToType(AppDomain domain) {
Assembly assembly = domain.GetAssemblies().Where(t => t.FullName == AssemblyName).Single();
return assembly.GetType(ClassName);
}
}
class MethodSignatureDTO {
public TypeDTO DeclaringType;
public string MethodName;
public TypeDTO[] ParameterTypes;
public static MethodSignatureDTO FromMethod(MethodInfo method) {
return new MethodSignatureDTO() {
DeclaringType = TypeDTO.FromType(method.DeclaringType),
MethodName = method.Name,
ParameterTypes = method.GetParameters().Select(t => TypeDTO.FromType(t.ParameterType)).ToArray()
};
}
public MethodInfo ToMethod() {
return ToMethod(AppDomain.CurrentDomain);
}
public MethodInfo ToMethod(AppDomain domain) {
Type[] parameterTypes = ParameterTypes.Select(t => t.ToType(domain)).ToArray();
return DeclaringType.ToType(domain).GetMethod(MethodName, parameterTypes);
}
}
class MethodCallDTO {
public MethodSignatureDTO Method;
public object Instance;
public object[] Arguments;
public object Invoke() {
return Invoke(AppDomain.CurrentDomain);
}
public object Invoke(AppDomain domain) {
return Method.ToMethod(domain).Invoke(Instance, Arguments);
}
}