ASP.NET MVC Preview生命週期分析(三)

來源:互聯網
上載者:User

詳細看看InvokeAction方式的執行:

protected internal bool InvokeAction(string actionName) {
      return InvokeAction (actionName, new RouteValueDictionary());
    }
     protected internal virtual bool InvokeAction(string actionName, RouteValueDictionary values) {
      if (String.IsNullOrEmpty(actionName)) {
        throw new ArgumentException(MvcResources.Common_NullOrEmpty, "actionName");
      }
      // We have to loop through all the methods to make sure there isn't
       // a conflict. If we stop the loop the first time we find a match
      // we might miss some error cases.
       MemberInfo[] membInfos = GetType().GetMember(actionName, MemberTypes.Method,
        BindingFlags.IgnoreCase | BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public);
      MethodInfo foundMatch = null;
      foreach (MemberInfo memberInfo in membInfos) {
         MethodInfo mi = (MethodInfo)memberInfo;
         // 1) Action methods must not have the non-action attribute in their inheritance chain, and
        // 2) special methods like constructors, property accessors, and event accessors cannot be action methods, and
        // 3) methods originally defined on Object (like ToString) or Controller cannot be action methods.
         if (!mi.IsDefined(typeof(NonActionAttribute), true) &&
          !mi.IsSpecialName &&
          mi.DeclaringType.IsSubclassOf(typeof(Controller))) {
          if (foundMatch != null) {
             throw new InvalidOperationException(
               String.Format(CultureInfo.CurrentUICulture, MvcResources.Controller_MoreThanOneAction, actionName, GetType()));
          }
          foundMatch = mi;
        }
      }
      if (foundMatch != null) {
        InvokeActionMethod(foundMatch, values);
        return true;
      }
       return false;
    }
它通過反射擷取所有同名 Action 方法信 息;其次,它過濾掉所有有 NonActionAttribute 和 IsSpecialName 標記的方法 ;第三,當同名有效 Action 被重載時它會拋出異常(提示 Controller_MoreThanOneAction),繼續調用InvokeActionMethod:

[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
   Justification = "We use MethodInfo since it represents only methods and not constructors." +
   "This method only makes sense for use with methods.")]
protected internal virtual void InvokeActionMethod(MethodInfo methodInfo, RouteValueDictionary values) {
   if (methodInfo == null) {
     throw new ArgumentNullException("methodInfo");
   }
   if (values == null) {
     values = new RouteValueDictionary();
   }
   if (methodInfo.ContainsGenericParameters) {
     throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, MvcResources.Controller_ActionCannotBeGeneric, methodInfo.Name));
   }
   ParameterInfo[] methodParameters = methodInfo.GetParameters();
   object[] parameterValues = null;
   if (methodParameters.Length > 0) {
     parameterValues = new object[methodParameters.Length];
     for (int i = 0; i < methodParameters.Length; i++) {
        ParameterInfo pi = methodParameters[i];
       if (pi.IsOut || pi.ParameterType.IsByRef) {
         throw new InvalidOperationException(String.Format (CultureInfo.CurrentUICulture, MvcResources.Controller_ReferenceParametersNotSupported, pi.Name, methodInfo.Name));
       }
       bool valueRequired = true;
       if (pi.ParameterType.IsClass) {
         // Classes (ref types) don't require values since we can pass in null
         valueRequired = false;
       }
       else {
          if ((pi.ParameterType.IsGenericType && ! pi.ParameterType.IsGenericTypeDefinition) &&
            (pi.ParameterType.GetGenericTypeDefinition() == typeof (Nullable<>))) {
           // Nullable types don't require values since we can pass in null
            valueRequired = false;
         }
       }
       // Try to get a value for the parameter. We use this order of precedence:
       // 1. Explicitly-provided extra parameters in the call to InvokeAction()
       // 2. Values from the RouteData (could be from the typed-in URL or from the route's default values)
       // 3. Request values (query string, form post data, cookie)
       object parameterValue = null;
       if (!values.TryGetValue (methodParameters[i].Name, out parameterValue)) {
         if (RouteData == null || !RouteData.Values.TryGetValue (methodParameters[i].Name, out parameterValue)) {
            if (Request != null) {
             parameterValue = Request[methodParameters[i].Name];
            }
         }
       }
       if (parameterValue == null && valueRequired) {
          throw new InvalidOperationException(String.Format (CultureInfo.CurrentUICulture, MvcResources.Controller_MissingParameter, pi.Name, methodInfo.Name));
       }
       try {
          parameterValues[i] = ConvertParameterType (parameterValue, methodParameters[i].ParameterType, methodParameters [i].Name, methodInfo.Name);
       }
       catch (Exception ex) {
         // Parameter value conversion errors are acceptable unless the value is required
          if (valueRequired) {
           throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, MvcResources.Controller_MissingParameter, pi.Name, methodInfo.Name), ex);
         }
       }
     }
   }
   InvokeActionMethodFilters(methodInfo, () => methodInfo.Invoke(this, parameterValues));
}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.