ASP.NET MVC IOC之Unity攻略
文章看着也不错,拿来分享给大家(转载)
原文地址 http://www.it165.net/pro/html/201407/17685.html
一、你知道IOC与DI吗?
1、IOC(Inversion of Control )——控制反转
即依赖对象不在被依赖模块的类中直接通过new来获取
先看看下面这段代码的问题~
view sourceprint?01.
public
class
SqlServerDal
02.
{
03.
public
void
Delete()
04.
{
05.
Console.WriteLine(
'删除表中某个订单信息!'
);
06.
}
07.
}
08.
09.
public
class
Order
10.
{
11.
private
readonly SqlServerDal dal =
new
SqlServerDal();
12.
public
void
Delete()
13.
{
14.
dal.Delete();
15.
}
16.
}
17.
18.
using System;
19.
using System.Collections.Generic;
20.
using System.Linq;
21.
using System.Text;
22.
namespace DIPTest
23.
{
24.
class
Program
25.
{
26.
static
void
Main(string[] args)
27.
{
28.
Order order =
new
Order();
29.
order.Delete();
30.
Console.Read();
31.
}
32.
}
33.
}
关于以上例子的说明:
(1)在Order类中,它依赖于具体的对象SqlServerDal,违反了依赖倒置的原则,即不论是高层还是底层,都应该依赖于抽象而不应该依赖于具体
(2)如果需求有变:数据访问层换为OracleDal,那么这个时候,就要修改Order类的代码;如果数据访问层再次换为MySqlDal,那么还要继续修改Order类的代码......如果无休止的变下去,将会是一个噩梦,而且你不但要修改 Order里边的代码,可能你还要修改Product、Users等类里边的代码,因为它们也可能跟Order类是同样的情况
怎么办呢?IOC啊~
那如何IOC啊?使用DI啊~
2、DI(Dependency Injection)——依赖注入
DI是IoC的一种实现方式,就是将依赖对象的创建和绑定转移到被依赖对象类的外面来实现
依赖注入分为:构造函数注入、属性注入和接口注入
(1)构造函数注入
首先,我们为数据访问类SqlServerDal定义一个抽象接口IDataAccess,并在IDataAccess接口中声明GetAll方法:
view sourceprint?1.
public
interface
IDataAccess
2.
{
3.
void
Delete();
4.
}
然后在SqlServerDal类中,实现IDataAccess接口:
view sourceprint?1.
public
class
SqlServerDal:IDataAccess
2.
{
3.
public
void
Delete()
4.
{
5.
Console.WriteLine(
'删除表中某个订单信息!'
);
6.
}
7.
}
接下来,我们还需要修改Order类:
view sourceprint?01.
public
class
Order
02.
{
03.
private
IDataAccess da;
//构造函数注入
04.
public
Order(IDataAccess ida)
05.
{
06.
da = ida;
07.
}
08.
public
void
Delete()
09.
{
10.
da.Delete();
11.
}
12.
}
下面是控制台程序调用的代码:
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Text;
05.
06.
namespace IOCDemo
07.
{
08.
class
Program
09.
{
10.
static
void
Main(string[] args)
11.
{
12.
SqlServerDal dal =
new
SqlServerDal();
//在Order类外部创建依赖对象
13.
Order order =
new
Order(dal);
//通过构造函数注入依赖
14.
order.Delete();
15.
Console.Read();
16.
}
17.
}
18.
}
(2)属性注入
属性注入就是通过属性来传递依赖。因此,我们首先需要在依赖类Order中定义一个属性:
view sourceprint?01.
public
class
Order
02.
{
03.
private
IDataAccess _da;
04.
//属性,接受依赖
05.
public
IDataAccess da
06.
{
07.
set { _da = value; }
08.
get {
return
_da; }
09.
}
10.
public
void
Delete()
11.
{
12.
_da.Delete();
13.
}
14.
}
下面是控制台程序调用的代码:
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Text;
05.
06.
namespace IOCDemo
07.
{
08.
class
Program
09.
{
10.
static
void
Main(string[] args)
11.
{
12.
AccessDal dal =
new
AccessDal();
//在外部创建依赖对象
13.
Order order =
new
Order();
14.
order.da = dal;
//给属性赋值
15.
order.Delete();
16.
Console.Read();
17.
}
18.
}
19.
}
(3)接口注入
相比构造函数注入和属性注入,用起来没有它们方便。首先定义一个接口,包含一个设置依赖的方法。
view sourceprint?1.
public
interface
IDependent
2.
{
3.
void
SetDependence(IDataAccess ida);
//设置依赖项
4.
}
用依赖类实现这个接口:
view sourceprint?01.
public
class
Order : IDependent
02.
{
03.
private
IDataAccess _ida;
04.
public
void
SetDependence(IDataAccess ida)
05.
{
06.
_ida = ida;
07.
}
08.
public
void
Delete()
09.
{
10.
_ida.Delete();
11.
}
12.
}
下面是控制台程序调用的代码:
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Text;
05.
namespace IOCDemo
06.
{
07.
class
Program
08.
{
09.
static
void
Main(string[] args)
10.
{
11.
AccessDal dal =
new
AccessDal();
//在Order外部创建依赖对象
12.
Order order =
new
Order();
13.
order.SetDependence(dal);
//传递依赖
14.
order.Delete();
15.
Console.Read();
16.
}
17.
}
18.
}
3、IoC容器
前面所有的栗子中,我们都是通过手动的方式来创建依赖对象,并将引用传递给被依赖模块。比如:
view sourceprint?1.
SqlServerDal dal =
new
SqlServerDal();
//在Order外部创建依赖对象
2.
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等方法。
这里我举个栗子,首先定义如下接口,并用两个类来进行实现:
view sourceprint?01.
/// <summary>
02.
/// 班级接口
03.
/// </summary>
04.
public
interface
IClass
05.
{
06.
string ClassName { get; set; }
07.
void
ShowInfo();
08.
}
09.
10.
/// <summary>
11.
/// 计科班
12.
/// </summary>
13.
public
class
CbClass : IClass
14.
{
15.
public
string ClassName { get; set; }
16.
public
void
ShowInfo()
17.
{
18.
Console.WriteLine(
'计科班:{0}'
, ClassName);
19.
}
20.
}
21.
22.
/// <summary>
23.
/// 电商班
24.
/// </summary>
25.
public
class
EcClass : IClass
26.
{
27.
public
string ClassName { get; set; }
28.
public
void
ShowInfo()
29.
{
30.
Console.WriteLine(
'电商班:{0}'
, ClassName);
31.
}
32.
}
(1)用编程方式实现注入
使用Unity来管理对象与对象之间的关系可以分为以下几步:
A、创建一个UnityContainer对象
B、通过UnityContainer对象的RegisterType方法来注册对象与对象之间的关系
C、通过UnityContainer对象的Resolve方法来获取指定对象关联的对象
注入代码如下:
view sourceprint?01.
public
static
void
ContainerCodeTest()
02.
{
03.
IUnityContainer container =
new
UnityContainer();
04.
//默认注册(无命名),如果后面还有默认注册会覆盖前面的
05.
container.RegisterType<IClass, CbClass>();
06.
//命名注册
07.
container.RegisterType<IClass, EcClass>(
'ec'
);
08.
//解析默认对象
09.
IClass cbClass = container.Resolve<IClass>();
10.
cbClass.ShowInfo();
11.
//指定命名解析对象
12.
IClass ecClass = container.Resolve<IClass>(
'ec'
);
13.
ecClass.ShowInfo();
14.
//获取容器中所有IClass的注册的已命名对象
15.
IEnumerable<IClass> classList = container.ResolveAll<IClass>();
16.
foreach (var item in classList)
17.
{
18.
item.ShowInfo();
19.
}
20.
}
(2)配置文件方式
通过配置文件配置Unity信息需要有以下几个步骤:
A、在配置文件<configSections> 配置节下注册名为unity的section
B、在<configuration> 配置节下添加Unity配置信息
C、在代码中读取配置信息,并将配置载入到UnityContainer中
配置文件内容如下:
view sourceprint?01.
<?xml version=
'1.0'
encoding=
'utf-8'
?>
02.
<configuration>
03.
<configSections>
04.
<section name=
'unity'
type=
'Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration'
/>
05.
</configSections>
06.
<unity xmlns=http:
//schemas.microsoft.com/practices/2010/unity>
07.
<!--定义类型别名-->
08.
<aliases>
09.
<add alias=
'IClass'
type=
'ConsoleApplication1.UnityDemo.IClass,ConsoleApplication1'
/>
10.
<add alias=
'CbClass'
type=
'ConsoleApplication1.UnityDemo.CbClass,ConsoleApplication1'
/>
11.
<add alias=
'EcClass'
type=
'ConsoleApplication1.UnityDemo.EcClass,ConsoleApplication1'
/>
12.
</aliases>
13.
<!--容器-->
14.
<container name=
'FirstClass'
>
15.
<!--映射关系-->
16.
<register type=
'IClass'
mapTo=
'CbClass'
></register>
17.
<register type=
'IClass'
mapTo=
'EcClass'
name=
'ec'
></register>
18.
</container>
19.
</unity>
20.
</configuration>
注入代码如下:
view sourceprint?1.
public
static
void
ContainerConfiguration()
2.
{
3.
IUnityContainer container =
new
UnityContainer();
//获取指定名称的配置节
4.
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection(
'unity'
);
5.
container.LoadConfiguration(section,
'FirstClass'
);
//获取特定配置节下已命名的配置节<container name='FirstClass'>下的配置信息
6.
IClass classInfo = container.Resolve<IClass>(
'ec'
);
7.
classInfo. ShowInfo();
8.
}
注意:
如果系统比较庞大,那么对象之间的依赖关系可能就会很复杂,最终导致配置文件变得很大,所以我们需要将Unity的配置信息从App.config或web.config中分离出来到某一个单独的配置文件中,比如Unity.config,然后将其作为参数传递给下面的方法,依然可以实现依赖注入:
view sourceprint?01.
public
static
void
ContainerConfigurationFromFile(string configFile)
02.
{
03.
//根据文件名获取指定config文件
04.
var fileMap =
new
ExeConfigurationFileMap { ExeConfigFilename = configFile };
05.
//从config文件中读取配置信息
06.
Configuration configuration =
07.
ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
08.
var unitySection = (UnityConfigurationSection)configuration.GetSection(
'unity'
);
09.
var container =
new
UnityContainer().LoadConfiguration(unitySection,
'FirstClass'
);
10.
IClass classInfo = container.Resolve<IClass>(
'ec'
);
11.
classInfo.ShowInfo();
12.
}
3、使用Unity为已存在的对象注册关系
在日常开发的过程中我们有时候会自己创建好一个对象,但是你又想对这个已经创建好的对象的生命周期进行管理,这个时候你可以使用Unity提供的RegisterInstance方法(有很多重载),由于RegisterInstance是对已存在的实例进行注册,所以无法通过配置文件来进行配置。
代码示例如下:
view sourceprint?01.
public
static
void
RegisterInstance()
02.
{
03.
IClass myClass =
new
MyClass();
04.
IClass yourClass =
new
YourClass();
05.
//为myClass实例注册默认实例
06.
container.RegisterInstance<IClass>(myClass);
07.
//为yourClass实例注册命名实例,同RegisterType
08.
container.RegisterInstance<IClass>(
'yourInstance'
, yourClass);
09.
container.Resolve<IClass>().ShowInfo();
10.
container.Resolve<IClass>(
'yourInstance'
).ShowInfo();
11.
}
这段代码很简单,就是使用RegisterInstance方法将已存在的实例myClass、yourClass等注册到UnityContainer中,默认情况下其实用的是ContainerControlledLifetimeManager,这个生命周期是由UnityContainer来进行管理,UnityContainer会维护一个对象实例的强引用,当你将已存在的实例注册到UnityContainer后,每次通过Resolve方法获取对象都是同一对象,也就是单件实例(singleton instance),具体有关生命周期相关信息在下面进行介绍。
注意是单实例哦~
4、Unity中生命周期管理
我们在系统中引入Unity主要就是想通过Unity来解除对象之间的依赖关系,方便我们根据配置调用到所需的对象,而Unity默认情况下会自动帮我们维护好这些对象的生命周期,可能Unity自动维护的生命周期并不总是我们想要的,这时我们就要根据具体的需求来更改这些对象的生命周期,下面就简单介绍一下Unity中内置的两个常用生命周期管理器,其他的生命周期管理器如果需要可以自己上网查看其详细说明。
(1)TransientLifetimeManager,瞬态生命周期,默认情况下,在使用RegisterType进行对象关系注册时如果没有指定生命周期管理器则默认使用这个生命周期管理器,这个生命周期管理器就如同其名字一样,当使用这种管理器的时候,每次通过Resolve或ResolveAll调用对象的时候都会重新创建一个新的对象。
代码如下:
view sourceprint?01.
public
static
void
TransientLifetimeManagerCode()
02.
{
03.
//以下2种注册效果是一样的
04.
container.RegisterType<IClass, MyClass>();
05.
container.RegisterType<IClass, MyClass>(
new
TransientLifetimeManager());
06.
Console.WriteLine(
'-------TransientLifetimeManager Begin------'
);
07.
Console.WriteLine(
'第一次调用RegisterType注册的对象HashCode:'
+
08.
container.Resolve<IClass>().GetHashCode());
09.
Console.WriteLine(
'第二次调用RegisterType注册的对象HashCode:'
+
10.
container.Resolve<IClass>().GetHashCode());
11.
Console.WriteLine(
'-------TransientLifetimeManager End------'
);
12.
}
如果是使用配置的方式,则需要在配置文件中注册关系的时候在<register>配置节下新增<lifetime>既可(如果不新增则默认使用TransientLifetimeManager),如果想使用其他的生命周期管理器,则更改此配置节即可!
其中<lifetime>有3个参数:
type,生命期周期管理器的类型,这边可以选择Unity内置的,也可以使用自定义的,其中内置的生命周期管理器会有智能提示 typeConverter,生命周期管理器转换类,用户自定义一个生命周期管理器的时候所创建一个转换器 value,初始化生命周期管理器的值
如果用此生命周期管理器,则要在配置文件中新增的节点如下:
view sourceprint?1.
<register type=
'IClass'
mapTo=
'MyClass'
>
2.
<lifetime type=
'transient'
/>
3.
</register>
注入代码如下:
view sourceprint?01.
public
static
void
TransientLifetimeManagerConfiguration()
02.
{
03.
//获取指定名称的配置节
04.
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection(
'unity'
);
05.
container.LoadConfiguration(section,
'FirstClass'
);
06.
Console.WriteLine(
'-------TransientLifetimeManager Begin------'
);
07.
Console.WriteLine(
'第一次调用RegisterType注册的对象HashCode:'
+
08.
container.Resolve<IClass>(
'transient'
).GetHashCode());
09.
Console.WriteLine(
'第二次调用RegisterType注册的对象HashCode:'
+
10.
container.Resolve<IClass>(
'transient'
).GetHashCode());
11.
Console.WriteLine(
'-------TransientLifetimeManager End------'
);
12.
}
以上无论是代码还是配置的方式,运行之后都会发现实例的哈希码是不一样的,说明每次调用都是重新生成一个对象实例!
(2)ContainerControlledLifetimeManager,容器控制生命周期管理,这个生命周期管理器是RegisterInstance默认使用的生命周期管理器,也就是单件实例,UnityContainer会维护一个对象实例的强引用,每次调用的时候都会返回同一对象,示例代码如下:view sourceprint?01.
public
static
void
ContainerControlledLifetimeManagerCode()
02.
{
03.
IClass myClass =
new
MyClass();
04.
//以下2种注册效果是一样的
05.
container.RegisterInstance<IClass>(
'ccl'
, myClass);
06.
container.RegisterInstance<IClass>(
'ccl'
, myClass,
new
ContainerControlledLifetimeManager());
07.
container.RegisterType<IClass, MyClass>(
new
ContainerControlledLifetimeManager());
08.
Console.WriteLine(
'-------ContainerControlledLifetimeManager Begin------'
);
09.
Console.WriteLine(
'第一次调用RegisterType注册的对象HashCode:'
+ container.Resolve<IClass>().GetHashCode());
10.
Console.WriteLine(
'第二次调用RegisterType注册的对象HashCode:'
+ container.Resolve<IClass>().GetHashCode());
11.
Console.WriteLine(
'第一次调用RegisterInstance注册的对象HashCode:'
+ container.Resolve<IClass>(
'ccl'
).GetHashCode());
12.
Console.WriteLine(
'第二次调用RegisterInstance注册的对象HashCode:'
+ container.Resolve<IClass>(
'ccl'
).GetHashCode());
13.
Console.WriteLine(
'-------ContainerControlledLifetimeManager End------'
);
14.
}
运行之后都会发现实例的哈希码是一样的,说明是单实例的
如果用此生命周期管理器,则要在配置文件中新增的节点如下:
view sourceprint?1.
<register type=
'IClass'
mapTo=
'MyClass'
name=
'ccl'
>
2.
<lifetime type=
'singleton'
/>
3.
</register>
注入代码与上例类似,这里不再列出
三、ASP.NET MVC与Unity
说了这么多Unity,主要还是想将其用到ASP.NET MVC的IOC中,其实很简单,大概就几个步骤搞定:
1. 实现IDependencyResolver接口并通过DependencyResolver.SetResolver告知MVC,将部分类型实例解析工作交由IoC容器Unity来处理
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Web;
05.
using System.Web.Mvc;
06.
using Microsoft.Practices.Unity;
07.
08.
namespace UnityOfMVC.IOC
09.
{
10.
public
class
UnityDependencyResolver : IDependencyResolver
11.
{
12.
IUnityContainer container;
13.
14.
public
UnityDependencyResolver(IUnityContainer container)
15.
{
16.
this
.container = container;
17.
}
18.
19.
public
object GetService(Type serviceType)
20.
{
21.
if
(!
this
.container.IsRegistered(serviceType))
22.
{
23.
return
null
;
24.
}
25.
return
container.Resolve(serviceType);
26.
}
27.
28.
public
IEnumerable<object> GetServices(Type serviceType)
29.
{
30.
return
container.ResolveAll(serviceType);
31.
}
32.
33.
}
34.
}
2、继承DefaultControllerFactory,重载GetControllerInstance方法,实现自己的UnityControllerFactory类,并通过IoC容器将之注册为IControllerFactory的实现
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Web;
05.
using System.Web.Mvc;
06.
using System.Web.Routing;
07.
using Microsoft.Practices.Unity;
08.
using System.Web.SessionState;
09.
10.
namespace UnityOfMVC.IOC
11.
{
12.
public
class
UnityControllerFactory : DefaultControllerFactory
13.
{
14.
IUnityContainer container;
15.
public
UnityControllerFactory(IUnityContainer container)
16.
{
17.
this
.container = container;
18.
}
19.
20.
protected
override IController GetControllerInstance(RequestContext reqContext, Type controllerType)
21.
{
22.
return
container.Resolve(controllerType) as IController;
23.
}
24.
}
25.
}
3、让我们开始弄一下配置文件
view sourceprint?01.
<configSections>
02.
<section name=
'unity'
type='Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
03.
Microsoft.Practices.Unity.Configuration' />
04.
</configSections>
05.
<unity>
06.
<containers>
07.
<container name=
'defaultContainer'
>
08.
<register type=
'UnityOfMVC.Models.IStudentRepository, UnityOfMVC'
mapTo=
'UnityOfMVC.Models.StudentRepository, UnityOfMVC'
/>
09.
<register type=
'System.Web.Mvc.IControllerFactory, System.Web.Mvc'
mapTo=
'UnityOfMVC.IOC.UnityControllerFactory, UnityOfMVC'
/>
10.
</container>
11.
</containers>
12.
</unity>
4、用引导类Bootstrapper进行初始化工作
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Web;
05.
using System.Configuration;
06.
using System.Web.Mvc;
07.
using Microsoft.Practices.Unity;
08.
using Microsoft.Practices.Unity.Configuration;
09.
using UnityOfMVC.IOC;
10.
11.
namespace UnityOfMVC.BootStrapper
12.
{
13.
public
class
Bootstrapper
14.
{
15.
public
static
IUnityContainer Init()
16.
{
17.
var container = BuildUnityContainer();
18.
DependencyResolver.SetResolver(
new
UnityDependencyResolver(container));
19.
return
container;
20.
}
21.
22.
private
static
IUnityContainer BuildUnityContainer()
23.
{
24.
var container =
new
UnityContainer();
25.
26.
UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
27.
configuration.Configure(container,
'defaultContainer'
);
28.
29.
return
container;
30.
}
31.
32.
}
33.
}
5、在函数Application_Start() 中进行真正的初始化工作
view sourceprint?01.
public
class
MvcApplication : System.Web.HttpApplication
02.
{
03.
protected
void
Application_Start()
04.
{
05.
AreaRegistration.RegisterAllAreas();
06.
07.
WebApiConfig.Register(GlobalConfiguration.Configuration);
08.
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
09.
RouteConfig.RegisterRoutes(RouteTable.Routes);
10.
BundleConfig.RegisterBundles(BundleTable.Bundles);
11.
AuthConfig.RegisterAuth();
12.
13.
BootStrapper.Bootstrapper.Init();
//就是这个东东
14.
}
15.
}
6、现在在你的MVC程序中注入依赖代码就ok了
(1)首先声明一个Student学生类
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Web;
05.
06.
namespace UnityOfMVC.Models
07.
{
08.
public
class
Student
09.
{
10.
public
int
Id { get; set; }
11.
public
string Name { get; set; }
12.
public
string Graduation { get; set; }
13.
public
string School { get; set; }
14.
public
string Major { get; set; }
15.
}
16.
}
(2)然后声明仓储接口和其实现
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Text;
05.
06.
namespace UnityOfMVC.Models
07.
{
08.
public
interface
IStudentRepository
09.
{
10.
IEnumerable<Student> GetAll();
11.
Student Get(
int
id);
12.
Student Add(Student item);
13.
bool Update(Student item);
14.
bool Delete(
int
id);
15.
}
16.
}
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Web;
05.
06.
namespace UnityOfMVC.Models
07.
{
08.
public
class
StudentRepository : IStudentRepository
09.
{
10.
private
List<Student> Articles =
new
List<Student>();
11.
12.
public
StudentRepository()
13.
{
14.
//添加演示数据
15.
Add(
new
Student { Id =
1
, Name =
'张三'
, Major =
'软件工程'
, Graduation =
'2013年'
, School =
'西安工业大学'
});
16.
Add(
new
Student { Id =
2
, Name =
'李四'
, Major =
'计算机科学与技术'
, Graduation =
'2013年'
, School =
'西安工业大学'
});
17.
Add(
new
Student { Id =
3
, Name =
'王五'
, Major =
'自动化'
, Graduation =
'2013年'
, School =
'西安工业大学'
});
18.
}
19.
/// <summary>
20.
/// 获取全部文章
21.
/// </summary>
22.
/// <returns></returns>
23.
public
IEnumerable<Student> GetAll()
24.
{
25.
return
Articles;
26.
}
27.
/// <summary>
28.
/// 通过ID获取文章
29.
/// </summary>
30.
/// <param name='id'></param>
31.
/// <returns></returns>
32.
public
Student Get(
int
id)
33.
{
34.
return
Articles.Find(p => p.Id == id);
35.
}
36.
/// <summary>
37.
/// 添加文章
38.
/// </summary>
39.
/// <param name='item'></param>
40.
/// <returns></returns>
41.
public
Student Add(Student item)
42.
{
43.
if
(item ==
null
)
44.
{
45.
throw
new
ArgumentNullException(
'item'
);
46.
}
47.
Articles.Add(item);
48.
return
item;
49.
}
50.
/// <summary>
51.
/// 更新文章
52.
/// </summary>
53.
/// <param name='item'></param>
54.
/// <returns></returns>
55.
public
bool Update(Student item)
56.
{
57.
if
(item ==
null
)
58.
{
59.
throw
new
ArgumentNullException(
'item'
);
60.
}
61.
62.
int
index = Articles.FindIndex(p => p.Id == item.Id);
63.
if
(index == -
1
)
64.
{
65.
return
false
;
66.
}
67.
Articles.RemoveAt(index);
68.
Articles.Add(item);
69.
return
true
;
70.
}
71.
/// <summary>
72.
/// 删除文章
73.
/// </summary>
74.
/// <param name='id'></param>
75.
/// <returns></returns>
76.
public
bool Delete(
int
id)
77.
{
78.
Articles.RemoveAll(p => p.Id == id);
79.
return
true
;
80.
}
81.
}
82.
}
(3)最后添加控制器StudentController,并注入依赖代码:
view sourceprint?01.
using System;
02.
using System.Collections.Generic;
03.
using System.Linq;
04.
using System.Web;
05.
using System.Web.Mvc;
06.
using UnityOfMVC.Models;
07.
08.
namespace UnityOfMVC.Controllers
09.
{
10.
public
class
StudentController : Controller
11.
{
12.
readonly IStudentRepository repository;
13.
//构造器注入
14.
public
StudentController(IStudentRepository repository)
15.
{
16.
this
.repository = repository;
17.
}
18.
19.
public
ActionResult Index()
20.
{
21.
var data = repository.GetAll();
22.
return
View(data);
23.
}
24.
25.
}
26.
}
(4)最后为控制器StudentController的Index方法添加视图即可,这里不再详述,运行效果如下:
转载于:https://www.cnblogs.com/dahe718/p/4303882.html
ASP.NET MVC IOC之Unity攻略相关推荐
- ASP.NET MVC IOC 之AutoFac攻略
转于:http://www.cnblogs.com/WeiGe/p/3871451.html 一.为什么使用AutoFac? 之前介绍了Unity和Ninject两个IOC容器,但是发现园子里用Aut ...
- 如何发布.Net MVC 网站项目(攻略集锦)
转载自诗人江湖老,原文地址 参考文献 既然是攻略,就必然有参考文献,放在文章开头,以示敬意! 1.MVC项目发布步骤 2.未能从程序集加载"System.ServiceModel.Activ ...
- ASP.NET完整打包卸载更新攻略(By Installshield 2010)【转】
- 前言 前阵子做了一个有关Installshield的OA 打包安装程序,用的版本Installshield 2010-Premier,具体功能的内容如下: 1.OA采用的是asp.net(C#)开 ...
- ASP.NET MVC 简单的分页思想与实现
首先我们通过VS创建一个空的基于Razor视图引擎的ASP.NET MVC3 Web应用程序,命名为JohnConnor.Web 对创建过程或Razor不太了解的看官,请移步 ASP.NET MVC ...
- asp.net mvc fckeditor全攻略(补充:Controller中传值的问题)
开篇仍然要叙述我的环境 环境说明: 软件环境:asp.net mvc3 + vs2010 系统环境:windows xp sp3 浏览器: ie8(为了世界的和平,为了社会的稳定,为了不再被大 ...
- 想爱容易,相处难:当ASP.NET MVC爱上IoC
也许你会问ASP.NET MVC为什么会爱上IoC? 相爱的理由常常很简单,就像一首歌中所唱--"只为相遇那一个眼神". 而ASP.NET MVC爱上IoC只为IoC能实现MVC控 ...
- ASP.NET MVC的Razor引擎:IoC在View激活过程中的应用
在<ASP.NET MVC的Razor引擎:RazorView>介绍BuildManagerCompiledView的时候,我们谈到默认使用的ViewPageActivator使用当前注册 ...
- ASP.NET画图全攻略(下)
我们在前面已经完成了饼图和条形图的自定义类,下面我们将要应用这些类了. 使用vs.net新建一个名为Insight_cs的Web应用程序,并且添加到刚才的Insight工程中.删除默认的webfo ...
- Asp.net C#制作PDF文件全攻略
StreamWriter pPDF=new StreamWriter(filePath); ArrayList xRefs=new ArrayList(); float yPos =0f; long ...
- Unity性能优化全攻略
#Unity性能优化全攻略 总结自Siki的性能优化. ##优化相关前提 ###Unity游戏安装包大/运行卡的原因 Mono虚拟机 解决这个问题 ###DrawCall https://zhuanl ...
最新文章
- P4755 Beautiful Pair (数据结构+分治)
- 使用STM32CubeMX,生成STM32F103ZE SPI3 HAL 工程
- Jupyterlab 插件安装后侧边栏找不到的解决
- qdialog 返回值_python-PyQt QDialog返回响应是或否
- web前端入门学习 css(4)(盒子模型)
- win32 输出文字时清除之前的_努力学习没效果?3个步骤,强化沟通输出,实现飞跃式成长...
- SwitchHosts!提示没有切换权限:C:\WINDOWS\system32\drivers\etc\host 文件无法修改
- Python生成带自定义信息和头像图片的二维码
- 如何在C中纯粹编写iOS应用程序
- 2021年11月_IEEE TRANSACTIONS ON MEDICAL IMAGING_科技前言热点调研表
- 华为数通NA-NP学习笔记(个人精简)
- 小程序和app究竟哪个好?
- 删除EFI系统分区(ESP)后Windows无法启动,重建引导分区并修复启动的过程
- 我爱 Ruby 的三十七个理由
- 09_Filter过滤器(访问所有资源前,首先执行自定义过滤器类的doFilter方法)_Listener监听器(监听域对象的改变)
- JS 日历插件 实现农历、节气 可自定义加班和休假
- 前端视频预览功能的实现
- ctfshow 萌新计划 writeup1-8
- 安装 office2007时出现:1706的错误-解决方案
- 一位算法工程师对自己工作的反思,写得挺实在的