Jeder, der Reflection verwendet hat, weiß, dass der Aufruf einer Methode sehr einfach ist, aber wie bereitet man eingehende Parameter für eine Methode mit [unbekannter Signatur] vor?
Beantworten wir diese Frage unten. Bitte schauen Sie sich den Implementierungsprozess von GetActionCallParameters an:
private static object[] GetActionCallParameters(HttpContext context, ActionDescription action) { if( action.Parameters == null || action.Parameters.Length == 0 ) return null; object[] parameters = new object[action.Parameters.Length]; for( int i = 0; i < action.Parameters.Length; i++ ) { ParameterInfo p = action.Parameters[i]; if( p.IsOut ) continue; if( p.ParameterType == typeof(NameValueCollection) ) { if( string.Compare(p.Name, "Form", StringComparison.OrdinalIgnoreCase) == 0 ) parameters[i] = context.Request.Form; else if( string.Compare(p.Name, "QueryString", StringComparison.OrdinalIgnoreCase) == 0 ) parameters[i] = context.Request.QueryString; else if( string.Compare(p.Name, "Headers", StringComparison.OrdinalIgnoreCase) == 0 ) parameters[i] = context.Request.Headers; else if( string.Compare(p.Name, "ServerVariables", StringComparison.OrdinalIgnoreCase) == 0 ) parameters[i] = context.Request.ServerVariables; } else{ Type paramterType = p.ParameterType.GetRealType(); // 如果参数是简单类型,则直接从HttpRequest中读取并赋值 if( paramterType.IsSimpleType() ) { object val = ModelHelper.GetValueByKeyAndTypeFrommRequest( context.Request, p.Name, paramterType, null); if( val != null ) parameters[i] = val; } else { // 自定义的类型。首先创建实例,然后给所有成员赋值。 // 注意:这里不支持嵌套类型的自定义类型。 object item = Activator.CreateInstance(paramterType); ModelHelper.FillModel(context.Request, item, p.Name); parameters[i] = item; } } } return parameters; }
Um diesen Code zu verstehen, müssen wir mit dem vorherigen [Prozess zum Finden von Aktionen] beginnen. Sie können die Beschreibung einer Aktion abrufen, die als ActionDescription-Typ innerhalb des Frameworks ausgedrückt wird:
internal sealed class ActionDescription : BaseDescription{ public ControllerDescription PageController; //为PageAction保留 public MethodInfo MethodInfo { get; private set; } public ActionAttribute Attr { get; private set; } public ParameterInfo[] Parameters { get; private set; } public bool HasReturn { get; private set; } public ActionDescription(MethodInfo m, ActionAttribute atrr) : base(m) { this.MethodInfo = m; this.Attr = atrr; this.Parameters = m.GetParameters(); this.HasReturn = m.ReturnType != ReflectionHelper.VoidType; } }
In der dritten Codezeile des Konstruktors , kann ich alle Parameter dieser Methode abrufen.
Dann kann ich die Definition jedes Parameters in der GetActionCallParameters-Methode schleifen und ihnen Werte zuweisen.
Dieser Code erklärt auch den Grund, warum wie bereits erwähnt nur vier Arten von NameValueCollection-Sammlungen unterstützt werden.
Hinweis: Wenn ich den Typ jedes Parameters erhalte, verwende ich die folgende Anweisung:
Type paramterType = p.ParameterType.GetRealType();
Tatsächlich spiegelt ParameterType bereits den Typ des Parameters wider. Warum nicht direkt? Was ist mit der Verwendung? Es?
Antwort: Wegen [Nullable-Generika]. Dieser Typ erfordert eine besondere Handhabung.
Zum Beispiel: Wenn ein Parameter wie folgt deklariert wird: int? id
Dann kann ich ihn nicht direkt in int konvertieren, selbst wenn er in QueryString enthalten ist. Um diesen Typ zu verwenden, müssen Sie ihn erhalten [tatsächlicher Typ].
GetRealType() ist eine Erweiterungsmethode, die speziell diese Funktion ausführt:
/// <summary> /// 得到一个实际的类型(排除Nullable类型的影响)。比如:int? 最后将得到int/// </summary> /// <param name="type"></param> /// <returns></returns>public static Type GetRealType(this Type type) { if( type.IsGenericType ) return Nullable.GetUnderlyingType(type) ?? type; else return type; }
Wenn der Typ eines Parameters ein benutzerdefinierter Typ ist, erstellt das Framework zunächst eine Instanz (Aufruf ohne). Parameterkonstruktor) und weisen Sie dann seiner Eigenschaft und seinem Feld Werte zu.
Hinweis: Benutzerdefinierte Typen müssen einen parameterlosen Konstruktor bereitstellen.
Der Code zum Ausfüllen von Datenelementen für eine Instanz eines benutzerdefinierten Typs lautet wie folgt:
internal static class ModelHelper{ public static readonly bool IsDebugMode; static ModelHelper() { CompilationSection configSection = ConfigurationManager.GetSection("system.web/compilation") as CompilationSection; if( configSection != null ) IsDebugMode = configSection.Debug; } /// <summary> /// 根据HttpRequest填充一个数据实体。 /// 这里不支持嵌套类型的数据实体,且要求各数据成员都是简单的数据类型。 /// </summary> /// <param name="request"></param> /// <param name="model"></param> public static void FillModel(HttpRequest request, object model, string paramName) { ModelDescripton descripton = ReflectionHelper.GetModelDescripton(model.GetType()); object val = null; foreach( DataMember field in descripton.Fields ) { // 这里的实现方式不支持嵌套类型的数据实体。 // 如果有这方面的需求,可以将这里改成递归的嵌套调用。 val = GetValueByKeyAndTypeFrommRequest( request, field.Name, field.Type.GetRealType(), paramName); if( val != null ) field.SetValue(model, val); } } /// <summary> /// 读取一个HTTP参数值。这里只读取QueryString以及Form /// </summary> /// <param name="request"></param> /// <param name="key"></param> /// <returns></returns> public static string GetHttpValue(HttpRequest request, string key) { string val = request.QueryString[key]; if( val == null ) val = request.Form[key]; return val; } public static object GetValueByKeyAndTypeFrommRequest( HttpRequest request, string key, Type type, string paramName) { // 不支持复杂类型 if( type.IsSimpleType() == false ) return null; string val = GetHttpValue(request, key); if( val == null ) { // 再试一次。有可能是多个自定义类型,Form表单元素采用变量名做为前缀。 if( string.IsNullOrEmpty(paramName) == false ) { val = GetHttpValue(request, paramName + "." + key); } if( val == null ) return null; } return SafeChangeType(val.Trim(), type); } public static object SafeChangeType(string value, Type conversionType) { if( conversionType == typeof(string) ) return value; if( value == null || value.Length == 0 ) // 空字符串根本不能做任何转换,所以直接返回null return null; try { // 为了简单,直接调用 .net framework中的方法。 // 如果转换失败,则会抛出异常。 return Convert.ChangeType(value, conversionType); } catch { if( IsDebugMode ) throw; // Debug 模式下抛异常 else return null; // Release模式下忽略异常(防止恶意用户错误输入) } } }
Bevor Sie Daten für eine benutzerdefinierte Datentypinstanz laden, müssen Sie die Instanz kennen ObjektWas sind die Attribute und Felder? Der Code für diesen Prozess lautet wie folgt:
/// <summary> /// 返回一个实体类型的描述信息(全部属性及字段)。/// </summary> /// <param name="type"></param> /// <returns></returns>public static ModelDescripton GetModelDescripton(Type type) { if( type == null ) throw new ArgumentNullException("type"); string key = type.FullName; ModelDescripton mm = (ModelDescripton)s_modelTable[key]; if( mm == null ) { List<DataMember> list = new List<DataMember>(); (from p in type.GetProperties(BindingFlags.Instance | BindingFlags.Public) select new PropertyMember(p)).ToList().ForEach(x=>list.Add(x)); (from f in type.GetFields(BindingFlags.Instance | BindingFlags.Public) select new FieldMember(f)).ToList().ForEach(x => list.Add(x)); mm = new ModelDescripton { Fields = list.ToArray() }; s_modelTable[key] = mm; } return mm; }
Nachdem alle Attribute und Feldbeschreibungsinformationen eines Typs abgerufen wurden, Sie können eine Schleife durchlaufen und zu QueryString und Form wechseln, um die erforderlichen Daten basierend auf den Namen dieser Datenelemente zu lesen.
【Verwandte Empfehlungen】
1. Besondere Empfehlung: Version V0.1 von „php Programmer Toolbox“ herunterladen
2. Kostenloses ASP-Video-Tutorial
3. Einstiegsbeispiel für .NET MVC
4. Detaillierte Erläuterung des Prozesses zum Suchen von Aktionen in der MyMVC-Box
5.Detaillierte Erläuterungen zum Prozess zum Ausführen von Aktionen in . NET MyMVC-Framework
6. Tutorial zur Verarbeitung von Rückgabewerten im .NET MyMVC-Framework
Das obige ist der detaillierte Inhalt vonTutorial zum Zuweisen von Werten zu Methoden im .NET MyMVC-Framework. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!