ASP.NET MVC 企业级实战
1、泛型
public class List<T>{
}
当定义泛型类的实例时,必须指定这个实例所存储的实际类型,泛型允许程序员将一个实际的数据类型规约延迟至泛型的实例被创建时才确定,泛型主要有两个有点:
1)编译时可以保证类型安全
2)不用做类型装换,获得一定的性能提升。
2、泛型方法、泛型委托、泛型接口
//泛型委托
public delegate void Del<T>(T item);
public static void Notify(int i){}
//泛型接口
public class myClass<T1,T2,T3>:MyInteface<T1,T2,T3>{
public T1 Method1(T2 param1,T3 param2){
throw new NotImplementedException();}}
interface MyInteface<T1,T2,T3>{
T1 Method1(T2 param1,T3 param2);
}
//泛型方法
static void Swap<T>(ref T t1,ref T t2){
T temp=t1;
t1=t2;
t2=temp;
}
public void Interactive(){
string str1="a";
string str2="b";
Swap<string> (ref str1,ref str2);
Console.WriteLine(str1+","+str2);
}
3、泛型约束 (可以给泛型的类型参数上加约束)
Where T:struct --类型参数虚是值类型
Where T:class --类型参数需是引用类型
Where T:new() --类型参数要有一个public的无参构造函数
............
4、部分类(partial)
在声明一个类、结构或者接口的时候用partial关键字可以让源码分布在不同的文件中。部分类仅是编译器提供的功能,在编译的时候会把partial关键字定义的类合在一起编译。
5、匿名方法
匿名方法的本质其实就是委托,函数式编程的最大特点之一就是把方法作为参数和返回值。ConsoleWrite——>MulticastDelegate(intPtr[ ])——>Delegate(object,intPtr)匿名方法:bian编译后会生成委托对象,生成方法,然后把方法装入委托对象,最后赋值给声明的委托变量。匿名方法可以省略参数:编译的时候会自动为这个方法按照委托签名的参数添加参数
public delegate void ConsoleWrite(string strMsg);
ConsoleWrite delCWl=new ConsoleWrite(WriteMsg);
delCWl("天下第一");
ConsoleWrite delCw2=delegate(string strMsg){
Console.WriteLine(strMsg);
}
DelCW2("天下第二");
隐式推断类型Var
应用场合:var主要用于表示一个LINQ查询的结果。这个结果既可能是ObjectQuery<>或IQueryable<>类型的对象,也可能是一个简单的实体类型的对象或者是一个基本类型对象,这时使用var声明这个对象可以节省很多代码书写上的时间
var customer=new User();
var i=1;
var隐式类型的限制
被声明的变量必须是一个局部变量,而不是静态或实例字段
变量必须在声明的同时被初始化,因为编译器要根据初始化值推断类型
初始化的对象不能是一个匿名函数
初始化表达式不能是null
语句中只声明一次变量,声明后不能更改类型。
复制的数据类型必须是可以在编译时确定的类型
对象集合初始化器
对象初始化:
.NET3.5/C#3.0 中我们有一种更好的方式来进行对象的初始化,那就是使用对象初始化器。这个特性时匿名类的一个基础
User user=new User{Id=1,Name="强哥",Age=23};
集合初始化:
list<Dog>dogs=new List<Dog>(){new Dog(){Name="Tom",Age=1},new Dog(){Name="Lucy",Age=3}}
6.匿名类
匿名类型提供了一种方便的方法,可用来将一组只读属性封装到单个对象中,而无须首先显式定义一个类型。类型名由编译器生成,并且不能在源代码级使用,每个属性的类型由编译器推断。我们可以使用new{object initializer} 或new[ ]{object,......}来初始化一个匿名类或不确定类型的数组。匿名类的对象需要使用var关键字声明。
var p=new {Id=1,Name="zouqj",Age=27};//属性名字和顺序不同会生成不同类
在编译后会生成一个"泛型类",
直接使用select new{object initializer}这样的语句就是将一个LINQ查询的结果返回到一个匿名类中
系统内置委托
Func/Action委托使用可变性:
Action<object>test=delegate(object o){Console.WriteLine(o);};
Action<string>test2=test;
Func<string>fest=delegate(){return Console.ReadLine();};
fest2=fest;
public delegate void Action();
public delegate bool Predicate<in T>(T obj);
public delegate int Comparison<in T>(T x,T y)
协变指的是委托方法的返回值类型直接或间接继承自委托签名的返回值类型,逆变则是参数类型继承自委托方法的参数System.Func,代表又返回类型的委托
public delegate TResult Func<out TResult>();
public delegate TResult Func<in T,out TResult>(T arg)
注:输入泛型参数-in最多可以有16个,输出泛型参数-out只有一个。System.Action代表无返回类型的委托
public delegate void Action<in T>(T obj);
public delegate void Action<in T1,in T2>(T1 arg1,T2 arg2);
注:最多有16个参数,System.Predicate<T>代表返回bool类型的委托,用作执行表达式
public delegate bool Predicate<in T>(T obj)
System.Comparison<T>代表返回int类型的委托,用于比较两个参数的大小。为什么要定义这么多简单的委托?
public delegate int Comparison<in T>(T x,T y)
7、Lambda表达式
Lambda表达式的本质就是匿名函数,Lambda表达式基于数学中的“入”演算得名,直接对应于其中的lambda抽象,是一个匿名函数,既没有函数名的函数。Lambda表达式是一个匿名函数,可以包含表达式和语句,并且可用于创建委托或表达式树类型。
lambda的基本形式是:
(input parameters) => expression
只有在Lambda有一个输入参数时,括号才是可选的,否则括号是必需的。两个或更多输入参数由括在括号中的逗号分隔:(x,y)=>x==y。
有时,编译器难于或无法推断输入类型。如果出现这种情况,您可以按以下示例中所示的方式显示指定类型:
(int x,string s)=> s.Length>x
使用空括号指定零个输入参数:
()=>someMethod()
Lambda表达式缩写推演
new Func<string,int>(delegate(string str){return str.Length})
delegate(string str){return str.Length;}//匿名方法
(string str)=>{return str.Length;}//Lambda语句
(string str)=>str.Length//Lambda表达式
(str)=>str.Length//让编译器推断参数类型
str=>str.Length//去掉不必要的括号
9、标准查询运算符(SQO)
标准查询运算符是定义在System.Linq.Enumerable类中的50多个为IEnumerable<T>准备的扩展方法,换句话说IEnumerable<T>上的每个方法都是一个标准查询运算符,这些方法用来对操作集合进行查询筛选
标准查询运算符提供了包括筛选、投影、聚合、排序等功能在内的查询功能。
1)、筛选集合Where
where方法提供了我们对于一个集合的筛选功能,但需要提供一个带bool返回值的“筛选器”(匿名方法、委托、Lambda表达式均可),从而表明集合中某个元素是否应该被返回。
var lst=InitLstData();
var result=lst.Where(x=>x.Age>=30).toList();
result.ForEach()
2)、查询投射Select
返回新对象集合IEnumberable<TSource>Select().返回年龄大于等于30岁的人的名字,代码如下:
var result=lst.Where(x=>x.Age>=30).Select(s=>s.Name).toList();
result.ForEach(x=>Console.WriteLine(x))
3)、统计数量int Count()
lst.Where(x=>x.Age>=30).Count();
4)、多条件排序OrderBy().ThenBy().ThenBy()
lst.OrderBy(x=>x.Age).OrderBy(x=>x.Id)
5)、集合连接Join()(未理解)
6)SelectMany:把集合中每个对象的另外集合属性的值重新拼接为一个新的集合
foreach(var s in teachers.SelectMany(t=>t.Students)){
Console.WriteLine(s);//每个元素都是person
}
6)、延迟加载Where
在标准查询运算符中,Where方法就是一个典型的延迟加载案例。在实际开发中,我们往往会使用一些ORM框架例如EF去操作数据库,Where方法的使用则是每次调用都只是在后续生成的Sql语句时增加一个查询条件,EF无法确定本次查询是否已经添加结束,所以没有办法在每个Where方法执行的时候确定最终的Sql语句.....
IEnumerable<User>user=lst.Where(x=>x.Age>=30);
7)、即时加载FindAll
在开发中如果使用FindAll方法,EF会根据方法中的条件自动生成SQL语句,然后立即与数据库进行交互获取查询结果,并加载到内存中去。
List<User>lstUser=lst.FindAll(x=>x.Age>=30);
SQO缺点:语句太庞大复杂
10、LinQ
IEnumerable<Dog>listDogs=from dog in dogs where dog.Age>5 orderby dog.Age descending select dog;
以from开始,以select或group by子句结尾。输出是一个IEnumerable<T>或IQueryable<T>集合。
注:T的类型由select或group by 推断出来
LINQ分组:
..............
第四章 MVC进阶
4.1、View详解
View的职责是向用户提供界面,负责根据提供的模型数据生成准备提供给用户的格式界面,并提供用户和系统交互的入口。
MVC支持多种视图引擎(Razor和ASPX视图引擎是官方默认给出的,其实还支持N种视图引擎,甚至都可以是自己写的视图引擎)
4.1.1、View和Action之间数据传递的方式
View和Action之间前后台数据传递的方式有如下几种
弱类型ViewData[ ]
动态型ViewBag//dynamic
动态类型Model
临时存储TempData[ ]
后台:return View(data);//存入ViewData.Model
前台:Model//其实就是WebViewPage.Model
4.1.2、TempData、ViewData和ViewBag的区别
ViewData是字典型的,ViewBag不在是字典的键值对结构,而是dynamic(动态)型,会在程序运行的时候动态解析。ViewData为object型,而ViewBag为dynamic型。dynamic型与object型的区别是在使用时它会自动根据数据类型转换,而object型则需要我们自己去强制转换
4.2、Razor视图引擎
4.2.1、什么是Razor
Razor是ASP.NET MVC 3.0出现的新的视图引擎,为视图提供精简的语法,最大限度减少了语法和额外字符串。Razor不是编程语言,而是服务器标记语言,是一种允许用户向网页中嵌入基于服务器代码的标记语法
语境A:在前台声明和使用C#变量
@{
string schoolName="湖南第一师范";
}
<span>@schoolName.Models</span> @*错误*@
<span> @(schoolName).Models </span>
<span>我毕业于 @schoolName 学校</span>
说明:声明C#变量的代码必须写在@{ }代码块中,使用@ + C#变量名就能取得C#变量的值,注意前后必须有空格,否则会被当作普通字符输出。
语境B:邮件格式中的@符号
<span>zouqiongjun@uuch.net</span>@*通过,因为@前面没有空格*@
<span>zouqiongjun @uuch.net</span>@*不通过, 因为@前面有空格*@
4.2.2 Razor语法
C#的主要语法规则如下:
Razor代码封装于@{......}中
行内表达式(变量和函数)以@开头
代码语句以分号结尾
字符串由引号包围
c#代码对大小写敏感
c#文件的扩展名是.cshtml
Razor通过理解标记的结构来实现代码和标记之间的顺畅切换
@核心转换字符,用来标记代码的转换字符串。
Razor表达式自动使用了HTML编码
如果想向浏览器输出HTML源代码,那么使用System.Web.IHtmlString:@Html.Raw("<b>zouyujie</b>")
<script>
alert('@Ajax.JavaScriptStringEncode("小李飞刀")');
</script>
@代码块
@{
string s="zouyujie";
int age=27;
}
@{Html.RenderPartial("TestPartial");}//调用无返回值方法
调用泛型方法:
@(Html.SomeMethod<User>());
混合代码与文本:
@if(1==1){
<text>我要输出文本在这里</text>
@:我要输出文本在这里
}
说明:当前台的C#
第五章 MVC核心透析
5.1、MVC Routing
在项目要使用Routing(路由),需要添加程序集引用System.Web.Routing.dll,而在ASP.NET MVC项目中则自动添加了此引用。严格来说,System.Web.Routing.dll并不属于ASP.NET MVC的一部分,微软把此项目单独列出来了,并没有开放源代码,但是未来微软也许会把Routing开源,毕竟开源是大势所趋,而且微软也在不断地拥抱开源。
MapRoute()有如下重载,它们都是扩展方法。
public class AreaRegistrationContext{
private readonly HashSet<string> _namespaces;
public AreaRegistrationContext(string areaName,RouteCollection routes)
}
ASP.NET MVC全局开启非入侵Ajax
ASP.NET MVC4 已经默认开启客户端验证和非入侵式js。在Web.config中可以看到如下配置:
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
如果只想在指定页面使用此功能,可以在页面中单独添加非入侵js文件:
@Scripts.Render("~/Scripts/jquery.unobtrusive-ajax.min.js")
.......
5.2.3 AjaxHelper
1.异步链接按钮
使用异步链接按钮时,必须开启非入侵Ajax(导入JQuery和unbtrusive相关的Ajax文件)
(1)在View中,@Ajax.ActionLink创建Ajax
......
5.2.4、请求Json数据
添加控制器Json,在Controller中使用Json方法返回一个JsonResult:
NorthwindEntities db=new NorthwindEntities();
public ActionResult CustomersList(){
var dogList=db.Customers.Select(x=>new{ CustomerID=x.CustomerID,ContactName=x.ContactName,Phone=x.Phone}).ToList();
return Json(dogList,JsonRequestBehavior.AllowGet);
}
MVC框架默认不允许使用Json响应Get请求,需要开启,开启代码为JsonRequestBehavior.AllowGet。在GetView中添加代码:
@Ajax.ActionLink("click here", "CustomersList",new AjaxOptions(){
UpdateTargetId="divMsg",
InsertionMode=InsertionMode.Replace,
HttpMethod="Get",
})