Asp.net MVC樣本項目“Suteki.Shop”分析之ModelBinder

來源:互聯網
上載者:User

在Suteki.Shop中,作者構造了一個ModelBinder基類“DataBinder”,其本身繼承自 IModelBinder介面,並以此其類派生出其它一些子類類如ProductBinder等等。可以說除了極個別的地方 之外,DataBinder被用於了Suteki.Shop大多數的ModelBinder綁定情境之路。

首先看一下其類圖 結構:

作為基類, DataBinder(圖中左下方)實現了將HTTP請求過來的資料轉換成為模型中相應的類型。其核心方法就是 BindModel,下面做一下解釋說明:

public virtual object BindModel(ControllerContext controllerContext,  ModelBindingContext bindingContext)
{
object entity;

if (declaringAttribute == null || declaringAttribute.Fetch)
{
entity =  FetchEntity(bindingContext, controllerContext);
}
else
{
entity =  Activator.CreateInstance(bindingContext.ModelType);
}

try
{
validatingBinder.UpdateFrom(entity,  controllerContext.HttpContext.Request.Form, bindingContext.ModelState,  bindingContext.ModelName);
}
catch(ValidationException ex)
{
//Ignore validation exceptions - they are stored in ModelState.
//The  controller can access the errors by inspecting the ModelState dictionary.
}

return entity;
}

首先要說明的就是declaringAttribute,這個變 量其實是DataBindAttribute類型執行個體,其作用是判斷當前所請求過來的資料是用於建立新的Model資訊 還是擷取並綁定已有的資料記錄。該執行個體的實始化是交給Accept方法來實現的(注意Accept方法的聲明 是在IAcceptsAttribute介面中定義的):

public void Accept(Attribute attribute)
{
declaringAttribute =  (DataBindAttribute) attribute;
}

而對該方法的調用是放在了 BindUsingAttribute的GetBinder()方法中,所以這裡要先看一下BindUsingAttribute的具體實現:

public class BindUsingAttribute : CustomModelBinderAttribute
{
private readonly Type binderType;

public BindUsingAttribute(Type  binderType)
{
if(!typeof(IModelBinder).IsAssignableFrom(binderType))
{
throw new InvalidOperationException("Type '{0}' does not implement  IModelBinder.".With(binderType.Name));
}

this.binderType =  binderType;
}

public override IModelBinder GetBinder()
{
var  binder = (IModelBinder) ServiceLocator.Current.GetInstance(binderType);

if (binder is IAcceptsAttribute)
{
((IAcceptsAttribute)binder).Accept(this);
}

return binder;
}
}

這個屬性類也就是在Action中進行 ModelBinder綁定時用到的,其類構造方法中通過一個型別參數初始化並在GetBinder()方法中使用 ServiceLocator來進行最終的ModelBinder執行個體化構建,注意在該方法中有對當前binder的邏輯判斷 (IAcceptsAttribute),並以此來區別當前Action綁定的ModelBinder是否實現了IAcceptsAttribute介面 。如果沒實現或declaringAttribute.Fetch為true時,就會在之前的DataBinder類方法 “BindModel”中調用“FetchEntity()”方法,FetchEntity會從提交的資料中的主鍵(PrimaryKey)中檢索資料並返回該對象執行個體,代碼如下:

private object FetchEntity(ModelBindingContext bindingContext,  ControllerContext controllerContext)
{
object entity;
var primaryKey =  bindingContext.ModelType.GetPrimaryKey();//從Shop.dbml中尋找相應的主鍵資訊
string  name = bindingContext.ModelName + "." + primaryKey.Name;//拼接出要擷取的主 鍵名稱

string rawKeyValue = controllerContext.HttpContext.Request.Form [name];

if (string.IsNullOrEmpty(rawKeyValue))
{
throw new  InvalidOperationException("Could not find a value named '{0} '".With(name));
}

int key = Convert.ToInt32(rawKeyValue);
var repository = resolver.GetRepository(bindingContext.ModelType);
entity =  repository.GetById(key);
return entity;
}

注意上面代碼中的這兩行:

var repository = resolver.GetRepository(bindingContext.ModelType);
entity = repository.GetById(key);

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.