Runtime那些从事

1   概述

Runtime

于读书本篇博文时,建议做上篇博文:详解ASP.NET MVC
路由  一起看,效果说不定会见又好把。  

前言

于字面意思看,就是运行时。但是这运行时究竟什么意思?可以拿它了解成:不是于编译期也非是当链接期,而是以运作时。那到底以运行期间举行了啊也?按照苹果官方的传道,就是拿有裁决(方法的调用,类的增长相当)推迟,推迟到运行期间。只要出或,程序即使得动态的完结任务,而未是咱们当编译期已经控制它而做到什么任务。这便表示了OC不仅仅要编译器,还索要一个运作时之网来支撑。

Controller(控制器)在ASP.NET
MVC中承受控制所有客户端和劳务端的并行,并且负责协调Model与View之间数据传递,是ASP.NET
MVC框架核心。Controller为ASP.NET
MVC框架的核心组成部分,其利害攸关承担处理浏览器请求,并操纵响应什么内容被浏览器,但连无背控制内容应怎样展示(View的职责)。

目录

连通下去便对Runtime做一个网的牵线,主要内容囊括:

  1. 简介
  2. 关联到之数据结构
  3. runtime.h解析
  4. 何以可以接触到RunTime?
  5. 消息
  6. 动态信息分析
  7. 信转发
  8. Runtime的应用状况

文章内容包括:Controller概述、Controller类别和章程、Controller运行过程、Controller方法类别、ViewData\ViewBag\TempData分析、ActionResult解说、Controller定义和参考文献,剩下有关Controller其他内容以本篇文章被不提,如Controller激活机制(Controller类型解析、Controller类型缓存、Controller的放及对话状态作为控制相当)、ControllerFactory、ControllerBuilder等,除此之外,文中有些过度涉及到脚的情,考虑篇幅等因素,只是简短提及了一晃,并未做透剖析,根据后期情况,会酌情考虑是不是更写一首彻底深入之根Controller的。

1.简介

依据前言,你曾经了解了Runtime大概是个什么坏,在OC发展进程中,它至关重要出少数独版本:Legacy和Modern。Legacy版本采用的是OC1.0版本;Modern版本采用的OC2.0本子,而且相比Legacy也补充加了有新特色。最鲜明的区分在于:

  • 在legacy版本,如果你改变了仿佛的布局,那么你必还编译继承自其的切近。
  • 于modern版本,如果你改变了接近的布局,你不要还编写继承自她的好像。

2   Controller类别和措施

平台

iPhone的应用程序以及OS X
v10.5本的64各类机器使用的是modern版本的runtime。
其余(OS X桌面应用32员程序)使用的是legacy版本的runtime。

Controller本身就是一个像样(Class),该类型有诸多办法(Method),这些点子中假如是公然方法(public
method)就会见吃视为是一个动作(Action)或动作方法(Action
Method),只要动作有,就可以经过该动作方法接收客户端传来的渴求及控制响应的查验(View)

2.关乎到的数据结构

这边要介绍一下当runtime.h里面涉及到之有数据结构。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace MVCControllerDemo.Controllers
 8 {
 9     public class ControllerDemoController : Controller
10     {
11         //
12         // GET: /ControllerDemo/
13 
14         [HttpGet]
15         public ActionResult Index()
16         {
17             return View();
18         }
19     }
20 }
Ivar

Ivar从字面意思来讲,它就是是象征的实例变量,它为是一个结构体指针,包含了变量的称呼、类型、偏移量以及所占用空间。

自打如齐代码可以总结发生Controller应拥有如下几个着力尺度:

SEL

选择器,每个方法还起谈得来之选择器,其实就是方法的名字,但是不仅仅是方的名,在objc.h中,我们好观看它的定义:

/// An opaque type that represents a method selector.一个不透明类型,用来代表一个方法选择器
typedef struct objc_selector *SEL;

由于定义可知它是一个objc_selector的结构体指针,尴尬的是于runtime源码中并没找到该结构体。猜想其里面应该就是一个char
的字符串。
你可以使:

 NSLog(@"%s",@selector(description));  //%s用来输出一个字符串

打印出description。
在这里你可以将她知道成一个选择器,可以标识某个方法。

(1)Controller必须为公开类别;

IMP

她是一个函数指针,指向方法的落实,在objc.h里面它的定义是这么的:

/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

(2)Controller名称必须盖Controller结尾;

id

id是一个咱常使用的种类,可用于作为类型转换的中介者。它相仿于Java里面的Object,可以变为任何的数据类型。它以objc.h里面是这样定义的:

/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;

她实际上是一个objc _
object的结构体指针,而以后将提到的Class其实是只objc _
class的指针,而objc _ class是延续自objc _o
bject的,因此可以互相转换,这也是干什么id可以转换为其它任何的数据类型的缘故。

(3)必须继续自ASP.NET
MVC内打的Controller类别,或促成IController自定义类别;

Method

道,它其实是一个objc_method的结构体指针,其定义如下:

/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;

struct objc_method {
    SEL _Nonnull method_name                                 OBJC2_UNAVAILABLE;
    char * _Nullable method_types                            OBJC2_UNAVAILABLE;
    IMP _Nonnull method_imp                                  OBJC2_UNAVAILABLE;
}  

以此就是比较好掌握了,该结构体包含了点子的名目(SEL),方法的品类以及艺术的IMP。

(4)所以动作方法必须为公开办法,任何非公开的计要宣称也private或protected的艺术都未会见吃视为一个动作方法;

Class

她是一个objc_class的结构体指针,在runtime.h中的定义如下:

/// An opaque type that represents an Objective-C class.一个不透明类型,代表OC的类
typedef struct objc_class *Class;

struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class _Nullable super_class                              OBJC2_UNAVAILABLE;
    const char * _Nonnull name                               OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list * _Nullable ivars                  OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable * _Nullable methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache * _Nonnull cache                       OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

欠结构体中列片介绍如下:

  • isa:是一个Class类型的指针,每个对象的实例都生isa指针,他针对性对象的类。而Class里面也发出只isa指针,它对meteClass(元类),元类保存了近乎措施的列表。
  • name:对象的名
  • version:类的版号,必须是0
  • info:供运行中利用的各标识
  • instance_size:该类的实例大小
  • ivars:成员变量数组,包含了此类包含的分子变量
  • methodLists:包含方法的数组列表,也是一个结构体,该结构体里面还蕴含了一个obsolete的指针,表示废弃的办法的列表
  • cache:缓存。这个比较复杂,在末端会涉及,这里先忽略。
  • protocols:协议列表,也是一个数组

要是于objc-runtime-new.h中,你晤面发现这么的概念(在runtime中连无完全暴露objc_class的实现):

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags

    class_rw_t *data() { 
        return bits.data();
    }
    //其他的省略

其实objc _ class继承自objc _
object。所以这也证明了为什么id能够转移为其它的品类。

3  Controller的运作过程

3.runtime.h解析

咱俩事先看一下在usr/include/objc/runtime.h,这个是其它一个工程还好一直找到的,它是SDK的平局部。主要定义了以下内容:

  1. 概念了一些档,例如Method/Ivar/Category等,还有一对结构体。
  2. 函数。函数里面有分了几乎充分接近:
    • 有关目标实例的办法,例如object _ getClass、object _
      setClass以及object _ getIvar等。这些函数大多以object开头
      用来博取属性或者对目标进行操作。
    • 得到接近定义之法,例如objc _ getClass/objc _
      getMetaClass等,这些艺术更多的是得到Class或者以Class级别上开展操作。
      多以objc开头
    • 同类系的方式。例如class _ getName/class _
      isMetaClass等,这些又多之是取Class的有性能。比如该类的习性列表、方法列表、协议列表等。传参大多也Class。
      多以class开头
    • 实例化类的一部分法。例如class _
      createInstance方法,就是一定给平常之alloc init。
    • 补偿加类的艺术。例如你得下这些点子冬天底挂号一个像样。使用objc
      _ allocateClassPair创建一个新类,使用 objc _
      registerClassPair对类进行挂号
    • 等等。。。
  3. 此外即使是局部丢掉的主意与花色。

当Controller被MvcHandler选中之后,下一样步就是是由此ActionInvoker选定合适的Action来运转。在Controllr中的每个Action可以定义0到大半只参数,ActionInvoker会依据这的RouteValue与客户端传来的数额准备好但传唱Action参数的多少,最后正式调用Controller中受选中的不行Action方法。参数传入的习性都是通过一致栽叫做模型绑定(Model
Binding)机制,从RequestContext取得数据,并拿数据对应或传播方法的参数中,让Action不用还比如前ASP或ASP.NET
Web
Forms中时常应用的Request.Fomr或Request.QueryString等目标来获取客户端的数码,通过从定义之模子绑定,甚至好叫您对诺除去Request.Form或Request.QueryString以外的数来,例如:HTTP
Cookies、HTTP Headers等等。

4. 什么好触发到RunTime?

生三种植不同的法子得以让OC编程和runtime系统相互。

Action运行完后的扭曲传值通常是ActionResult类别或其衍生类别(Derived
Class),事实上,ActionResult是一个抽象类,如ViewResult用来回传一个View、RedirectResult用来用网页又定向、Content回传文字内容、FileResult回传二进制文档等,这些均是继承ActionResult。MvcHandler从Controller得到ActionResult之后,就见面开始运行ActionResult提供的ExecuteResult方法,并拿运行结果应到客户端,这时Controller的职责就是完。

OC源代码

多数气象下,我们形容的OC代码,其实它们底层的实现即是runtime。runtime系统于不动声色自动帮助我们处理了操作。例如我们编译一个类,编译器器会创建一个结构体,然后这个结构体会从接近中捕获信息,包括方法、属性、Protocol等。

上述也Controller的基本运行过程。Controller于运行时还来平等叠所谓的动作过滤器机制,分为如下四种基本型:

NSObject的片智

当Foundation框架内来个NSObject.h,在usr/include/objc里面为时有发生一个NSObject.h。而我辈平素应用的切近的基类是/usr/include/objc里面的这NSObject.h,Foundation里面的NSObject.h只是NSObject的一个Category。所以这里我们还关心一下/usr/include/objc里面的NSObject.h。
出于大部分目标都是NSObject的子类,所以当NSObject.h里面定义之方法还好下。
当这些方法中,有部分办法能查询runtime系统的消息,例如:

- (BOOL)isKindOfClass:(Class)aClass;   //用来检测一个对象是否是某各类的实例对象,aClass也有可能是父类,同样可以检测出来。
- (BOOL)isMemberOfClass:(Class)aClass;   //而该方法只能检测一个对象是否是某各类的实例对象。但如果aClass不能为该类的父类,如果是父类则该方法返回NO

- (BOOL)respondsToSelector:(SEL)aSelector;

- (BOOL)conformsToProtocol:(Protocol *)aProtocol;

- (IMP)methodForSelector:(SEL)aSelector;

此间用代码对isKindOfClass和isMemberOfClass做只简易介绍:

//stu是Student的实例对象,Student的父类为Person,Person的父类为NSObject。
[stu isKindOfClass:[Student class]];    //YES
[stu isKindOfClass:[Person class]];    //YES
[stu isKindOfClass:[NSObject class]];   //YES

[stu isMemberOfClass:[Student class]];    //YES
[stu isMemberOfClass:[Person class]];    //NO
[stu isMemberOfClass:[NSObject class]];   //NO

咱俩可当objc源代码中之NSObject.mm中视相应的实现:

+ (BOOL)isMemberOfClass:(Class)cls {
    return object_getClass((id)self) == cls;
}
- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}
+ (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = object_getClass((id)self); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

于具体落实可知,为什么isKindOfClass能够检测出superclass。另外,在NSObject.h中,并无观看个别独办法的类似方式声明,但是在实现中也含有了看似方式的贯彻。这里发生个谜:为什么没对外宣称的有限独八九不离十措施还得以以表调用呢?(比如自己得直接利用[Student
isMemberOfClass:[NSObject class]])

这边还为此到了class方法,这个点子声明如下:

+ (Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead");

- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");

+ (Class)class {   //返回当前的self
    return self;
}

- (Class)class {
    return object_getClass(self);
}

此最主要之是知道self究竟代表在啊:

  1. 当self为实例对象的时节,[self class] 和
    object_getClass(self)是当价格的。object_getClass([self
    class])得到的凡元类。
  2. 当self为类对象的时光,[self
    class]回去的是本人,还是self。object_getClass(self)
    与object_getClass([self class])等价格。拿到之是元类。

(1)授权过滤器(Authorization
Filters);

Runtime函数

runtime系统实际就算是一个动态共享的Library,它是出于在/usr/include/objc目录的集体接口中的函数和数据结构组成。
葡京娱乐注册 1

(2)动作过滤器(Action Filters);

5. 消息

在Objective-C中,消息直到运行时才用其与信息的落实绑定,编译器会将

[receiver message];

转换成

objc_msgSend(receiver,selector);   //1

objc_msgSend(receiver,selector,arg1,arg2,...);  //2

要含有参数,那么就是见面履2艺术。其实不外乎拖欠法,还有以下几单艺术:

objc_msgSend_stret    
objc_msgSendSuper
objc_msgSendSuper_stret

当想一个目标的父类发送message时,会利用

objc_msgSendSuper

若果艺术的返回值是一个结构体,那么就见面用

objc_msgSend_stret
objc_msgSendSuper_stret

这里我们可以打开objc源码,然后你见面发觉中来差不多独.s文件:
葡京娱乐注册 2
这边用有objc-msg-类的异文件,我猜测应该是针对性不同的CPU指令集(指令不雷同)做了各自处理。因为这些.s文件名称中隐含的凡见仁见智的arm指令集。而且打开.s文件你晤面发现内部的落实是汇编语言,所以苹果为效率要蛮拼底,直接用汇编语言实现。
内部虽可知找到objc _ msgSend的实现(objc-msg-i386.s中):
葡京娱乐注册 3
尽管如此对汇编了解不是太多,但是这文件被的注释很详细,从注释可以视objc_msgSend方法的执行进程:

  1. 预先加载receiver和selector到寄存器,然后判断receiver是否为空,如果也空,则函数执行完毕;
  2. 若是receiver不为空,开始寻找缓存,查看方缓存列表中是不是有改selector,如果来则实施;
  3. 如无缓存,则寻方法列表,如果当术列表中找到,则超越反至实际的imp实现。没有则实行完毕。

(3)结果过滤器(Result Filters);

利用了藏参数

每当殡葬一个音之时光,会叫编译成objc_msgSend,此时该信息之参数将见面传出objc_msgSend方法中。除此之外,还会包含两个暗藏的参数:

  1. receiver
  2. method的selector

马上点儿独参数在上头也出涉及。其中的receiver就是信息之发送方,而selector就是选择器,也堪直接用
_ cmd来指代( _
cmd用来代表时所于方的SEL)。之所以隐蔽是坐以术声明遭连从未于强烈声明,在源代码中我们照例可引用它。

(4)例外过滤器(Exception Fiters);

抱方式地址

我们每次发送信息都见面走objc_msgSend()方法,那么来无发生艺术规避消息绑定直接获得方式的地方并调用方法吧?答案当然是有。我们地方简单介绍了IMP,其实我们得以使NSObject的

- (IMP)methodForSelector:(SEL)aSelector;

法,通过该方式得到IMP,然后调用该办法。但是避开消息绑定而直接调用的行使并无普遍,但是如果您一旦再三循环调用的话,直接获得方式地址并调用不失为一个节省操作。看下面的代码:

 void (*setter)(id,SEL,BOOL);
    setter = (void(*)(id,SEL,BOOL))[stu2 methodForSelector:@selector(learning)];
    NSDate *startDate = [NSDate date];
    for (int i = 0;i<100000;i++) {
        setter(stu2,@selector(learning),YES);
    }
    double deltaTime = [[NSDate date] timeIntervalSinceDate:startDate];
    NSLog(@"----%f",deltaTime);

    NSDate *startDate1 = [NSDate date];
    for (int i = 0;i<100000;i++) {
        [stu2 learning];
    }
    double deltaTime1 = [[NSDate date] timeIntervalSinceDate:startDate1];
    NSLog(@"----%f",deltaTime1);

公可以自动飞一下,看一下时刻差异。你会意识:获取方式地址直接调用更省时间,但请留心利用状况。

4  控制器方法类别

6. 动态信息分析

此地介绍一下设动态地提供方的贯彻。

4.1 动作方法选定器

动态方法分析

在支付进程被,你或许想动态地提供一个术的兑现。比如我们针对一个对象声明了一个性质,然后我们利用了
@dynamic 标识符:

@dynamic propertyName;

拖欠标识符的目的就是是告诉编译器:和是特性相关的getter和setter方法会动态地提供(当然你为堪直接手动在代码里面实现)。这个时候你尽管见面就此到NSObject.h里面的点滴单艺术

+ (BOOL)resolveClassMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);
+ (BOOL)resolveInstanceMethod:(SEL)sel OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0, 2.0);

来供方式的兑现。
事实上OC方法就是一个简约的C函数,它至少含有了零星个参数self和 _
cmd,你可以自己声明一个计:

void dynamicMethodIMP(id self, SEL _cmd) {
    //这里是方法的具体实现
}

这儿咱们好以宣称属性的切近吃贯彻者提到的蝇头独道(一个凡是解析类方法,一个凡是分析实例方法),例如我于Person里面这么勾画:

@dynamic address;   //也就意味着我们需要手动/动态实现该属性的getter和setter方法。

您晤面发现当我们运行下面的代码时,程序会crash:

   Person *zhangsan = [[Person alloc] init];
    zhangsan.address = @"he nan xinxiang ";

    NSLog(@"%@",zhangsan.address);

//    crash reason
// -[Person setAddress:]: unrecognized selector sent to instance 0x1d4449630

此处大概的做一个动态方法分析:

void setter(id self,SEL _cmd) {
    NSLog(@"set address");
}

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    NSString *selStr = NSStringFromSelector(sel);
    if ([selStr hasPrefix:@"set"]) {
        class_addMethod([self class], sel, (IMP)setter, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

于是我们需要协调失去贯彻setAddress:
方法。(这里判断用hasPrefix不太可靠,开发者可以活动根据要求调整)。转发信息(下面会讲到)和动态解析是正交的。也就是说一个class有会再消息转发机制面前失去动态解析这个方,也足以将动态解析方法返回NO,然后以操作转发给消息转发。

 当通过ActionInvoker选定Controller内的明方法时,ASP.NET
MVC还发另一个表征称为”动作方法选定器(Action Method
Selector)”,该选定器可以套用在动作方法及,以便ActionInvoker”选定”适当的Action。

动态加载

OC编程也允许我们以程序运行的上动态去创造和链接一个近似还是分类。这些创造的类或分类将会晤以及运行app前创办的切近一样,没有异样。
动态加载在支付之过程被得以开多事情,例如系统设置中的异模块就是动态加载的。
于Cocoa环境中,最经典的就是是Xcode,它可装不同的插件,这个呢是动态加载的计实现的。

 (1)NonAction属性

7. 信转发

发送一个音于目标,如果目标非克处理,那么即便会发生错误。然而,在生错误之前,runtime
系统会让目标第二糟会错过处理该消息。这里详细已经于深入浅出理解消息的传递和转账文章被举行了介绍,这里就是不再介绍了。

一经控制器某个方法特性也NonAction,即使该Action方法是“公开方法”,也会见告知ActionInvoker不要选定这个Action来运作。主要用途:a.保护Controller中之一定公开办法毫无发布到Web上;b.功能尚未开发到位将进行部署,暂时无思将这办法去。

8. Runtime底应用状况

Runtime的采用几乎无处不在,OC本身就是是一样派系运行时语言,Class的变型、方法的调用等等,都是Runtime。另外,我们可用Runtime做一些其它的事务。

1 [NonAction]
2  public ActionResult  Index()
3   {
4        return View();
5   }
字典转换Model

平时我们由服务端拿到之多少是json字符串,我们可以将该转移成成NSDictionary,然后通过runtime中之一对办法做一个转换:
事先以到model的具备属性或者成员变量,然后拿其及字典中之key做映射,然后经KVC对性赋值即可。更多但参见class_copyIvarList方法赢得实例变量问题抓住的想受到之例子。

啊不过拿public改也private,达到保障的效益。

热更新(JSPatch的实现)

JSPatch能到位JS调用和改写OC方法的根本原因就是OC是动态语言,OC上的有所方的调用/类的生成都通过OC
Runtime在运转时进行,我们得依据名称/方法名反射得到相应的类似以及方。例如

Class class = NSClassFromString("UIViewController");
id viewController = [[class alloc] init];
SEL selector = NSSelectorFromString("viewDidLoad");
[viewController performSelector:selector];

呢正是鉴于此,才促成了热更新。

1 private ActionResult  Index()
2  {
3        return View();
4   }
给Category添加属性

俺们可以runtime在Category中叫类添加属性,这个至关重要采用了点儿个runtime钟的办法:

OBJC_EXPORT void
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,id _Nullable value, objc_AssociationPolicy policy);

OBJC_EXPORT id _Nullable
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key);

具体运用可参见:吃分类(Category)添加属性。

(2)HTTP动词限定属性

Method Swizzling

其是改变一个曾是的selector的实现之技巧,比如您想拿viewDidload方法替换为咱于定义之方法,给系统的法子上加有索要的效益,来贯彻某些需求。比如您想跟每个ViewController展示的次数,你可以用该技能再写ViewDidAppear方法,然后开片投机之处理。可以瞻仰Method
Swizzling里头的讲授。

 HttpGet、HttpPost、HttpDelete、HttpPut、HttpHead、HttpOptions、HttpPatch属性(Attributes)都是动作方法选定器的相同局部。如下例子讲解HttpGet属性,即意味着只有当客户端浏览器发送HTTP
GET要求时,ActionInvoker才会选定到这个Action:

总结

Objective-c本身便是同等宗冬天语言,所以了解runtime有助于我们更为入木三分地了解其中间的落实原理。也会见把有近似非常不便之题材经过runtime很快解决。

