我们在Nancy的默认模型绑定器上遇到了问题.鉴于以下……
public class Foo { public Foo() { } public string Name { get; set; } public Bar Bar { get; set; } } public class Bar { public string Name { get; set; } }
像……这样的元素
<input type="text" value="Name" /> <input type="text" value="Bar.Name" />
使用默认模型绑定器如此…
var foo = this.Bind< Foo>();
这正确绑定Foo.Name但无法绑定Foo.Bar.Name
有没有办法用默认绑定器启用这种绑定,还是我们需要自己滚动?如果有的话有什么好的例子吗?
解决方法
为什么不尝试这个.我很确定递归可以被优化,并且它会在不起作用的地方出现,并且它可以放在比IModelBinder更聪明的地方,但它基本上可以做你想要的.
/// <summary> /// Sample model binder that manually binds customer models /// </summary> public class CustomModelBinder : IModelBinder { /// <summary> /// Bind to the given model type /// </summary> /// <param name="context">Current context</param> /// <param name="modelType">Model type to bind to</param> /// <param name="blackList">Blacklisted property names</param> /// <returns>Bound model</returns> public object Bind(NancyContext context,Type modelType,params string[] blackList) { var parentObject = Activator.CreateInstance(modelType); foreach (var key in context.Request.Form) { var value = context.Request.Form[key]; this.SetObjectValue(parentObject,modelType,key,value); } return parentObject; } /// <summary> /// Sets the object value. /// </summary> /// <param name="instance">The instance.</param> /// <param name="type">The type.</param> /// <param name="key">Name of the property.</param> /// <param name="propertyValue">The property value.</param> private void SetObjectValue(object instance,Type type,string key,string propertyValue) { if (key.Contains(".")) { this.SetObjectValueDeep(instance,type,propertyValue); } PropertyInfo propertyInfo = type.GetProperty(key); if (propertyInfo == null) { return; } propertyInfo.SetValue(instance,Convert.ChangeType(propertyValue,propertyInfo.PropertyType),null); } /// <summary> /// Sets the object value derp. /// </summary> /// <param name="instance">The instance.</param> /// <param name="type">The type.</param> /// <param name="key">The key.</param> /// <param name="propertyValue">The property value.</param> private void SetObjectValueDeep(object instance,string propertyValue) { var propList = key.Split('.').ToList(); PropertyInfo propertyInfo = type.GetProperty(propList.First()); if (propertyInfo == null) { return; } var childObject = propertyInfo.GetValue(instance,null); if (childObject == null) { childObject = Activator.CreateInstance(propertyInfo.PropertyType); propertyInfo.SetValue(instance,childObject,null); } propList.RemoveAt(0); var newKey = propList.Aggregate(string.Empty,(current,prop) => current + (prop + ".")).TrimEnd('.'); if (newKey.Contains(".")) { this.SetObjectValueDeep(childObject,childObject.GetType(),newKey,propertyValue); } else { this.SetObjectValue(childObject,propertyValue); } } /// <summary> /// Determines whether this instance can bind the specified model type. /// </summary> /// <param name="modelType">Type of the model.</param> /// <returns> /// <c>true</c> if this instance can bind the specified model type; otherwise,<c>false</c>. /// </returns> public bool CanBind(Type modelType) { return true; } }