C# Nancy模型绑定到子类

C# Nancy模型绑定到子类,c#,model-binding,nancy,C#,Model Binding,Nancy,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" />

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.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, key, 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, Type type, string key, 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, childObject.GetType(), newKey, 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;
    }
}
//
///手动绑定客户模型的示例模型绑定器
/// 
公共类CustomModelBinder:IModelBinder
{
/// 
///绑定到给定的模型类型
/// 
///当前上下文
///要绑定到的模型类型
///列入黑名单的财产名称
///束缚模型
公共对象绑定(NancyContext上下文,类型modelType,参数字符串[]黑名单)
{
var parentObject=Activator.CreateInstance(modelType);
foreach(context.Request.Form中的var键)
{
var value=context.Request.Form[key];
SetObjectValue(parentObject、modelType、key、value);
}
返回parentObject;
}
/// 
///设置对象值。
/// 
///实例。
///类型。
///属性的名称。
///属性值。
私有void SetObjectValue(对象实例、类型类型、字符串键、字符串属性值)
{
if(键包含(“.”)
{
SetObjectValueDeep(实例、类型、键、propertyValue);
}
PropertyInfo PropertyInfo=type.GetProperty(键);
如果(propertyInfo==null)
{
返回;
}
SetValue(实例,Convert.ChangeType(propertyValue,propertyInfo.PropertyType),null);
}
/// 
///设置对象值derp。
/// 
///实例。
///类型。
///钥匙。
///属性值。
私有void SetObjectValueDeep(对象实例、类型、字符串键、字符串属性值)
{
var propList=key.Split('.').ToList();
PropertyInfo PropertyInfo=type.GetProperty(propList.First());
如果(propertyInfo==null)
{
返回;
}
var childObject=propertyInfo.GetValue(实例,null);
if(childObject==null)
{
childObject=Activator.CreateInstance(propertyInfo.PropertyType);
SetValue(实例,子对象,空);
}
propList.RemoveAt(0);
var newKey=propList.Aggregate(string.Empty,(current,prop)=>current+(prop+)).TrimEnd('.');
if(newKey.Contains(“.”)
{
this.SetObjectValueDeep(childObject,childObject.GetType(),newKey,propertyValue);
}
其他的
{
this.SetObjectValue(childObject,childObject.GetType(),newKey,propertyValue);
}
}
/// 
///确定此实例是否可以绑定指定的模型类型。
/// 
///模型的类型。
/// 
///如果此实例可以绑定指定的模型类型,则为true;否则为false。
/// 
公共布尔CanBind(类型modelType)
{
返回true;
}
}

当您在客户端填充javascript对象模型,然后以json或xml提交该模型时,您的运气可能会更好。我确信孩子们的物品会被捆绑起来。这太棒了,谢谢。添加列表处理和发布到GitHub可能是个好主意。