【问题标题】:Invoke method similar to WCF invoker?调用类似于 WCF 调用程序的方法?
【发布时间】:2017-03-03 17:08:21
【问题描述】:

一些强类型类:

public class A 
{
    public C Process(B b)
    { 
        return new C()
        {
            Output = b.Property + " bar!"
        };
    }
}

public class B
{
    public string Property {get;set;}
}

public class C
{
    public string Output {get;set;}
}

输入为 JSON 字符串:

string input = "{\"Property\":\"foo\"}";

我想要的是,如果我有 A 的实例作为对象,我想调用这个 JSON 并检索对象输出:

object instanceOfA = new A();

object result = instanceOfA.GetType().GetMethod("Process").Invoke(instanceOfA, new []{ /*json here?*/});

所以,它基本上类似于对一些普通参数的一些 JavaScript 调用。

【问题讨论】:

    标签: c# json wcf


    【解决方案1】:

    如果将“Process”方法的方法签名更改为将字符串作为输入,并尝试将输入反序列化为您想要的类型呢?所以是这样的:

    string input = "{\"Property\":\"foo\"}";
    object instanceOfA = new A();
    object result = instanceOfA.GetType().GetMethod("Process").Invoke(instanceOfA, new object[]{ input });
    
    public class A
    {
        public C Process(string input)
        {
            var b = (B) JsonConvert.DeserializeObject(input, typeof(B));
    
            if (!string.IsNullOrEmpty(b.Property))
            {
                return new C()
                {
                    Output = b.Property + " bar!"
                };
            }
    
            return null;
        }
    }
    
    public class B
    {
        public string Property { get; set; }
    }
    
    public class C
    {
        public string Output { get; set; }
    }
    

    【讨论】:

    • 这不行。我编写插件,并且不想每次编写新插件时都反序列化“某些东西”。最好将此任务委派给始终执行此操作的上层。
    • 好的。我不确定我是否完全理解您的需求。如果您在上层进行序列化和反序列化并且“某些东西”可能会有所不同,您仍然不需要从 Process 方法返回不同的对象类型吗?如果是这样,您可以使用接口作为方法参数,或者使用字符串作为方法的输入和输出。
    • 我不能使用字符串作为插件的输入。与 WCF 合约进行类比——你使用强类型实体,你甚至不知道它们是如何表示的——作为字符串、字节数组或其他。
    • 我正在考虑的比较是 MVC 中的自定义模型绑定器,您可以在其中实现另一层以将调用路由到插件并首先将 Json 绑定到那里的实体。但这可能不是您需要的。抱歉,我无法提供更多帮助
    • 我已经找到了部分解决方案。稍后我会发布它。
    【解决方案2】:

    使用 Newtonsoft.Json 功能简单地解决了问题:

    public class JsonInvoker
    {
        private readonly MethodInfo _methodInfo;
        private readonly Type _paramType;
        private readonly JsonSerializerSettings _settings;
        public JsonInvoker(Type instanceType, string methodName)
        {
            _methodInfo = instanceType.GetMethod(methodName);
            _paramType = _methodInfo.GetParameters()[0].ParameterType;
            _settings = new JsonSerializerSettings
            {
                ContractResolver = new RequireObjectPropertiesContractResolver(),
                MissingMemberHandling = MissingMemberHandling.Error
            };
        }
    
        public object Invoke(object instance, string json)
        {
            var input = JsonConvert.DeserializeObject(json, _paramType, _settings);
            var output = _methodInfo.Invoke(instance, new[] { input });
            return output;
        }
    
        private class RequireObjectPropertiesContractResolver : DefaultContractResolver
        {
            protected override JsonObjectContract CreateObjectContract(Type objectType)
            {
                var contract = base.CreateObjectContract(objectType);
                contract.ItemRequired = Required.AllowNull;
                return contract;
            }
        }
    }
    

    现在我可以调用我的方法了:

    class Program
    {
        static void Main(string[] args)
        {
            object plugin = new A();
            string json = "{\"Property\":\"foo\"}";
            var invoker = new JsonInvoker(plugin.GetType(), "Process");
            //here I call invoker with simple string.
            var output = invoker.Invoke(plugin, json);
    
        }
    }
    
    
    
    public class A
    {
        public C Process(B input)
        {
            return new C
                   {
                       Property = input.Property + " bar"
                   };
        }
    }
    
    public class C
    {
        public string Property { get; set; }
    }
    public class B
    {
        public string Property { get; set; }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多