在 OpenAccess ORM MVC 项目上使用依赖注入





5.00/5 (2投票s)
在 OpenAccess ORM MVC 项目上使用依赖注入
引言
你可能正在使用OpenAccess ORM启动一个新项目,并想知道如何实现依赖注入以防止硬编码依赖项并使在运行时更改它们成为可能。这其实并不难,特别是现在有了新的依赖注入框架,你只需要在Nuget上获取它们,将其引用到你的项目中,然后就可以使用了。
我会尽可能简单地解释这一点,我将首先解释我的示例架构,首先定义我使用的不同层。我们还将关注一个名为Departments
的数据库表。让我们开始吧。
假设你的架构目前简单地由4层组成,即
- 领域层(Domain)– 包含你的业务对象的模型。
- 基础设施层(Infrastructure)– 包含你在数据访问层上添加的抽象层。
- Web层 – 这是你的表示层。
- 测试层(Tests)– 我想我不需要解释这个。
对于领域层,我们不需要编码,因为Telerik 为你生成了所有内容,所以让我们直接进入基础设施层。让我们关注4个文件
Repository.cs – 此文件包含你的泛型存储库代码,用于从你的领域提取和/或处理信息
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
namespace EmployeesDemo.Infrastructure.Repositories
{
public abstract class Repository<T> : IDisposable, IRepository<T>
where T : class
{
protected IEntitiesModelUnitOfWork Context
{
get;
private set;
}
protected Repository(IEntitiesModelUnitOfWork context)
{
this.Context = context;
}
public IList GetAll()
{
return this.Context.GetAll().ToList();
}
public T Find(Expression<Func<T, bool>> predicate)
{
return this.Context.GetAll().FirstOrDefault(predicate);
}
public void Add(T order)
{
this.Context.Add(order);
}
public void Remove(T order)
{
this.Context.Delete(order);
}
public void Dispose()
{
this.Context = null;
}
}
}
IRepository.cs – 你的Repository.cs的接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
namespace EmployeesDemo.Infrastructure.Repositories
{
public interface IRepository<T>
where T : class
{
T Find(Expression<Func<T, bool>> predicate);
void Add(T order);
IList GetAll();
void Remove(T order);
}
}
DepartmentRepository.cs – 此文件仅包含Department
实体的抽象,如果是泛型方法,则应将其放在Repository.cs中
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EmployeesDemo.Infrastructure.Repositories
{
public class DepartmentRepository : Repository<Department>, IDepartmentRepository
{
public DepartmentRepository(IEntitiesModelUnitOfWork context)
: base(context)
{
}
public Department GetBy(string name)
{
return this.Context.GetAll<Department>().FirstOrDefault(x => x.Name == name);
}
}
}
IDepartmentRepository.cs – 这是DepartmentRepository
的接口。
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EmployeesDemo.Infrastructure.Repositories
{
public interface IDepartmentRepository : IRepository<Department>
{
Department GetBy(string name);
}
}
现在让我们进入表示层,首先我们定义一个视图模型,我们最终将在我们的控制器和视图中使用它。
DepartmentsViewModel.cs – 基本上是所有Departments
列表的模型。
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EmployeesDemo.Web.Models
{
public class DepartmentsViewModel
{
public DepartmentsViewModel()
{
this.Departments = new List<Department>();
}
public IList<Department> Departments { get; set; }
}
}
DepartmentViewModel.cs – 用于单个Department
的模型
using EmployeesDemo.Domain;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EmployeesDemo.Web.Models
{
public class DepartmentViewModel
{
public string Name { get; set; }
public string Description { get; set; }
}
}
DepartmentService.cs – 现在,这是用于与你的存储库通信的类
using EmployeesDemo.Web.Models;
using EmployeesDemo.Infrastructure.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EmployeesDemo.Web.Services
{
public class DepartmentService
{
private readonly IDepartmentRepository departmentRepository;
public DepartmentService(
IDepartmentRepository departmentRepository)
{
this.departmentRepository = departmentRepository;
}
public DepartmentsViewModel GetAll()
{
return new DepartmentsViewModel
{
Departments = departmentRepository.GetAll().ToList()
};
}
public DepartmentViewModel GetBy(string name)
{
var department = departmentRepository.GetBy(name);
return new DepartmentViewModel
{
Name = department.Name
};
}
}
}
HomeController.cs – 此控制器控制主页视图,在这里我们将使用我们需要的服务,在这种情况下是Department
服务。创建构造函数后,我们现在可以在代码中使用这些服务了。
using EmployeesDemo.Web.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace EmployeesDemo.Web.Controllers
{
public class HomeController : Controller
{
public DepartmentService departmentService;
public HomeController(
DepartmentService departmentService)
{
this.departmentService = departmentService;
}
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var technologyDepartment = departmentService.GetBy("Technology");
var allDepartment = departmentService.GetAll();
return View();
}
}
}
但是不要运行它,虽然它可以无错误地编译,但在运行时你会收到此错误。
'/' 应用程序中的服务器错误。
为此对象未定义无参数构造函数。
说明:在执行当前 Web 请求期间发生未经处理的异常。请查看堆栈跟踪,了解有关错误以及其在代码中源自何处的更多信息。
异常详细信息:System.MissingMethodException
:为此对象未定义无参数构造函数。
源错误
在执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪识别有关异常的来源和位置的信息。 |
为什么???这是因为默认情况下,ASP.NET MVC 要求控制器具有一个public
无参数构造函数,从而创建控制器的实例。因此,在我们的示例中,我们的构造函数需要DepartmentService
实例,我们需要一些东西将此实例传递给我们的控制器。现在你需要依赖注入框架,你可以选择很多选项,例如Unity、Castle.Windsor、Autofac、StructureMap等。我之前使用过Castle.Windsor,并且对此没有任何抱怨,但现在让我们使用Ninject。
现在要做到这一点,首先你需要在nuget中下载它。只需搜索Ninject并安装Ninject.MVC3即可,我之所以这么说,是因为这更容易,因为它的依赖项是另外两个,所以它也会自动安装它们。
安装完成后,我们需要创建一个NinjectModule并让ninject为你粘合在一起。我所做的是创建一个名为IoC的文件夹,在这个文件夹中,我们创建一个名为ControllerModule
的类。
现在让我们进行绑定
using EmployeesDemo.Domain;
using EmployeesDemo.Infrastructure.Repositories;
using EmployeesDemo.Web.Services;
using Ninject.Modules;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace EmployeesDemo.Web.IoC
{
public class ControllerModule : NinjectModule
{
public override void Load()
{
this.Bind<IEntitiesModelUnitOfWork>().To<EntitiesModel>()
.InRequestScope()
.WithConstructorArgument
("connectionId", "TestingDatabaseConnection");
this.Bind<IDepartmentRepository>().To<DepartmentRepository>()
.InRequestScope();
this.Bind<DepartmentService>().To<DepartmentService>()
.InRequestScope();
}
}
}
现在,我们完成了绑定。让我们修改我们的Global.asax,以便所有内容都在ApplicationStart
注册。首先让我们继承NinjectHttpApplication
并替换默认的HttpApplication
。
接下来替换……
void Application_Start()
为……
override void OnApplicationStarted()
然后调用……
base.OnApplicationStarted();
我们还需要重写NinjectHttpApplication
的CreateKernel
方法
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly());
return kernel;
}
最后,由于我们在Global.asax中创建了它,因此我们不需要在App_Start文件夹中创建的名为NinjectWebCommon.cs的ninject生成的代码,因此请删除它们。
现在你可以开始了。运行你的应用程序,然后查看结果。
归档于:架构、CodeProject、编程标签:ASP.NET MVC、C#、依赖注入、依赖注入框架、MVC、ninject