리플렉션을 사용해 본 사람이라면 메소드 호출이 매우 간단하다는 것을 알겠지만, [알 수 없는 서명]이 있는 메소드에 대한 수신 매개변수는 어떻게 준비합니까?
아래 질문에 답해 보겠습니다. GetActionCallParameters의 구현 프로세스를 살펴보세요.
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; }
이 코드를 이해하려면 이전 [액션 찾기 프로세스]부터 시작해야 합니다. get 액션에 대한 설명은 프레임워크 내에서 ActionDescription 유형으로 구체적으로 표현됩니다.
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; } }
생성자 코드의 세 번째 줄에서 다음을 얻을 수 있습니다. 모든 매개변수를 메소드로 지정합니다.
그런 다음 GetActionCallParameters 메서드에서 각 매개변수의 정의를 루프하고 여기에 값을 할당할 수 있습니다.
이 코드는 앞서 언급한 것처럼 4가지 유형의 NameValueCollection 컬렉션만 지원하는 이유도 설명합니다.
참고로 각 매개변수의 유형을 가져올 때 다음 명령문을 사용합니다.
Type paramterType = p.ParameterType.GetRealType();
사실 ParameterType은 이미 매개변수의 유형을 반영하고 있는데 직접 사용하면 어떨까요?
답변: [nullable 제네릭] 때문입니다. 이 유형에는 특별한 처리가 필요합니다.
예를 들어 매개변수가 int? id와 같이 선언된 경우
그러면 QueryString에 id와 같은 매개변수가 포함되어 있어도 이를 직접 int?로 변환할 수 없습니다. [실제 유형].
GetRealType()은 다음 기능을 구체적으로 수행하는 확장 메서드입니다.
/// <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; }
매개변수 유형이 사용자 정의 유형인 경우 프레임워크는 먼저 인스턴스를 생성합니다(매개변수 생성자 없이 호출). )을 선택한 다음 해당 속성과 필드에 값을 할당합니다.
참고: 사용자 정의 유형은 매개변수가 없는 생성자를 제공해야 합니다.
사용자 정의 유형 인스턴스의 데이터 멤버를 채우는 코드는 다음과 같습니다.
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模式下忽略异常(防止恶意用户错误输入) } } }
사용자 정의 데이터 유형 인스턴스에 대한 데이터를 로드하기 전에 인스턴스를 알아야 합니다 object 속성과 필드는 무엇입니까? 이 프로세스의 코드는 다음과 같습니다.
/// <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; }
유형의 모든 속성과 필드 설명 정보를 얻은 후 루프를 수행할 수 있습니다. 이러한 데이터 멤버의 이름은 QueryString으로 이동하고 양식은 필요한 데이터를 읽습니다.
【관련 추천사항】
1. 특별 추천: "php Programmer Toolbox" V0.1 버전 다운로드
4. MyMVC 박스에서 Action을 찾는 과정에 대한 자세한 설명
5. .NET에서 Action을 실행하는 과정에 대한 자세한 설명 MyMVC 프레임워크
6. .NET MyMVC 프레임워크를 사용하여 반환 값을 처리하는 방법에 대한 튜토리얼
위 내용은 .NET MyMVC 프레임워크의 메서드에 값을 할당하는 방법에 대한 자습서의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!