用过反射的人都知道,调用一个方法很简单,但如何给一个【不知签名】的方法准备传入参数呢?
下面就来回答这个问题,请接着看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; }
要理解这段代码还要从前面的【查找Action的过程】说起,在那个阶段,可以获取一个Action的描述,具体在框架内部表示为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就已经反映了参数的类型,为什么不直接使用它呢?
答:因为【可空泛型】的原因。这个类型我们需要特殊的处理。
例如:如果某个参数是这样声明的: 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; }
如果某个参数的类型是一个自定义的类型,框架会先创建实例(调用无参的构造函数),然后给它的Property, Field赋值。
注意了:自定义的类型,一定要提供一个无参的构造函数。
为自定义类型的实例填充数据成员的代码如下:
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模式下忽略异常(防止恶意用户错误输入) } } }
在给自定义的数据类型实例加载数据前,需要先知道这个实例对象有哪些属性以及字段,这个过程的代码如下:
/// <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,Form读取所需的数据了。
【相关推荐】
1. 特别推荐:“php程序员工具箱”V0.1版本下载
2. ASP免费视频教程
Atas ialah kandungan terperinci .NET MyMVC框架如何给方法赋值的教程. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

C# memainkan peranan utama dalam ekosistem .NET dan merupakan bahasa pilihan untuk pemaju. 1) C# menyediakan kaedah pengaturcaraan yang cekap dan mudah digunakan, menggabungkan kelebihan C, C dan Java. 2) Melaksanakan melalui .NET Runtime (CLR) untuk memastikan operasi silang platform yang cekap. 3) C# menyokong asas untuk penggunaan lanjutan, seperti LINQ dan pengaturcaraan asynchronous. 4) Pengoptimuman dan amalan terbaik termasuk menggunakan StringBuilder dan pengaturcaraan asynchronous untuk meningkatkan prestasi dan penyelenggaraan.

C# adalah bahasa pengaturcaraan yang dikeluarkan oleh Microsoft pada tahun 2000, yang bertujuan untuk menggabungkan kuasa C dan kesederhanaan Java. 1.C# adalah bahasa pengaturcaraan yang berorientasikan objek, yang menyokong enkapsulasi, warisan dan polimorfisme. 2. Proses penyusunan C# menukarkan kod tersebut ke dalam bahasa pertengahan (IL), dan kemudian menyusunnya ke dalam pelaksanaan kod mesin dalam persekitaran runtime .NET (CLR). 3. Penggunaan asas C# termasuk pengisytiharan berubah -ubah, aliran kawalan dan definisi fungsi, sementara penggunaan lanjutan meliputi pengaturcaraan asynchronous, LINQ dan perwakilan, dan lain -lain. 5. Cadangan Pengoptimuman Prestasi termasuk penggunaan LINQ, pengaturcaraan asynchronous, dan meningkatkan kebolehbacaan kod.

C# adalah bahasa pengaturcaraan, manakala .NET adalah rangka kerja perisian. 1.C# dibangunkan oleh Microsoft dan sesuai untuk pembangunan pelbagai platform. 2..NET menyediakan perpustakaan kelas dan persekitaran runtime, dan menyokong pelbagai bahasa. Kedua -dua bekerja bersama untuk membina aplikasi moden.

C# .NET adalah platform pembangunan yang kuat yang menggabungkan kelebihan bahasa C# dan .NET. 1) Ia digunakan secara meluas dalam aplikasi perusahaan, pembangunan web, pembangunan permainan dan pembangunan aplikasi mudah alih. 2) Kod C# disusun menjadi bahasa pertengahan dan dilaksanakan oleh persekitaran runtime .NET, menyokong pengumpulan sampah, jenis keselamatan dan pertanyaan Linq. 3) Contoh penggunaan termasuk output konsol asas dan pertanyaan Linq maju. 4) Kesalahan biasa seperti rujukan kosong dan kesilapan penukaran jenis boleh diselesaikan melalui debuggers dan pembalakan. 5) Cadangan Pengoptimuman Prestasi termasuk pengaturcaraan dan pengoptimuman pertanyaan Linq. 6) Walaupun persaingan, C#.NET mengekalkan kedudukan pentingnya melalui inovasi berterusan.

Trend masa depan C#.NET terutamanya tertumpu pada tiga aspek: pengkomputeran awan, microservices, AI dan integrasi pembelajaran mesin, dan pembangunan silang platform. 1) Pengkomputeran awan dan microservices: C#.NET mengoptimumkan prestasi persekitaran awan melalui platform Azure dan menyokong pembinaan seni bina microservice yang cekap. 2) Integrasi AI dan Pembelajaran Mesin: Dengan bantuan Perpustakaan ML.NET, pemaju C# boleh membenamkan model pembelajaran mesin dalam aplikasi mereka untuk mempromosikan pembangunan aplikasi pintar. 3) Pembangunan silang platform: Melalui .Netcore dan .NET5, C# Aplikasi boleh dijalankan pada Windows, Linux dan MacOS, memperluaskan skop penempatan.

Perkembangan terkini dan amalan terbaik dalam pembangunan C#. NET termasuk: 1. Pengaturcaraan Asynchronous meningkatkan respons aplikasi, dan memudahkan kod yang tidak menyekat menggunakan async dan menunggu kata kunci; 2. LINQ menyediakan fungsi pertanyaan yang kuat, memanipulasi data dengan cekap melalui pelaksanaan dan pokok ekspresi yang tertunda; 3. Cadangan Pengoptimuman Prestasi termasuk menggunakan pengaturcaraan asynchronous, mengoptimumkan pertanyaan LINQ, memori pengurusan rasional, meningkatkan kebolehbacaan dan penyelenggaraan kod, dan ujian unit penulisan.

Bagaimana Membina Aplikasi Menggunakan .NET? Membina aplikasi menggunakan .NET boleh dicapai melalui langkah-langkah berikut: 1) Memahami asas-asas .NET, termasuk C# bahasa dan sokongan pembangunan silang platform; 2) mempelajari konsep teras seperti komponen dan prinsip kerja ekosistem .NET; 3) menguasai penggunaan asas dan lanjutan, dari aplikasi konsol mudah ke operasi WebAPIS dan pangkalan data yang kompleks; 4) terbiasa dengan kesilapan biasa dan teknik debugging, seperti konfigurasi dan isu sambungan pangkalan data; 5) Pengoptimuman prestasi aplikasi dan amalan terbaik, seperti pengaturcaraan dan caching asynchronous.

C# digunakan secara meluas dalam aplikasi peringkat perusahaan, pembangunan permainan, aplikasi mudah alih dan pembangunan web. 1) Dalam aplikasi peringkat perusahaan, C# sering digunakan untuk ASP.Netcore untuk membangunkan WebAPI. 2) Dalam pembangunan permainan, C# digabungkan dengan enjin Perpaduan untuk merealisasikan kawalan peranan dan fungsi lain. 3) C# menyokong polimorfisme dan pengaturcaraan tak segerak untuk meningkatkan fleksibiliti kod dan prestasi aplikasi.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

SublimeText3 versi Inggeris
Disyorkan: Versi Win, menyokong gesaan kod!

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

SublimeText3 Linux versi baharu
SublimeText3 Linux versi terkini

ZendStudio 13.5.1 Mac
Persekitaran pembangunan bersepadu PHP yang berkuasa
