ASP.NET MVC IOC之Unity攻略

一、你知道IOC与DI吗?

1、IOC(Inversion of Control )——控制反转

即依赖对象不在被依赖模块的类中直接通过new来获取

先看看下面这段代码的问题~

public class SqlServerDal
{
public void Delete()
{
Console.WriteLine("删除表中某个订单信息!");
}
} public class Order
{
private readonly SqlServerDal dal = new SqlServerDal();
public void Delete()
{
dal.Delete();
}
} using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DIPTest
{
class Program
{
static void Main(string[] args)
{
Order order = new Order();
order.Delete();
Console.Read();
}
}
}

关于以上例子的说明:

(1)在Order类中,它依赖于具体的对象SqlServerDal,违反了依赖倒置的原则,即不论是高层还是底层,都应该依赖于抽象而不应该依赖于具体

(2)如果需求有变:数据访问层换为OracleDal,那么这个时候,就要修改Order类的代码;如果数据访问层再次换为MySqlDal,那么还要继续修改Order类的代码......如果无休止的变下去,将会是一个噩梦,而且你不但要修改   Order里边的代码,可能你还要修改Product、Users等类里边的代码,因为它们也可能跟Order类是同样的情况

怎么办呢?IOC啊~

那如何IOC啊?使用DI啊~

2、DIDependency Injection)——依赖注入

DI是IoC的一种实现方式,就是将依赖对象的创建和绑定转移到被依赖对象类的外面来实现

依赖注入分为:构造函数注入、属性注入和接口注入

(1)构造函数注入

首先,我们为数据访问类SqlServerDal定义一个抽象接口IDataAccess,并在IDataAccess接口中声明GetAll方法:

public interface IDataAccess
{
void Delete();
}

然后在SqlServerDal类中,实现IDataAccess接口:

public class SqlServerDal:IDataAccess
{
public void Delete()
{
Console.WriteLine("删除表中某个订单信息!");
}
}

接下来,我们还需要修改Order类:

public class Order
{
private IDataAccess da; //构造函数注入
public Order(IDataAccess ida)
{
da = ida;
}
public void Delete()
{
da.Delete();
}
}

下面是控制台程序调用的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IOCDemo
{
class Program
{
static void Main(string[] args)
{
SqlServerDal dal = new SqlServerDal();//在Order类外部创建依赖对象
Order order = new Order(dal);//通过构造函数注入依赖
order.Delete();
Console.Read();
}
}
}

(2)属性注入

属性注入就是通过属性来传递依赖。因此,我们首先需要在依赖类Order中定义一个属性:

public class Order
{
private IDataAccess _da;
//属性,接受依赖
public IDataAccess da
{
set { _da = value; }
get { return _da; }
}
public void Delete()
{
_da.Delete();
}
}

下面是控制台程序调用的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace IOCDemo
{
class Program
{
static void Main(string[] args)
{
AccessDal dal = new AccessDal();//在外部创建依赖对象
Order order = new Order();
order.da = dal;//给属性赋值
order.Delete();
Console.Read();
}
}
}

(3)接口注入

相比构造函数注入和属性注入,用起来没有它们方便。首先定义一个接口,包含一个设置依赖的方法。

public interface IDependent
{
void SetDependence(IDataAccess ida);//设置依赖项
}

用依赖类实现这个接口:

public class Order : IDependent
{
private IDataAccess _ida;
public void SetDependence(IDataAccess ida)
{
_ida = ida;
}
public void Delete()
{
_ida.Delete();
}
}

下面是控制台程序调用的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IOCDemo
{
class Program
{
static void Main(string[] args)
{
AccessDal dal = new AccessDal();//在Order外部创建依赖对象
Order order = new Order();
order.SetDependence(dal);//传递依赖
order.Delete();
Console.Read();
}
}
}

3、IoC容器

前面所有的栗子中,我们都是通过手动的方式来创建依赖对象,并将引用传递给被依赖模块。比如:

SqlServerDal dal = new SqlServerDal();//在Order外部创建依赖对象
Order order = new Order(dal);//通过构造函数注入依赖

对于大型项目来说,相互依赖的组件比较多。如果还用手动的方式,自己来创建和注入依赖的话,显然效率很低,而且往往还会出现不可控的场面。因此,IoC容器就诞生了。IoC容器实际上是一个DI框架,它能简化我们的工作量。它包含以下几个功能:

  • 动态创建、注入依赖对象。
  • 管理对象生命周期。
  • 映射依赖关系。

本篇我们使用微软框架组给提供的Unity来实现依赖注入,它是最流行的IOC容器之一

二、Unity的使用

1、Unity是个什么东东?

Unit是微软patterns& practices组用C#实现的轻量级、可扩展的依赖注入容器,我们可以通过代码或者XML配置文件的形式来配置对象与对象之间的关系,在运行时直接调用Unity容器即可获取我们所需的对象,以便建立松散耦合的应用程序。

对于小型项目:用代码的方式实现即可

对于中大型项目:使用配置文件比较好

2、Unity入门

您可以访问http://unity.codeplex.com/releases得到最新版本的Unity,也可以直接在Nuget中获取到最新版本的Unity,或者下载微软的企业库,然后在项目中添加Microsoft.Practices.Unity.dll和Microsoft.Practices.Unity.Configuration.dll的引用

这里用到的最重要的东东就是IUnityContainer 接口,它本身定义了很多方法,当然还有一些扩展方法,具体的接口定义这里就不说了,我们会经常用到IUnityContainer 接口的RegisterInstance、RegisterType、Resolve等方法。

这里我举个栗子,首先定义如下接口,并用两个类来进行实现:

    /// <summary>
/// 班级接口
/// </summary>
public interface IClass
{
string ClassName { get; set; }
void ShowInfo();
} /// <summary>
/// 计科班
/// </summary>
public class CbClass : IClass
{
public string ClassName { get; set; }
public void ShowInfo()
{
Console.WriteLine("计科班:{0}", ClassName);
}
} /// <summary>
/// 电商班
/// </summary>
public class EcClass : IClass
{
public string ClassName { get; set; }
public void ShowInfo()
{
Console.WriteLine("电商班:{0}", ClassName);
}
}

(1)用编程方式实现注入

使用Unity来管理对象与对象之间的关系可以分为以下几步:

A、创建一个UnityContainer对象

B、通过UnityContainer对象的RegisterType方法来注册对象与对象之间的关系

C、通过UnityContainer对象的Resolve方法来获取指定对象关联的对象

注入代码如下:

public static void ContainerCodeTest()
{
IUnityContainer container = new UnityContainer();
//默认注册(无命名),如果后面还有默认注册会覆盖前面的
container.RegisterType<IClass, CbClass>();
//命名注册
container.RegisterType<IClass, EcClass>("ec");
//解析默认对象
IClass cbClass = container.Resolve<IClass>();
cbClass.ShowInfo();
//指定命名解析对象
IClass ecClass = container.Resolve<IClass>("ec");
ecClass.ShowInfo();
//获取容器中所有IClass的注册的已命名对象
IEnumerable<IClass> classList = container.ResolveAll<IClass>();
foreach (var item in classList)
{
item.ShowInfo();
}
}

(2)配置文件方式

通过配置文件配置Unity信息需要有以下几个步骤:

A、在配置文件<configSections> 配置节下注册名为unity的section

B、在<configuration> 配置节下添加Unity配置信息

C、在代码中读取配置信息,并将配置载入到UnityContainer中

配置文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns=http://schemas.microsoft.com/practices/2010/unity>
<!--定义类型别名-->
<aliases>
<add alias="IClass" type="ConsoleApplication1.UnityDemo.IClass,ConsoleApplication1" />
<add alias="CbClass" type="ConsoleApplication1.UnityDemo.CbClass,ConsoleApplication1" />
<add alias="EcClass" type="ConsoleApplication1.UnityDemo.EcClass,ConsoleApplication1" />
</aliases>
<!--容器-->
<container name="FirstClass">
<!--映射关系-->
<register type="IClass" mapTo="CbClass"></register>
<register type="IClass" mapTo="EcClass" name="ec"></register>
</container>
</unity>
</configuration>

注入代码如下:

public static void ContainerConfiguration()
{
IUnityContainer container = new UnityContainer();//获取指定名称的配置节
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
container.LoadConfiguration(section, "FirstClass");//获取特定配置节下已命名的配置节<container name="FirstClass">下的配置信息
IClass classInfo = container.Resolve<IClass>("ec");
classInfo. ShowInfo();
}

注意:

如果系统比较庞大,那么对象之间的依赖关系可能就会很复杂,最终导致配置文件变得很大,所以我们需要将Unity的配置信息从App.config或web.config中分离出来到某一个单独的配置文件中,比如Unity.config,然后将其作为参数传递给下面的方法,依然可以实现依赖注入:

public static void ContainerConfigurationFromFile(string configFile)
{
//根据文件名获取指定config文件
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = configFile };
//从config文件中读取配置信息
Configuration configuration =
ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
var unitySection = (UnityConfigurationSection)configuration.GetSection("unity");
var container = new UnityContainer().LoadConfiguration(unitySection, "FirstClass");
IClass classInfo = container.Resolve<IClass>("ec");
classInfo.ShowInfo();
}

3、使用Unity为已存在的对象注册关系

在日常开发的过程中我们有时候会自己创建好一个对象,但是你又想对这个已经创建好的对象的生命周期进行管理,这个时候你可以使用Unity提供的RegisterInstance方法(有很多重载),由于RegisterInstance是对已存在的实例进行注册,所以无法通过配置文件来进行配置。

代码示例如下:

public static void RegisterInstance()
{
IClass myClass = new MyClass();
IClass yourClass = new YourClass();
//为myClass实例注册默认实例
container.RegisterInstance<IClass>(myClass);
//为yourClass实例注册命名实例,同RegisterType
container.RegisterInstance<IClass>("yourInstance", yourClass);
container.Resolve<IClass>().ShowInfo();
container.Resolve<IClass>("yourInstance").ShowInfo();
}

这段代码很简单,就是使用RegisterInstance方法将已存在的实例myClass、yourClass等注册到UnityContainer中,默认情况下其实用的是ContainerControlledLifetimeManager,这个生命周期是由UnityContainer来进行管理,UnityContainer会维护一个对象实例的强引用,当你将已存在的实例注册到UnityContainer后,每次通过Resolve方法获取对象都是同一对象,也就是单件实例(singleton instance),具体有关生命周期相关信息在下面进行介绍。

注意是单实例哦~

4、Unity中生命周期管理

我们在系统中引入Unity主要就是想通过Unity来解除对象之间的依赖关系,方便我们根据配置调用到所需的对象,而Unity默认情况下会自动帮我们维护好这些对象的生命周期,可能Unity自动维护的生命周期并不总是我们想要的,这时我们就要根据具体的需求来更改这些对象的生命周期,下面就简单介绍一下Unity中内置的两个常用生命周期管理器,其他的生命周期管理器如果需要可以自己上网查看其详细说明。

(1)TransientLifetimeManager瞬态生命周期,默认情况下,在使用RegisterType进行对象关系注册时如果没有指定生命周期管理器则默认使用这个生命周期管理器,这个生命周期管理器就如同其名字一样,当使用这种管理器的时候,每次通过ResolveResolveAll调用对象的时候都会重新创建一个新的对象

代码如下:

public static void TransientLifetimeManagerCode()
{
//以下2种注册效果是一样的
container.RegisterType<IClass, MyClass>();
container.RegisterType<IClass, MyClass>(new TransientLifetimeManager());
Console.WriteLine("-------TransientLifetimeManager Begin------");
Console.WriteLine("第一次调用RegisterType注册的对象HashCode:" +
container.Resolve<IClass>().GetHashCode());
Console.WriteLine("第二次调用RegisterType注册的对象HashCode:" +
container.Resolve<IClass>().GetHashCode());
Console.WriteLine("-------TransientLifetimeManager End------");
}

如果是使用配置的方式,则需要在配置文件中注册关系的时候在<register>配置节下新增<lifetime>既可(如果不新增则默认使用TransientLifetimeManager),如果想使用其他的生命周期管理器,则更改此配置节即可!

其中<lifetime>有3个参数:

  • type,生命期周期管理器的类型,这边可以选择Unity内置的,也可以使用自定义的,其中内置的生命周期管理器会有智能提示
  • typeConverter,生命周期管理器转换类,用户自定义一个生命周期管理器的时候所创建一个转换器
  • value,初始化生命周期管理器的值

如果用此生命周期管理器,则要在配置文件中新增的节点如下:

<register type="IClass" mapTo="MyClass">
<lifetime type="transient" />
</register>

注入代码如下:

public static void TransientLifetimeManagerConfiguration()
{
//获取指定名称的配置节
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
container.LoadConfiguration(section, "FirstClass");
Console.WriteLine("-------TransientLifetimeManager Begin------");
Console.WriteLine("第一次调用RegisterType注册的对象HashCode:" +
container.Resolve<IClass>("transient").GetHashCode());
Console.WriteLine("第二次调用RegisterType注册的对象HashCode:" +
container.Resolve<IClass>("transient").GetHashCode());
Console.WriteLine("-------TransientLifetimeManager End------");
}

以上无论是代码还是配置的方式,运行之后都会发现实例的哈希码是不一样的,说明每次调用都是重新生成一个对象实例!
(2)ContainerControlledLifetimeManager,容器控制生命周期管理,这个生命周期管理器是RegisterInstance默认使用的生命周期管理器,也就是单件实例,UnityContainer会维护一个对象实例的强引用,每次调用的时候都会返回同一对象,示例代码如下:

public static void ContainerControlledLifetimeManagerCode()
{
IClass myClass = new MyClass();
//以下2种注册效果是一样的
container.RegisterInstance<IClass>("ccl", myClass);
container.RegisterInstance<IClass>("ccl", myClass, new ContainerControlledLifetimeManager());
container.RegisterType<IClass, MyClass>(new ContainerControlledLifetimeManager());
Console.WriteLine("-------ContainerControlledLifetimeManager Begin------");
Console.WriteLine("第一次调用RegisterType注册的对象HashCode:" + container.Resolve<IClass>().GetHashCode());
Console.WriteLine("第二次调用RegisterType注册的对象HashCode:" + container.Resolve<IClass>().GetHashCode());
Console.WriteLine("第一次调用RegisterInstance注册的对象HashCode:" + container.Resolve<IClass>("ccl").GetHashCode());
Console.WriteLine("第二次调用RegisterInstance注册的对象HashCode:" + container.Resolve<IClass>("ccl").GetHashCode());
Console.WriteLine("-------ContainerControlledLifetimeManager End------");
}

运行之后都会发现实例的哈希码是一样的,说明是单实例的

如果用此生命周期管理器,则要在配置文件中新增的节点如下:

<register type="IClass" mapTo="MyClass" name="ccl">
<lifetime type="singleton" />
</register>

注入代码与上例类似,这里不再列出

三、ASP.NET MVC与Unity

说了这么多Unity,主要还是想将其用到ASP.NET MVC的IOC中,其实很简单,大概就几个步骤搞定:

1. 实现IDependencyResolver接口并通过DependencyResolver.SetResolver告知MVC,将部分类型实例解析工作交由IoC容器Unity来处理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.Practices.Unity; namespace UnityOfMVC.IOC
{
public class UnityDependencyResolver : IDependencyResolver
{
IUnityContainer container; public UnityDependencyResolver(IUnityContainer container)
{
this.container = container;
} public object GetService(Type serviceType)
{
if (!this.container.IsRegistered(serviceType))
{
return null;
}
return container.Resolve(serviceType);
} public IEnumerable<object> GetServices(Type serviceType)
{
return container.ResolveAll(serviceType);
} }
}

2、继承DefaultControllerFactory,重载GetControllerInstance方法,实现自己的UnityControllerFactory类,并通过IoC容器将之注册为IControllerFactory的实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Practices.Unity;
using System.Web.SessionState; namespace UnityOfMVC.IOC
{
public class UnityControllerFactory : DefaultControllerFactory
{
IUnityContainer container;
public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
} protected override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
{
return container.Resolve(controllerType) as IController;
}
}
}

3、让我们开始弄一下配置文件

<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration" />
</configSections>
<unity>
<containers>
<container name="defaultContainer">
<register type="UnityOfMVC.Models.IStudentRepository, UnityOfMVC" mapTo="UnityOfMVC.Models.StudentRepository, UnityOfMVC"/>
<register type="System.Web.Mvc.IControllerFactory, System.Web.Mvc" mapTo="UnityOfMVC.IOC.UnityControllerFactory, UnityOfMVC"/>
</container>
</containers>
</unity>

4、用引导类Bootstrapper进行初始化工作

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Configuration;
using System.Web.Mvc;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using UnityOfMVC.IOC; namespace UnityOfMVC.BootStrapper
{
public class Bootstrapper
{
public static IUnityContainer Init()
{
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
} private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer(); UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
configuration.Configure(container, "defaultContainer"); return container;
} }
}

5、在函数Application_Start() 中进行真正的初始化工作

public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();

BootStrapper.Bootstrapper.Init(); //就是这个东东
}
}

6、现在在你的MVC程序中注入依赖代码就ok了

(1)首先声明一个Student学生类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web; namespace UnityOfMVC.Models
{
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string Graduation { get; set; }
public string School { get; set; }
public string Major { get; set; }
}
}

(2)然后声明仓储接口和其实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace UnityOfMVC.Models
{
public interface IStudentRepository
{
IEnumerable<Student> GetAll();
Student Get(int id);
Student Add(Student item);
bool Update(Student item);
bool Delete(int id);
}
}
 

(3)最后添加控制器StudentController,并注入依赖代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using UnityOfMVC.Models; namespace UnityOfMVC.Controllers
{
public class StudentController : Controller
{
readonly IStudentRepository repository;
//构造器注入
public StudentController(IStudentRepository repository)
{
this.repository = repository;
} public ActionResult Index()
{
var data = repository.GetAll();
return View(data);
} }
}

