首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> 關於ASP.NET

ASP.NET MVC Model 繫結機制模擬實作:簡單型別與複雜型別綁定

     編輯:關於ASP.NET

ModelBinder 核心流程

DefaultModelBinder 為預設繫結器,核心方法:

  • GetParameterValues(ActionDescriptor):遍歷參數,呼叫 GetParameterValue。
  • GetParameterValue(ParameterDescriptor, prefix):嘗試帶前綴繫結,失敗且無明確前綴時退回空前綴(FallbackToEmptyPrefix)。
  • BindModel(Type, prefix):核心繫結邏輯。

簡單型別繫結

判斷依據:ModelMetadata.IsComplexType == false(支援字串轉換的型別:基本型別、DateTime、Guid、decimal 等)。

public object BindModel(Type parameterType, string prefix)
{
    if (!ValueProvider.ContainsPrefix(prefix)) return null;
    return ValueProvider.GetValue(prefix).ConvertTo(parameterType);
}

複雜型別繫結:遞迴屬性繫結

建立實例 → 遍歷 TypeDescriptor.GetProperties → 遞迴呼叫 BindModel(property.PropertyType, key) → 設定屬性值。

object model = CreateModel(parameterType);
foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(parameterType))
{
    string key = String.IsNullOrEmpty(prefix) ? prop.Name : prefix + "." + prop.Name;
    prop.SetValue(model, BindModel(prop.PropertyType, key));
}
return model;

實驗驗證:自訂繫結器整合

public class HomeController : Controller
{
    public DefaultModelBinder ModelBinder { get; private set; }
    public HomeController() { ModelBinder = new DefaultModelBinder(GetValueProvider()); }
    
    private void InvokeAction(string actionName)
    {
        var controllerDesc = new ReflectedControllerDescriptor(typeof(HomeController));
        var actionDesc = (ReflectedActionDescriptor)controllerDesc.FindAction(ControllerContext, actionName);
        actionDesc.MethodInfo.Invoke(this, ModelBinder.GetParameterValues(actionDesc).ToArray());
    }
    
    public void Index() { InvokeAction("Action"); }
    
    private IValueProvider GetValueProvider()
    {
        var data = new NameValueCollection();
        data.Add("foo", "abc");
        data.Add("bar", "123");
        data.Add("baz", "123.45");
        return new NameValueCollectionValueProvider(data, CultureInfo.InvariantCulture);
    }
    
    public void Action(string foo, [Bind(Prefix="baz")] double bar)
    {
        Response.Write($"foo: {foo}<br/>bar: {bar}<br/>");
    }
}

結果:foo=abc、bar=123.45([Bind(Prefix="baz")] 將參數 bar 對應至鍵 baz)。

關鍵設計細節

  • ParameterBindingInfo.Prefix 優先於參數名稱作為前綴。
  • FallbackToEmptyPrefix:無明確前綴且帶前綴繫結失敗時,嘗試空前綴(支援無前綴表單)。
  • CreateModel:預設呼叫無參建構子,可覆寫支援工廠模式。
  • TypeDescriptor 而非反射,支援 ICustomTypeDescriptor 動態屬性。

總結

簡單型別直接轉換,複雜型別遞迴屬性繫結。DefaultModelBinder 以 ValueProvider 為資料來源,ModelMetadata 判斷型別分類,BindAttribute 控制前綴對應。掌握此流程可自訂繫結器處理特殊格式或資料來源。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved