简体   繁体   English

WPF或WinForms,类似于MVC查询字符串的值提供程序/绑定

[英]WPF or WinForms, MVC querystring-like value provider/binding

I'm working on a WPF project using a third party web browser control. 我正在使用第三方Web浏览器控件进行WPF项目。 To pass data from the web page I'm doing a redirect in JavaScript and then cancelling the "Navigating" event of the browser [see Using WebKit.NET to call a C# function from JavaScript). 为了从网页传递数据,我正在使用JavaScript进行重定向,然后取消浏览器的“ Navigating”事件(请参阅使用WebKit.NET从JavaScript调用C#函数)。

In the navigating event I'm doing some URL crunching to create a dictionary of arguments from the URL parameters, and then call a particular method (also based on the URL). 在导航事件中,我正在进行一些URL处理,以根据URL参数创建参数字典,然后调用特定方法(也基于URL)。

With a URL that looks something like this = 'app-Method?arg1=5.3&arg2=3' I end up with a Dictionary containing the following information: 使用看起来像这样的URL ='app-Method?arg1 = 5.3&arg2 = 3',我最终得到了一个包含以下信息的字典:

//var methodName = "Method";
//var dictionary = { { "arg1", "5.3" }, { "arg2", "3" } };

It I can't do the conversion at this stage as different methods would have different arguments with different types. 我无法在此阶段进行转换,因为不同的方法使用不同的类型会有不同的参数。

I'd then call another method (method name from the URL) like this: 然后,我将这样调用另一个方法(URL中的方法名称):

switch(methodName)
{
     case "Method":
         Method(Convert.ToDecimal(dictionary["arg1"]), Convert.ToInt(dictionary["arg2"]));
         break;
}

Obviously in MVC a HTTPGet action method does all this conversion, crunching, and method calling for me. 显然,在MVC中,HTTPGet操作方法完成了所有这些转换,处理和方法调用。 I was wondering if (using the MVC libraries or some other method) it is possible to replicate this sort of behaviour in a non-MVC application, just for the purposes of cleaner looking code and more simplicity if there are lots of different methods. 我想知道是否(使用MVC库或其他方法)可以在非MVC应用程序中复制这种行为,只是为了使代码看起来更简洁,并且如果有很多不同的方法则更加简单。

I hope that makes sense, I'm finding it a little difficult to explain. 我希望这是有道理的,我觉得很难解释。

Edit: 编辑:

Here's full example code: 这是完整的示例代码:

this.browser.Navigating += (s, ev) =>
        {
            if (ev.Url.AbsoluteUri.Contains("app"))
            {
                var method = ev.Url.Host.Split('-')[1];
                var arguments = ev.Url.Query.TrimStart('?').Split('&');

                var dictionary = new Dictionary<string, string>();

                foreach (var arg in arguments)
                {
                    var split = arg.Split('=');

                    dictionary.Add(split[0], split[1]);
                }

                switch (method)
                {
                    case "add":
                        Add(Convert.ToInt32(dictionary["first"]), Convert.ToInt32(dictionary["second"]));
                        break;
                    default:                            
                        break;
                }

                ev.Cancel = true;
            }
        };

I figured out a really flexible way to do this using reflection and the JSON.net library. 我想出了一种使用反射和JSON.net库执行此操作的非常灵活的方法。 I changed the URL so that the parameters are passed as an HTML Encoded JSON. 我更改了URL,以便将参数作为HTML编码的JSON传递。 I loop through the required arguments and use the ToObject method of JSON.net to convert them to the required type. 我通过所需的参数和循环使用JSON.net的ToObject方法将它们转换为所需类型。 This even works when passing arrays and complex types. 甚至在传递数组和复杂类型时也可以使用。

var jsonString = HttpUtility.UrlDecode(ev.Url.Query.TrimStart('?'));

var json = JObject.Parse(jsonString);

var methodInfo = objWithMethodToRun.GetMethod(methodName);

var parameterInfoArray = methodInfo.GetParameters();
var parameters = new object[parameterInfoArray.Length];

//Add parameters as correct types to array.
for (var i = 0; i < parameterInfoArray.Length; i++)
{
    var methodParameterInfo = parameterInfoArray[i];

    //If there is nothing in the json we'll set it to null
    if (json[methodParameterInfo.Name] == null || json[methodParameterInfo.Name].Type == JTokenType.Null)
    {
        parameters[i] = null;
    }
    else
    {
        var convertMethod = json[methodParameterInfo.Name].GetType().GetMethod("ToObject", new Type[] { })
                            .MakeGenericMethod(methodParameterInfo.ParameterType);

        parameters[i] = convertMethod.Invoke(json[methodParameterInfo.Name], null);
    }
}

//Invoke the method
dynamic result = methodInfo.Invoke(objWithMethodToRun, parameters);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM