2014-02-06 32 views
0

通過使用回答this question我已經得到了一個逗號分隔的列表在我的模型綁定到一個簡單的IEnumerable類型定製「現場」活頁夾

然而,而不是宣佈在控制器中模型綁定(或全局性的),我更希望能夠在我的模型的一個字段上聲明某種屬性,這些字段聲明它是需要這種邊界綁定方法的字段。

我想象的東西,看起來像這樣:

[CommaSeparated] 
public IEnumerable<int> ListIDs {get;set;} 

任何幫助將非常感激

回答

2

假設你已經聲明瞭一個標記屬性:

[AttributeUsage(AttributeTargets.Property)] 
public class CommaSeparatedAttribute: Attribute 
{ 

} 

這是很輕鬆的適應在鏈接帖子中看到的模型聯編程序的實現僅適用於使用此屬性修飾屬性的情況:

public class CommaSeparatedValuesModelBinder : DefaultModelBinder 
{ 
    private static readonly MethodInfo ToArrayMethod = typeof(Enumerable).GetMethod("ToArray"); 

    protected override object GetPropertyValue(ControllerContext controllerContext, ModelBindingContext bindingContext, System.ComponentModel.PropertyDescriptor propertyDescriptor, IModelBinder propertyBinder) 
    { 
     if (propertyDescriptor.PropertyType.GetInterface(typeof(IEnumerable).Name) != null) 
     { 
      var actualValue = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name); 

      if (actualValue != null && !String.IsNullOrWhiteSpace(actualValue.AttemptedValue) && actualValue.AttemptedValue.Contains(",")) 
      { 
       var valueType = propertyDescriptor.PropertyType.GetElementType() ?? propertyDescriptor.PropertyType.GetGenericArguments().FirstOrDefault(); 
       bool isCommaSeparated = propertyDescriptor.Attributes.OfType<CommaSeparatedAttribute>().Any(); 

       if (isCommaSeparated && valueType != null && valueType.GetInterface(typeof(IConvertible).Name) != null) 
       { 
        var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(valueType)); 

        foreach (var splitValue in actualValue.AttemptedValue.Split(new[] { ',' })) 
        { 
         list.Add(Convert.ChangeType(splitValue, valueType)); 
        } 

        if (propertyDescriptor.PropertyType.IsArray) 
        { 
         return ToArrayMethod.MakeGenericMethod(valueType).Invoke(this, new[] { list }); 
        } 
        else 
        { 
         return list; 
        } 
       } 
      } 
     } 

     return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder); 
    } 
} 

基本上這就是你需要確定,以應用自定義逗號分隔邏輯或退回到默認行爲,如果物業裝飾有標記的屬性:

​​
+0

輝煌!這工作完美。我試圖做你做的事情,但我試圖使用正在傳遞的'type'參數。感謝你! – JakeJ