1 [HttpGet]
2  public ActionResult  Index()
3  {
4       return View();
5  }

参照链接:

1.Objective-C Runtime Programming
Guide
2.Objective-C
Runtime
3.objc4
4.浅显理解消息的传递和转发
5.class_copyIvarList方法获得实例变量问题抓住的想
6.JSPatch
实现原理详解
7.叫分类(Category)添加属性
8.Method Swizzling

转载请注明来源:http://www.cnblogs.com/zhanggui/p/8243316.html

若将[HttpGet]改为[HttpPost],浏览器将搜不交葡京娱乐注册资源。

1 [HttPost]
2 public ActionResult  Index()
3 {
4        return View();
5 }

葡京娱乐注册 4

 注释:如果动作方法及并未嵌套任何限制属性,那么客户端浏览器发送任意HTTP动词都见面自行选定到相应之Action。

 当需要展示接收窗体信息时,可以创建两独同名的Action,分别就此[HttpGet](显示窗体HTML)和[HttpPost](接收窗体输出的值)属性来限制。

 1        [HttpGet]
 2         public ActionResult  Index()
 3         {
 4              return View();
 5         }
 6 
 7         [HttpGet]
 8         public ActionResult Create()
 9         {
10             return View();
11         }
12 
13 
14         [HttpPost]
15         public ActionResult Create(FormCollection fc)
16         {
17             //UpdateToDB(fc);
18             return RedirectToAction("Index");
19         }

4.2 操作过滤器

一个操作方法一旦为入选就会见就施行,并且只要它回到一个结果,返回的结果为会见随着履行,ASP.NET
MVC 5提供五种植方法,分别列于如下:

  • 便身份验证
  • 授权
  • 操作前后处理
  • 结果前后处理
  • 错误处理。

除外,还有另外一栽过滤器,即再写过滤器,它同意为大局或控制器的默认集合制定例外情况。

操作过滤器可以作为直接采用于操作方法或控制器类的风味来修,或当作以大局过滤器列表中登记的独自接近来编排。如果打算用修的操作过滤器作为特色来以,那么其必须连续自FilterAttribute或其的另外子类,如ActionFilterAttribute。不当作特色应用的大局操作过滤器没有针对性是基类的求。无论采取哪个路由,操作过滤器支持的过滤活动且是因为实现之接口决定。

5  Controller动作结果

5.1
控制器动作结果类型(ActionResult)  

寻常,在概念一个办法时,我们常规性地冲章程是否来返回值归结为来返回值和无返回值两大类,控制器的真相是相仿,控制器的action本质是道,如果以数学集合来定义,那么控制器是近似的一个子集,同理,控制器action是方法的一个子集,因此,在研控制器和控制器action时,我们是好才用研究类和法的相似思维的。

控制器动作(具体的action)返回的结果称控制器动作结果,动作结果是控制器返回给浏览器请求的内容。ASP.NET
MVC框架支持六种标准项目的动作结果。

 (1)继承ActionResult的动作结果

 葡京娱乐注册 5

(2)继承关系

葡京娱乐注册 6

 (3)例子

eg1:ViewResult

葡京娱乐注册 7葡京娱乐注册 8

 1 //方法1: ViewResult作为返回类型
 2 public ViewResult Index()
 3         {
 4             return View();
 5         }
 6 
 7 
 8 
 9  //方法二: ViewResultBase作为返回类型
10 public ViewResultBase Index()
11         {
12             return View();
13         }
14 
15 //方法三: ActionResult作为返回类型
16 public ActionResult Index()
17         {
18             return View();
19         }

View
Code

eg2:EmptyResult

葡京娱乐注册 9葡京娱乐注册 10

1   // GET: /ControllerDemo/
2         public EmptyResult  Index()
3         {
4             return null;
5         }

View
Code

eg3:ContentResult

葡京娱乐注册 11葡京娱乐注册 12

 1 //方法1:ContentResult作为返回类型
 2 public ContentResult Index()
 3         {
 4              return Content("Hello World");
 5         }
 6 
 7 
 8 //方法2:ActionResult作为返回类型
 9 public ActionResult Index()
10         {
11             return Content("Hello World");
12         }

View
Code

 eg4:JsonResult

葡京娱乐注册 13葡京娱乐注册 14

 1 public JsonResult jsonResult()
 2  2         {
 3  3            TechInfoCompanay jsonCompany=new TechInfoCompanay(){id="S001",CompanyName="信息科技有限公司"};
 4  5             return Json(jsonCompany,JsonRequestBehavior.AllowGet);
 5  6          }
 6  7 
 7  8 
 8  9  //定义一个公司类
 9 10     public class TechInfoCompanay
