溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ASP.NET Web API Model-ActionBinding

發(fā)布時間:2020-07-19 08:03:58 來源:網(wǎng)絡 閱讀:838 作者:jinyuan0829 欄目:編程語言

ASP.NET Web API Model-ActionBinding

前言

前面的幾個篇幅把Model部分的知識點劃分成一個個的模塊來講解,而在控制器執(zhí)行過程中分為好多個過程,對于控制器執(zhí)行過程()主要講解了過濾器以及在后面的過濾器篇幅中也有講到,而在過濾器之中還有一些執(zhí)行過程,也就是在授權過濾器執(zhí)行完畢后,行為過濾器執(zhí)行之前,我們要做的就是Model綁定,面前也都說了之前對Model的知識點模塊都講解的差不多了,今天這個篇幅我們就來看一下這些零散知識點的源頭,也就是Model綁定的入口點。

 

 

Model-ActionBinding

HttpActionBinding的由來

我們通過前面幾篇的了解都知道在ASP.NET Web API框架中進入整個Model綁定的入口點就是在HttpActionBinding類型中,對于這個類型前面的篇幅也介紹過,它里面封裝了ParameterBinding數(shù)組,這些ParameterBinding就是控制器方法中每個參數(shù)執(zhí)行Model綁定的對象了,既然我們知道HttpActionBinding類型中有著許多ParameterBinding類型的對象實例,那么我們就要看看HttpActionBinding類型是怎么生成的。

示例代碼1-1

this.SetSingle<IActionValueBinder>(new DefaultActionValueBinder());

首先我們看到示例代碼1-1中可以看到在HttpConfiguration類型的服務容器中,默認注冊為IActionValueBinder類型服務的是DefaultActionValueBinder類型。

示例代碼1-2

namespace System.Web.Http.ModelBinding
{
    public class DefaultActionValueBinder : IActionValueBinder
    {
        public DefaultActionValueBinder();

        public virtual HttpActionBinding GetBinding(HttpActionDescriptor actionDescriptor);
        protected virtual HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter);
    }
}


代碼1-2中所示的是DefaultActionValueBinder類型的定義,其中的這兩個方法很重要,第一個GetBinding()方法是用以框架內部來進行調用,根據(jù)HttpActionDescriptor控制器方法描述類型對象獲取到我們所需的HttpActionBinding,而其內部實現(xiàn)則是調用下面的GetParameterBinding()方法,利用HttpActionDescriptor對象獲取到HttpParameterDescriptor集合后,然后遍歷的去調用GetParameterBinding()方法,從而能夠獲取到HttpParameterBinding對象實例,最后生成HttpActionBinding對象實例,從設計角度來看這個DefaultActionValueBinder類型中的兩個方法GetBinding()GetParameterBinding()方法都是采用了templatemethod模式,這種模式在框架設計中很常見。

 

HttpParameterBinding的由來

下面我們就要來說說GetParameterBinding()方法的細節(jié)實現(xiàn)了因為關乎著使用哪種方式來進行綁定。也就是根據(jù)HttpParameterDescriptor類型實例怎么去創(chuàng)建HttpParameterBinding的。

示例代碼1-3

    protected virtual HttpParameterBinding GetParameterBinding(HttpParameterDescriptor parameter)
    {
        ParameterBindingAttribute parameterBinderAttribute = parameter.ParameterBinderAttribute;
        if (parameterBinderAttribute == null)
        {
            ParameterBindingRulesCollection parameterBindingRules = parameter.Configuration.ParameterBindingRules;
            if (parameterBindingRules != null)
            {
                HttpParameterBinding binding = parameterBindingRules.LookupBinding(parameter);
                if (binding != null)
                {
                    return binding;
                }
            }
            Type parameterType = parameter.ParameterType;
            if (TypeHelper.IsSimpleUnderlyingType(parameterType) || TypeHelper.HasStringConverter(parameterType))
            {
                return parameter.BindWithAttribute(new FromUriAttribute());
            }
            parameterBinderAttribute = new FromBodyAttribute();
        }
        return parameterBinderAttribute.GetBinding(parameter);
     }

代碼1-3就是具體的實現(xiàn)了,那我們就就來看一下其中的過程以及會涉及到的類型。

