I recently learned ASP. NET MVC and compared the previous WebForm with no IsPostBack judgment, event processing is also replaced by Action. In the WebForm of MVC, a large number of events are bound to the UI, mixed js injection, and style changes are gone; the server control is no longer needed, and the View is released, the Controller can be tested in units, and the View can be quickly replaced with the ViewModel. (To be honest, it would not have been a page engine like Razor and powerful intelligent awareness of vs ide, ASP. net mvc and JSP are no different. Maybe someone will use the strust tag and spring tag in.. NET)
In addition, the current EF, Model layer, and DAL implementations are naturally handed over to the ORM frameworks such as EF. With the mature Repository Pattern and UnitOfWork Pattern practices, the Service hierarchy becomes a convention. (For Repository and UnitOfWork, see Implementing the Repository and Unit of Work Patterns in an ASP. net mvc Application ). To separate the Repository, UnitOfWork is to avoid Directly Writing Linq2Db code in the Controller, so it is difficult to implement Mockup, like the following code:
(For details, refer to: Walkthrough: Using TDD with ASP. net mvc)
[No code for using Repository Pattern]
[Csharp]
Public class HomeController: Controller {
ContactEntities _ db = new ContactEntities ();
Public ActionResult Index (){
Var dn = _ db. Contacts;
Return View (dn );
}
}
[Code for using Repository Pattern]
[Csharp]
Namespace MvcContacts. Models {
Public class EF_ContactRepository: MvcContacts. Models. IContactRepository {
Private ContactEntities _ db = new ContactEntities ();
Public Contact GetContactByID (int id ){
Return _ db. Contacts. FirstOrDefault (d => d. Id = id );
}
...
A Mock Repository can be used for testing. Where does the _ db data come from...
[Csharp]
Namespace MvcContacts. Tests. Models {
Class InMemoryContactRepository: MvcContacts. Models. IContactRepository {
Private List <Contact> _ db = new List <Contact> ();
...
Controller becomes like this: www.2cto.com
[Csharp]
Public class HomeController: Controller {
IContactRepository _ repository;
Public HomeController (): this (new EF_ContactRepository ()){}
Public HomeController (IContactRepository repository ){
_ Repository = repository;
}
Public ViewResult Index (){
Throw new NotImplementedException ();
}
}
}
In fact, the above are all references. The purpose of Unity is to further delay the instantiation of Repository or UnitOfWork (often evolved into a Service) and give it to the IoC container for injection. To achieve more flexible switching, such as switching from MS Entities to MySql Entities or from ObjectContext to DbContext (CodeFirst ).
The following describes how to implement Unity. MVC3:
1. EF CodeFirst Models
Use EF CodeFirst to create a Models project to manage Entities
The table is very simple. There is only one DbSet <User>
[Csharp]
Namespace MvcWithUnityTest. Models
{
Public class DbEntities: DbContext
{
Public DbSet <User> Users {get; set ;}
}
}
2. GenericRepository
Mainly for EF (ObjectContext) and EF CodeFirst (DbContext) extract interface IRepository
[Csharp]
Using System;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;
Using System. Linq. Expressions;
Namespace GenericRepository
{
Public interface IRepository <T>: IDisposable where T: class
{
IQueryable <T> AsQueryable ();
IEnumerable <T> GetAll ();
IEnumerable <T> Find (Expression <Func <T, bool> where );
T Single (Expression <Func <T, bool> where );
T First (Expression <Func <T, bool> where );
Void Delete (T entity );
Void Add (T entity );
Void Update (T entity );
}
}
DbContextRepository <T> corresponds to the IRepository <T> Implementation of DbContext. The Context instance is injected through the constructor.
[Csharp]
Using System;
Using System. Collections. Generic;
Using System. Linq;
Using System. Text;
Using System. Data. Entity;
Using System. Linq. Expressions;
Namespace GenericRepository
{
Public class DbContextRepository <T>: IRepository <T> where T: class
{
Protected DbSet <T> _ objectSet;
Protected DbContext _ context;
Public DbContextRepository (DbContext context)
{
_ ObjectSet = context. Set <T> ();
_ Context = context;
}
Public IQueryable <T> AsQueryable ()
{
Return _ objectSet;
}
Public IEnumerable <T> GetAll ()
{
Return _ objectSet. ToList ();
}
Public IEnumerable <T> Find (Expression <Func <T, bool> where)
{
Return _ objectSet. Where (where );
}
Public T Single (Expression <Func <T, bool> where)
{
Return _ objectSet. Single (where );
}
Public T First (Expression <Func <T, bool> where)
{
Return _ objectSet. First (where );
}
Public void Delete (T entity)
{
If (_ context. Entry (entity). State = System. Data. EntityState. Detached)
_ ObjectSet. Attach (entity );
_ ObjectSet. Remove (entity );
}
Public void Add (T entity)
{
_ ObjectSet. Add (entity );
}
Public void Update (T entity)
{
_ ObjectSet. Attach (entity );
_ Context. Entry (entity). State = System. Data. EntityState. Modified;
}
Public void Dispose ()
{
System. Diagnostics. Trace. WriteLine ("context dispose ");
_ Context. Dispose ();
}
}
}
3. MVC Web Applications
(1) Get Unity. MVC3 through NuGet first
In ASP. NET MVC3, the dependency injection container interface IDependencyResolver is opened. When ASP. NET Controller is called, dependency injection is performed using this interface. Therefore, you can use this interface,
Use any dependency injection container. In addition, Unity. MVC3.dll extends the RegisterControllers method in the UnityContainerExtensions class,
It will complete registration for all non-abstract controllers of the current Assembly (Dependencies from IControllerFactory)
The added Bootstrapper. cs file is displayed in the Web project.
[Csharp] print? Public static class Bootstrapper
{
Public static void Initialise ()
{
Var container = BuildUnityContainer ();
DependencyResolver. SetResolver (new UnityDependencyResolver (container ));
}
Private static IUnityContainer BuildUnityContainer ()
{
Var container = new UnityContainer ();
// Register all your components with the container here
// E.g. container. RegisterType <ITestService, TestService> ();
Container. LoadConfiguration ("default ");
Container. RegisterControllers ();
Return container;
}
}
Public static class Bootstrapper
{
Public static void Initialise ()
{
Var container = BuildUnityContainer ();
DependencyResolver. SetResolver (new UnityDependencyResolver (container ));
}
Private static IUnityContainer BuildUnityContainer ()
{
Var container = new UnityContainer ();
// Register all your components with the container here
// E.g. container. RegisterType <ITestService, TestService> ();
Container. LoadConfiguration ("default ");
Container. RegisterControllers ();
Return container;
}
}
Here I put all dependencies in the configuration file:
[Html] print? <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">
<Alias = "IRepository" type = "GenericRepository. IRepository '1, GenericRepository"/>
<Alias = "DbContextRepository" type = "GenericRepository. DbContextRepository '1, GenericRepository"/>
<Alias = "User" type = "MvcWithUnityTest. Models. User, MvcWithUnityTest. Models"/>
<Alias = "DbEntities" type = "MvcWithUnityTest. Models. DbEntities, MvcWithUnityTest. Models"/>
<Container name = "default">
<Register type = "IRepository [User]" mapTo = "DbContextRepository [User]">
<Lifetime type = "HierarchicalLifetimeManager"/>
<Constructor>
<Param name = "context" dependencyType = "DbEntities">
</Param>
</Constructor>
</Register>
</Container>
</Unity>
</Configuration>
<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">
<Alias = "IRepository" type = "GenericRepository. IRepository '1, GenericRepository"/>
<Alias = "DbContextRepository" type = "GenericRepository. DbContextRepository '1, GenericRepository"/>
<Alias = "User" type = "MvcWithUnityTest. Models. User, MvcWithUnityTest. Models"/>
<Alias = "DbEntities" type = "MvcWithUnityTest. Models. DbEntities, MvcWithUnityTest. Models"/>
<Container name = "default">
<Register type = "IRepository [User]" mapTo = "DbContextRepository [User]">
<Lifetime type = "HierarchicalLifetimeManager"/>
<Constructor>
<Param name = "context" dependencyType = "DbEntities">
</Param>
</Constructor>
</Register>
</Container>
</Unity>
</Configuration> call Bootstrapper. Initialise (); in Global. asax. cs.
In addition, note that <register type = "IRepository [User]" mapTo = "DbContextRepository [User]"> adds <lifetime type = "HierarchicalLifetimeManager"/>
In this way, Dispose is called at the end of the Controller lifecycle. (To be expanded)
Let's take a look at the implementation of Controller:
According to the preceding configuration file: <register type = "IRepository [User]" mapTo = "DbContextRepository [User]">
[Dependency] The UserRepository is injected into the instance when the Controller requests.
[Csharp] print? Public class HomeController: Controller
{
[Dependency]
Public IRepository <User> UserRepository {get; set ;}
Public ActionResult Index ()
{
ViewBag. Message = "ASP. NET MVC3 With Unity. MVC3! ";
Var users = UserRepository. GetAll ();
Return View (users );
}
Public ActionResult About ()
{
Return View ();
}
}
Public class HomeController: Controller
{
[Dependency]
Public IRepository <User> UserRepository {get; set ;}
Public ActionResult Index ()
{
ViewBag. Message = "ASP. NET MVC3 With Unity. MVC3! ";
Var users = UserRepository. GetAll ();
Return View (users );
}
Public ActionResult About ()
{
Return View ();
}
}
Run:
The entire IoC system structure is used, for example:
From Lullaby's Blog