10 11     {
11 12         public string id { set; get; }
12 13         public string CompanyName { set; get; }
13 14     }

View
Code

eg5:RedirectResult

葡京娱乐注册 15葡京娱乐注册 16

 1 //方法1:RedirectResult作返回类型
 2 public RedirectResult redirectResult()
 3         {
 4             return Redirect("https://www.google.com.hk/");//具体的URL
 5         }
 6 
 7 //方法1: ActionResult作返回类型
 8 public  ActionResult redirectResult()
 9         {
10             return Redirect("https://www.google.com.hk/");//具体的URL
11         }

View
Code

eg6:RedirectToRouteResult

葡京娱乐注册 17葡京娱乐注册 18

1  public ActionResult redirectResult()
2         {
3             return Redirect("https://www.google.com.hk/");//具体的URL
4         }
5 
6         public RedirectToRouteResult redirectToRouteResult()
7         {
8             return RedirectToAction("Index");
9         }

View
Code

5.2一般方法

(1)如下只是让起主意样式,不举行具体代码。

 1 //无返回类型
 2 public  void  functionName(形参)
 3 {
 4      //to add your content
 5 }
 6 
 7 //有返回类型
 8 public  返回类型  functionName(形参)
 9 {
10      //to add your content
11     return   与方法返回类型相匹配的结果;
12 }

(2)例子

eg:举个自定义返回string的法

RouteConfig.cs

葡京娱乐注册 19葡京娱乐注册 20

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using System.Web.Routing;
 7 
 8 namespace MVCControllerDemo
 9 {
10     public class RouteConfig
11     {
12         public static void RegisterRoutes(RouteCollection routes)
13         {
14             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
15 
16             routes.MapRoute(
17                 name: "Default",
18                 url: "{controller}/{action}/{id}",
19                 defaults: new { Controller = "ControllerDemo", action = "Index", id = UrlParameter.Optional }
20             );
21         }
22     }
23 }

View
Code

ControllerDemoController.action

葡京娱乐注册 21葡京娱乐注册 22

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace MVCControllerDemo.Controllers
 8 {
 9     public class ControllerDemoController : Controller
10     {
11 
12         public string GeneralFunction()
13         {
14             return "自定义一般方法";
15         }
16     }
17 }

View
Code

测试结果

葡京娱乐注册 23

6  ViewBag、ViewData和TempData概述

6.1
三者在MVC框架里之概念

当MVC框架中,System.Web.Mvc命名空间下的ControllerBase中,对ViewBag、ViewData以及TempData三独特性的概念如下

ViewBag

葡京娱乐注册 24葡京娱乐注册 25

 1  [Dynamic]
 2         public object ViewBag
 3         {
 4             [return: Dynamic]
 5             get
 6             {
 7                 Func<ViewDataDictionary> viewDataThunk = null;
 8                 if (this._dynamicViewDataDictionary == null)
 9                 {
10                     if (viewDataThunk == null)
11                     {
12                         viewDataThunk = () => this.ViewData;
13                     }
14                     this._dynamicViewDataDictionary = new DynamicViewDataDictionary(viewDataThunk);
15                 }
16                 return this._dynamicViewDataDictionary;
17             }
18         }

View
Code

ViewData

葡京娱乐注册 26葡京娱乐注册 27

 1 public ViewDataDictionary ViewData
 2         {
 3             get
 4             {
 5                 if (this._viewDataDictionary == null)
 6                 {
 7                     this._viewDataDictionary = new ViewDataDictionary();
 8                 }
 9                 return this._viewDataDictionary;
10             }
11             set
12             {
13                 this._viewDataDictionary = value;
14             }
15         }

View
Code

TempData

葡京娱乐注册 28葡京娱乐注册 29

 1 public TempDataDictionary TempData
 2         {
 3             get
 4             {
 5                 if ((this.ControllerContext != null) && this.ControllerContext.IsChildAction)
 6                 {
 7                     return this.ControllerContext.ParentActionViewContext.TempData;
 8                 }
 9                 if (this._tempDataDictionary == null)
10                 {
11                     this._tempDataDictionary = new TempDataDictionary();
12                 }
13                 return this._tempDataDictionary;
14             }
15             set
16             {
17                 this._tempDataDictionary = value;
18             }
19         }

View
Code

6.2 三者比较

(1)ViewData和TempData属性均归一个有所字典结构的数码容器,即字典类型的key/Value对,ViewBag为Dynamic类型。