首先會根據(jù)參數(shù)HttpParameterDescriptor類型實例獲取到在這個控制器方法參數(shù)上使用了ParameterBindingAttribute標識,并且獲取ParameterBindingAttribute類型實例。我們暫且就來看一下ParameterBindingAttribute類型定義。

示例代碼1-4

    [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
    public abstract class ParameterBindingAttribute : Attribute
    {
        // Methods
        protected ParameterBindingAttribute();
        public abstract HttpParameterBinding GetBinding(HttpParameterDescriptor parameter);
    }


從代碼1-4可以看出,這個ParameterBindingAttribute類型適用于類型以及參數(shù),也就是說我們選擇綁定的方式可以在Model類型定義的時候標識這個特性,也可以在定義控制器方法的時候適當?shù)慕o參數(shù)這個特性標識。

然而在這個類型中為什么會有GetBinding()方法呢?因為這個類型是抽象類型,也就是采用了上面所說過的template method模式,而在子類實現(xiàn)中,根據(jù)自身適應的情況生成響應的HttpParameterBinding類型??聪氯缦碌膱D表示相關的對象模型。

1

ASP.NET Web API Model-ActionBinding

上面圖1中涉及到的每個類型大家可以去看前面的篇幅,篇幅中有遺漏的就麻煩大家自己多動一下手去看看吧。

 

HttpParameterBinding的選擇機制

 

接著代碼1-3的思緒,在我們獲取到了ParameterBindingAttribute之后,并不知道這個控制器方法中的參數(shù)是否標識有ParameterBindingAttribute,或者是參數(shù)類型上是否有標識。這個時候假使是有的話,可以看到代碼1-3中的最后一句代碼,直接使用獲取到的ParameterBindingAttribute類型進行調用GetBinding()方法,也就是在上一小節(jié)中圖1所示的那樣。

然而還有一種情況,就是我們在定義控制器方法的時候參數(shù)沒有明確的標識我們要使用某種綁定機制,或者是在定義Model的時候沒有明確的表示,這個時候框架則會從定義好的規(guī)則集合中根據(jù)當前控制其方法參數(shù)的描述類型來獲取對應的ParameterBinding類型實例。如下的示例代碼定義了規(guī)則集合的定義。

示例代碼1-5

    internal static ParameterBindingRulesCollection GetDefaultParameterBinders()
    {
        ParameterBindingRulesCollection ruless = new ParameterBindingRulesCollection();
        ruless.Add(typeof(CancellationToken), parameter => new CancellationTokenParameterBinding(parameter));
        ruless.Add(typeof(HttpRequestMessage), parameter => new HttpRequestParameterBinding(parameter));
        ruless.Add(delegate (HttpParameterDescriptor parameter) {
            if (!typeof(HttpContent).IsAssignableFrom(parameter.ParameterType))
            {
                return null;
            }
            return parameter.BindAsError(Error.Format(SRResources.ParameterBindingIllegalType, new object[] { parameter.ParameterType.Name, parameter.ParameterName }));
        });
        return ruless;
     }


代碼1-5中所表示的就是規(guī)則定義,意思就是在我們使用HttpParameterDescriptor類型實例來從集合中想獲取ParameterBinding的時候,ParameterBindingRulesCollection類型會把我們的HttpParameterDescriptor類型實例中的ParameterType取出來和之前定義的每一項規(guī)則的類型進行比對,類型吻合了就會隨之調用對應的委托類型進行ParameterBinding生成。從代碼1-5中我們可以看到的是規(guī)則中只有CancellationToken類型和HttpRequestMessage類型,假使這個時候我們的控制其方法參數(shù)類型是自定義的復雜類型,這里也都沒有定義,這個時候框架會取出HttpParameterDescriptor類型中的ParameterType進行判斷,假使是可以轉換成string類型的簡單類型參數(shù),則會生成一個FromUriAttribute類型作為標識,FromUriAttribute類型繼承自ModelBinderAttribute類型。

假使這里的判斷沒有通過則說明是復雜類型,最后我們再看待代碼1-3中的定義最后生成的是FromBodyAttribute標識類型,這個時候請參照圖1。


向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI