使用 ASP.NET MVC 路由之类的路由解析为对象

Parse to object with a route like ASP.NET MVC routing

在 ASP.NET MVC 中可以这样定义路由:

routes.MapRoute("myroute",
    "myroute/{country}/{name}-{type}",
    new { controller = "MyController", action = "Get" });

然后将其直接解析为一个对象:

public class MyController : Controller
{
   public HttpResponseMessage Get([FromRoute] MyViewModel model)
   {
      //TODO do stuff with model.
   }
}

这是我的视图模型:

public class MyViewModel
{
    public string Name { get; set; }
    public string Type{ get; set; }
}

我的问题是,我可以在一个简单的控制台应用程序中进行相同的解析吗?

class Program
{
    static void Main(string[] args)
    {
        string route = "myroute/{country}/{name}-{type}";

        string input = "myroute/Denmark/MyName-MyType";

        //TODO Parse input to MyViewModel with route
        MyViewModel result;
    }
}

public class MyViewModel
{
    public string Name { get; set; }
    public string Type { get; set; }
}

一定有某种方法可以做到这一点,因为 ASP.NET MVC 路由是可能的。

使用 Microsoft.AspNetCore.Routing:

解析和应用路由模板实际上非常简单
string route = "/myroute/{country}/{name}-{type}";
string input = "/myroute/Denmark/MyName-MyType";

var routeTemplate = TemplateParser.Parse(route);
var matcher = new TemplateMatcher(routeTemplate, null);
var values = new RouteValueDictionary();

if (matcher.TryMatch(input, values))
{
    foreach (var item in values)
    {
        Console.WriteLine("{0}: {1}", item.Key, item.Value);
    }
}
country: Denmark
type: MyType
name: MyName

但是,将其绑定到一个实体将意味着您将拥有整个 model binding 堆栈,这恰好“有点”更复杂,无法单独启动。因此,我只建议您使用一点反射手动进行此操作:

public static T BindValues<T>(RouteValueDictionary values)
    where T : new()
{
    var obj = new T();
    foreach (var prop in typeof(T).GetProperties())
    {
        if (values.ContainsKey(prop.Name))
        {
            prop.SetValue(obj, values[prop.Name]);
        }
    }
    return obj;
}

并像这样使用:

var obj = BindValues<MyViewModel>(values);

虽然这显然不如模型绑定强大,但它应该足以满足您的用例。