三者方法签名也:

1  public TempDataDictionary TempData { get; set; }
2  public ViewDataDictionary ViewData { get; set; }
3  public object ViewBag { [return: Dynamic] get; }

(2)TempData存储临时数据,并且安装的变量在为第一赖读取后会见吃移除,即TempData设置的变量只能于读取一不良。(why?)

(3)ViewBag和ViewData属性是一模一样卖数据的不等表现形式,二者的不同之处在于前者是一个动态目标,可以啊该指定任意属性(动态性将作为数据字典的Key)。

(4)三者均是容器,即能储存常量,变量,也克积存集合。

7  ActionResult解说

 在ASP.NET MVC框架中,对ActionResult定义如下:

 1 // Generated by .NET Reflector from C:\Users\WJM\documents\visual studio 2013\Projects\DEMOMVC\packages\Microsoft.AspNet.Mvc.5.0.0\lib\net45\System.Web.Mvc.dll
 2 namespace System.Web.Mvc
 3 {
 4     using System;
 5     
 6     public abstract class ActionResult
 7     {
 8         protected ActionResult()
 9         {
10         }
11         
12         public abstract void ExecuteResult(ControllerContext context);
13     }
14 }

 ActionResult是Action运行后底回传型别,但是当Action回传ActionResult的时段,其实并无包含这个ActionResult(例如ViewResult)的周转结果,而是包含运行此ActionResult时所要的数目,当MvcHandler从Controller取得ActionResult之后才会错过运转出ActionResult的结果。在ActionResult抽象类中不过定义了一个ExecuteResult()方法。

ASP.NET 定义了以下几种植衍生型别。

葡京娱乐注册 30

8  控制器定义

诚如地,在定义Controller时,采用简单种办法,即实现IController和累Controller。

8.1 实现IController

RouteConfig.cs

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 using System.Web.Routing;
 7 
 8 namespace MVCControllerDemo
 9 {
10     public class RouteConfig
11     {
12         public static void RegisterRoutes(RouteCollection routes)
13         {
14             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
15 
16             routes.MapRoute(
17                 name: "Default",
18                 url: "{controller}/{action}/{id}",
19                 defaults: new { Controller = "ControllerDemo", action = "Index", id = UrlParameter.Optional }
20             );
21         }
22     }
23 }

RouteDemoController

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 using System.Reflection;
 8 namespace MVCControllerDemo.Controllers
 9 {
10     public class ControllerDemoController : IController
11     {
12         public String Index()
13         {
14             return "<h1>Index</h1>";
15         }
16 
17 
18 
19         public void Execute(System.Web.Routing.RequestContext requestContext)
20         {
21             string action = requestContext.RouteData.Values["action"].ToString();
22             Type typ = typeof(ControllerDemoController);
23             MethodInfo md = typ.GetMethod(action, BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
24             if (md == null)
25             {
26                 requestContext.HttpContext.Response.Write("<h1>404</h1>");
27             }
28             else
29             {
30                 string s = md.Invoke(this, null).ToString();
31                 requestContext.HttpContext.Response.Write(s);
32             }
33         }
34     }
35 }

8.2 继承Controller

这种措施较常用。

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 namespace MVCControllerDemo.Controllers
 8 {
 9     public class ControllerDemoController : Controller
10     {
11         //
12         // GET: /ControllerDemo/
13 
14         [HttpGet]
15         public ActionResult Index()
16         {
17             return View();
18         }
19     }
20 }

 

9  参考文献

【01】http://www.cnblogs.com/wangiqngpei557/p/3390812.html

【02】http://www.cnblogs.com/yaozhenfa/p/asp\_net\_mvc\_controller.html

【03】http://www.360doc.com/content/12/0611/15/29831\_217456312.shtml

【04】http://blog.csdn.net/yw1688/article/details/51280665

【05】Professional Asp.net MVC 5

【06】Professional Asp.net MVC 4

【07】The framework of revelation  of 
Professional Asp.net MVC 5

【08】 https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions-1/controllers-and-routing/aspnet-mvc-controllers-overview-cs

10  版权

 

  • 感您的阅读,若发生不足之处,欢迎指教,共同学习、共同进步。
  • 博主网址:http://www.cnblogs.com/wangjiming/。
  • 最为少一些文章以读、参考、引用、抄袭、复制和糊等强办法组成而成的,大部分吧原创。
  • 假设你喜爱,麻烦推荐一下;如你发出新想法,欢迎提出,邮箱:2016177728@qq.com。
  • 可以转载该博客,但得著名博客来源。