Asp.net mvc ASP.NETMVC新手的IoC容器障碍
我必须承认,我是ASP.NETMVC新手,目前正在研究如何启动我的新项目的所有最佳实践。到目前为止,我已经理解了存储库模式和工作单元的概念,并且已经讨论了依赖注入和控制反转(IoC)。在过去的两天里,我一直在研究这个问题,我得出结论,我喜欢两个IoC容器,它们是StructureMap和NInject,尽管两者都不完美,我还没有设法让StructureMap工作,尽管我喜欢轻量级语法 下面是我的应用程序的构造方式。首先,我的数据上下文和存储库有以下接口:Asp.net mvc ASP.NETMVC新手的IoC容器障碍,asp.net-mvc,dependency-injection,inversion-of-control,structuremap,ninject,Asp.net Mvc,Dependency Injection,Inversion Of Control,Structuremap,Ninject,我必须承认,我是ASP.NETMVC新手,目前正在研究如何启动我的新项目的所有最佳实践。到目前为止,我已经理解了存储库模式和工作单元的概念,并且已经讨论了依赖注入和控制反转(IoC)。在过去的两天里,我一直在研究这个问题,我得出结论,我喜欢两个IoC容器,它们是StructureMap和NInject,尽管两者都不完美,我还没有设法让StructureMap工作,尽管我喜欢轻量级语法 下面是我的应用程序的构造方式。首先,我的数据上下文和存储库有以下接口: public interface IDa
public interface IDataContext : IDisposable
{
IRepository<T> Repository<T>() where T : class;
void Commit();
}
public interface IRepository<T> where T : class
{
IEnumerable<T> GetAll();
IEnumerable<T> Find(Expression<Func<T, bool>> where);
T Single(Expression<Func<T, bool>> where);
void Insert(T entity);
void Delete(T entity);
}
公共接口IDataContext:IDisposable
{
i存储库(),其中T:class;
无效提交();
}
公共接口IRepository,其中T:class
{
IEnumerable GetAll();
IEnumerable Find(表达式where);
T单个(表达式,其中);
无效插入(T实体);
无效删除(T实体);
}
然后我有一个这样的LinqToSql实现:
public class LinqToSqlDataContext : IDataContext
{
private readonly DataContext _context;
public LinqToSqlDataContext(DataContext context)
{
_context = context;
}
public IRepository<T> Repository<T>() where T : class
{
return new LinqToSqlRepository<T>(_context);
}
public void Commit()
{
_context.SubmitChanges();
}
public void Dispose()
{
}
}
public class LinqToSqlRepository<T> : IRepository<T> where T : class
{
private readonly DataContext _context;
public LinqToSqlRepository(DataContext context)
{
_context = context;
}
public IEnumerable<T> GetAll()
{
return _context.GetTable<T>();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> where)
{
return _context.GetTable<T>().Where(where);
}
public T Single(Expression<Func<T, bool>> where)
{
return _context.GetTable<T>().SingleOrDefault(where);
}
public void Insert(T entity)
{
_context.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
_context.GetTable<T>().DeleteOnSubmit(entity);
}
}
公共类LinqToSqlDataContext:IDataContext
{
私有只读数据上下文_上下文;
公共LinqToSqlDataContext(DataContext上下文)
{
_上下文=上下文;
}
公共IRepository存储库(),其中T:class
{
返回新的LinqToSqlRepository(_上下文);
}
公共无效提交()
{
_context.SubmitChanges();
}
公共空间处置()
{
}
}
公共类LinqToSqlRepository:IRepository,其中T:class
{
私有只读数据上下文_上下文;
公共LinqToSqlRepository(DataContext上下文)
{
_上下文=上下文;
}
公共IEnumerable GetAll()
{
返回_context.GetTable();
}
公共IEnumerable查找(表达式where)
{
返回_context.GetTable().Where(Where);
}
公共T单(表达式,其中)
{
返回_context.GetTable().SingleOrDefault(其中);
}
公共无效插入(T实体)
{
_context.GetTable().InsertOnSubmit(实体);
}
公共作废删除(T实体)
{
_context.GetTable().DeleteOnSubmit(实体);
}
}
目前,我发现有两个地方需要使用我的数据上下文
public class MvcApplication : NinjectHttpApplication
{
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel(new ServiceModule());
// Gives my wrapper class access to the kernel instance
IoCContainer.Initialize(kernel);
return kernel;
}
public static void RegisterRoutes(RouteCollection routes)
{
...
}
}
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IDataContext>().To<LinqToSqlDataContext>().InRequestScope();
Bind<DataContext>().To<MyDataContext>().InRequestScope();
}
}
public static class IoCContainer
{
private static IKernel _kernel;
public static void Initialize(IKernel kernel)
{
_kernel = kernel;
}
public static T Get<T>()
{
return _kernel.Get<T>();
}
public static object Get(Type type)
{
return _kernel.Get(type);
}
}
public类mvcapapplication:NinjectHttpApplication
{
Application Started()上受保护的覆盖无效
{
RegisterAllAreas();
注册地址(RouteTable.Routes);
}
受保护的覆盖IKernel CreateKernel()
{
var kernel=新的标准内核(新的ServiceModule());
//允许我的包装器类访问内核实例
初始化(内核);
返回内核;
}
公共静态无效注册表项(路由收集路由)
{
...
}
}
内部类ServiceModule:NinjectModule
{
公共覆盖无效负载()
{
Bind().To().InRequestScope();
Bind().To().InRequestScope();
}
}
公共静态类IoCContainer
{
私有静态IKernel_内核;
公共静态void初始化(IKernel内核)
{
_内核=内核;
}
公共静态不获取()
{
返回_kernel.Get();
}
公共静态对象Get(类型)
{
return _kernel.Get(type);
}
}
这很有效。控制器构造函数现在自动将其依赖项连接起来,在我的数据注释属性中,我可以说:
var context = IoCContainer.Get<IDataContext>();
var context=IoCContainer.Get();
我喜欢NInject,但即使使用从NinjectHttpApplication继承的Global.asax.cs文件(它处理许多管道),我仍然觉得有很多事情需要删除
接下来我看了结构图。StructureMap没有自带内置的ControllerFactory,但生成一个非常简单。在测试期间,我已将其临时放置在Global.asax.cs文件中。以下是该文件的最终内容:
public class MvcApplication : HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory());
// Configure structure map
ObjectFactory.Initialize(x =>
{
x.For<IDataContext>()
.HttpContextScoped()
.Use<LinqToSqlDataContext>();
x.For<DataContext>()
.HttpContextScoped()
.Use<MyDataContext>();
});
}
protected void Application_EndRequest()
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
public static void RegisterRoutes(RouteCollection routes)
{
...
}
}
public class StructureMapControllerFactory : DefaultControllerFactory
{
public override IController CreateController(RequestContext requestContext, string controllerName)
{
try
{
var controllerType = base.GetControllerType(requestContext, controllerName);
return ObjectFactory.GetInstance(controllerType) as IController;
}
catch (Exception e)
{
return base.CreateController(requestContext, controllerName);
}
}
}
public类mvcapapplication:HttpApplication
{
受保护的无效应用程序\u Start()
{
RegisterAllAreas();
注册地址(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(新结构MapControllerFactory());
//配置结构图
ObjectFactory.Initialize(x=>
{
x、 For()
.HttpContextScoped()
.使用();
x、 For()
.HttpContextScoped()
.使用();
});
}
受保护的无效应用程序\u EndRequest()
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
公共静态无效注册表项(路由收集路由)
{
...
}
}
公共类结构MapControllerFactory:DefaultControllerFactory
{
公共重写IController CreateController(RequestContext RequestContext,string controllerName)
{
尝试
{
var controllerType=base.GetControllerType(requestContext,controllerName);
返回ObjectFactory.GetInstance(controllerType)作为IController;
}
捕获(例外e)
{
返回base.CreateController(requestContext,controllerName);
}
}
}
我还应该能够在我的data annotation属性中获取数据上下文的实例,方法是:
var context = ObjectFactory.GetInstance<IDataContext>();
var context=ObjectFactory.GetInstance();
对我来说,这在语法上确实感觉轻松多了。但是,当我运行我的应用程序时,它不工作
我想知道的是:
public class MvcApplication : NinjectHttpApplication
{
protected override void OnApplicationStarted()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel()
{
var kernel = new StandardKernel(new ServiceModule());
// Gives my wrapper class access to the kernel instance
IoCContainer.Initialize(kernel);
return kernel;
}
public static void RegisterRoutes(RouteCollection routes)
{
...
}
}
internal class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IDataContext>().To<LinqToSqlDataContext>().InRequestScope();
Bind<DataContext>().To<MyDataContext>().InRequestScope();
}
}
public static class IoCContainer
{
private static IKernel _kernel;
public static void Initialize(IKernel kernel)
{
_kernel = kernel;
}
public static T Get<T>()
{
return _kernel.Get<T>();
}
public static object Get(Type type)
{
return _kernel.Get(type);
}
}