我必须承认,我是ASP.Net MVC的新手,我目前正在研究如何开始我的新项目的所有最佳实践。到目前为止,我已经理解了存储库模式和工作单元的概念,并且我已经进入了依赖注入和控制反转(IoC)。在过去的2天里我一直在研究这个问题,并且我总结出有2个我喜欢的IoC容器,它们是StructureMap和NInject,尽管这两个容器都不是完美的,我还没有设法让StructureMap工作,尽管我喜欢光重量语法。IoC容器跨越ASP.Net MVC Newb
这是我的应用程序的构建方式。首先,我有我的数据上下文和存储库中的以下接口:
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);
}
然后我对此有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);
}
}
目前我已经找到了2个地方,我需要用我的数据上下文。
- 内的控制器构造
- 在数据标注属性(不能有一个构造函数)
我试图删除任何依赖关系,尽我的能力。请说你是否有任何建议。
现在到我的IoC容器实现。首先NInject我设法修改我的Global.asax.cs文件到以下几点:
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);
}
}
这工作得很好。该控制器构造函数现在自动他们之间的依赖有线起来,我的数据注释中属性我可以说:
var context = IoCContainer.Get<IDataContext>();
我喜欢NInject但即使有文件的Global.asax.cs从NinjectHttpApplication继承(其中处理很多管道的)我仍然觉得我很想去除很多事情。
接下来我看了一下StructureMap。 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);
}
}
}
我也应该能够得到一个实例,以我的数据注解属性中的数据方面:下面是该文件的最终内容
var context = ObjectFactory.GetInstance<IDataContext>();
这肯定感觉在语法上很多打火机对我来说。但是,当我运行我的应用程序不起作用。
我想知道以下几点:
- 无论我的模式是正确的。
- 哪个IoC容器是最好最容易使用的。如果NInject然后我正确地做这个,如果StructureMap那么我怎么能修复我收到的错误。
我知道这是很多,但我真的很感激,如果有人可以帮忙。谢谢。
*更少*如果你想要一个答案... – 2010-07-22 19:09:27
你必须做很多事情 - 使用IDataContext,IRepository,当你实际上只需要一个接口来定义方法和一个实现它的类。你不必把所有东西都捆起来,大约2到3次。在Ninject网站的源代码中查看使用Ninject实现的DI。 Nate Kohari在他的GitHub上有它。 – mare 2010-07-22 23:29:46