1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
namespace System.Web.Mvc {
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Web.Mvc.Resources;
public abstract class ActionDescriptor : ICustomAttributeProvider, IUniquelyIdentifiable {
private readonly static ActionMethodDispatcherCache _staticDispatcherCache = new ActionMethodDispatcherCache();
private ActionMethodDispatcherCache _instanceDispatcherCache;
private readonly Lazy<string> _uniqueId;
private static readonly ActionSelector[] _emptySelectors = new ActionSelector[0];
protected ActionDescriptor() {
_uniqueId = new Lazy<string>(CreateUniqueId);
}
public abstract string ActionName {
get;
}
public abstract ControllerDescriptor ControllerDescriptor {
get;
}
internal ActionMethodDispatcherCache DispatcherCache {
get {
if (_instanceDispatcherCache == null) {
_instanceDispatcherCache = _staticDispatcherCache;
}
return _instanceDispatcherCache;
}
set {
_instanceDispatcherCache = value;
}
}
[SuppressMessage("Microsoft.Security", "CA2119:SealMethodsThatSatisfyPrivateInterfaces", Justification = "This is overridden elsewhere in System.Web.Mvc")]
public virtual string UniqueId {
get {
return _uniqueId.Value;
}
}
private string CreateUniqueId() {
return DescriptorUtil.CreateUniqueId(GetType(), ControllerDescriptor, ActionName);
}
public abstract object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters);
internal static object ExtractParameterFromDictionary(ParameterInfo parameterInfo, IDictionary<string, object> parameters, MethodInfo methodInfo) {
object value;
if (!parameters.TryGetValue(parameterInfo.Name, out value)) {
// the key should always be present, even if the parameter value is null
string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedActionDescriptor_ParameterNotInDictionary,
parameterInfo.Name, parameterInfo.ParameterType, methodInfo, methodInfo.DeclaringType);
throw new ArgumentException(message, "parameters");
}
if (value == null && !TypeHelpers.TypeAllowsNullValue(parameterInfo.ParameterType)) {
// tried to pass a null value for a non-nullable parameter type
string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedActionDescriptor_ParameterCannotBeNull,
parameterInfo.Name, parameterInfo.ParameterType, methodInfo, methodInfo.DeclaringType);
throw new ArgumentException(message, "parameters");
}
if (value != null && !parameterInfo.ParameterType.IsInstanceOfType(value)) {
// value was supplied but is not of the proper type
string message = String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedActionDescriptor_ParameterValueHasWrongType,
parameterInfo.Name, methodInfo, methodInfo.DeclaringType, value.GetType(), parameterInfo.ParameterType);
throw new ArgumentException(message, "parameters");
}
return value;
}
internal static object ExtractParameterOrDefaultFromDictionary(ParameterInfo parameterInfo, IDictionary<string, object> parameters) {
Type parameterType = parameterInfo.ParameterType;
object value;
parameters.TryGetValue(parameterInfo.Name, out value);
// if wrong type, replace with default instance
if (parameterType.IsInstanceOfType(value)) {
return value;
}
else {
object defaultValue;
if (ParameterInfoUtil.TryGetDefaultValue(parameterInfo, out defaultValue)) {
return defaultValue;
}
else {
return TypeHelpers.GetDefaultValue(parameterType);
}
}
}
public virtual object[] GetCustomAttributes(bool inherit) {
return GetCustomAttributes(typeof(object), inherit);
}
public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) {
if (attributeType == null) {
throw new ArgumentNullException("attributeType");
}
return (object[])Array.CreateInstance(attributeType, 0);
}
internal virtual IEnumerable<FilterAttribute> GetFilterAttributes(bool useCache) {
return GetCustomAttributes(typeof(FilterAttribute), inherit: true).Cast<FilterAttribute>();
}
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete("Please call System.Web.Mvc.FilterProviders.Providers.GetFilters() now.", true)]
public virtual FilterInfo GetFilters() {
return new FilterInfo();
}
public abstract ParameterDescriptor[] GetParameters();
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "This method may perform non-trivial work.")]
public virtual ICollection<ActionSelector> GetSelectors() {
return _emptySelectors;
}
public virtual bool IsDefined(Type attributeType, bool inherit) {
if (attributeType == null) {
throw new ArgumentNullException("attributeType");
}
return false;
}
internal static string VerifyActionMethodIsCallable(MethodInfo methodInfo) {
// we can't call static methods
if (methodInfo.IsStatic) {
return String.Format(CultureInfo.CurrentCulture,
MvcResources.ReflectedActionDescriptor_CannotCallStaticMethod,
methodInfo,
methodInfo.ReflectedType.FullName);
}
// we can't call instance methods where the 'this' parameter is a type other than ControllerBase
if (!typeof(ControllerBase).IsAssignableFrom(methodInfo.ReflectedType)) {
return String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedActionDescriptor_CannotCallInstanceMethodOnNonControllerType,
methodInfo, methodInfo.ReflectedType.FullName);
}
// we can't call methods with open generic type parameters
if (methodInfo.ContainsGenericParameters) {
return String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedActionDescriptor_CannotCallOpenGenericMethods,
methodInfo, methodInfo.ReflectedType.FullName);
}
// we can't call methods with ref/out parameters
ParameterInfo[] parameterInfos = methodInfo.GetParameters();
foreach (ParameterInfo parameterInfo in parameterInfos) {
if (parameterInfo.IsOut || parameterInfo.ParameterType.IsByRef) {
return String.Format(CultureInfo.CurrentCulture, MvcResources.ReflectedActionDescriptor_CannotCallMethodsWithOutOrRefParameters,
methodInfo, methodInfo.ReflectedType.FullName, parameterInfo);
}
}
// we can call this method
return null;
}
}
}
|