(4)最后为控制器StudentController的Index方法添加视图即可,这里不再详述,运行效果如下:

*将自己学习的点滴记录并分享出来,既能使自己得到成长,偶尔也能帮助一下别人,何乐而不为呢?如果这篇文章对你还有点用的话,希望帮忙推荐一下~

ASP.NET MVC IOC之Unity攻略的更多相关文章

  1. ASP.NET MVC IOC 之Ninject攻略

    ASP.NET MVC IOC 之Ninject攻略 一.为什么要使用Ninject? 很多其它类型的IOC容器过于依赖配置文件,老是配置,总感觉有点不爽,而且要使用assembly-qualifie ...

  2. [转]ASP.NET MVC IOC 之AutoFac攻略

    本文转自:http://www.cnblogs.com/WeiGe/p/3871451.html 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用A ...

  3. ASP.NET MVC IOC 之AutoFac攻略

    一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天,发现这个东东确实是个高大上的IOC容器~ Autofa ...

  4. ASP.NET MVC Razor视图引擎攻略

    --引子 看下面一段MVC 2.0的代码. <%if (Model != null){%> <p><%=Model%></p><%}%>&l ...

  5. ASP.NET MVC IOC 之AutoFac

    ASP.NET MVC IOC 之AutoFac攻略 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用AutoFac的貌似更为普遍,于是捯饬了两天, ...

  6. ASP.NET MVC中使用Unity进行依赖注入的三种方式

    在ASP.NET MVC中使用Unity进行依赖注入的三种方式 2013-12-15 21:07 by 小白哥哥, 146 阅读, 0 评论, 收藏, 编辑 在ASP.NET MVC4中,为了在解开C ...

  7. ASP.NET没有魔法——ASP.NET MVC IoC

    之前的文章介绍了MVC如何通过ControllerFactory及ControllerActivator创建Controller,而Controller又是如何通过ControllerBase这个模板 ...

  8. ASP.NET MVC IOC依赖注入之Autofac系列(二)- WebForm当中应用

    上一章主要介绍了Autofac在MVC当中的具体应用,本章将继续简单的介绍下Autofac在普通的WebForm当中的使用. PS:目前本人还不知道WebForm页面的构造函数要如何注入,以下在Web ...

  9. ASP.NET没有魔法——ASP.NET MVC IoC代码篇

    上一篇文章主要以文字的形式介绍了IoC及其在ASP.NET MVC中的使用,本章将从以下几点介绍如何使用代码在ASP.NET MVC中实现依赖注入: ● AutoFac及安装 ● 容器的创建 ● 创建 ...

随机推荐

  1. JavaScript-2.2 document.write 输出到页面的内容

    <html> <head> <meta http-equiv="content-type" content="text/html;chars ...

  2. java 面试题汇总(未完成)

    版权声明:本文博客原创文章,博客,未经同意,不得转载.

  3. 【MongoDB】Serveral common command of MongoDb

    In the recent days, since the overwork made me exhaused, on arrival to home I will go to bed, which ...

  4. POJ - 2828 Buy Tickets (段树单点更新)

    Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get ...

  5. MYSQL 优化指南

    数据库设计原则   标准化和规范化 数据库设计范式(3NF)   第一范式 数据属性唯一标示 在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关 ...

  6. response的contentType 几种类型

    ajax开发中在请求server端的响应时, 对于每一种返回类型 规范的做法是要在服务端指定response的contentType 的. (当然 不指定绝大多数情况下也没什么问题 尤其是返回&quo ...

  7. HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online

    意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...

  8. AngularJS html5Mode与ASP.NET MVC路由共存

    前言 很久之前便听说AngularJS,非常酷,最近也比较火,我也在持续关注这个技术,只是没有认真投入学习.前不久公司找我们部门做一个OA系统(想省下几万大洋的费用),第一时间便想到AngularJS ...

  9. JMeter怎么在get URL请求、POST请求中添加动态参数用于服务器段安全验证

    从前一个页面(含有服务器段返回给客户端的参数,用于在下一次请求时验证)中添加后置处理器中的Regular Expression Extractor,使用正则表达式对参数进行提取. 在用到这些变量时可以 ...

  10. cocos2d-x注意事项(十)Lua发展飞机战争-4-创建主角

    二战中被称为二战飞机飞机,当然,以飞机作业.这是一个游戏,我们必须加入一个飞机--这是我们的英雄. 首先创建一个层(PlaneLayer)要显示飞机.然后,create飞机初始化方法 module(& ...