1

我必须承认,我是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个地方,我需要用我的数据上下文。

  1. 内的控制器构造
  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>(); 

这肯定感觉在语法上很多打火机对我来说。但是,当我运行我的应用程序不起作用。

我想知道以下几点:

  1. 无论我的模式是正确的。
  2. 哪个IoC容器是最好最容易使用的。如果NInject然后我正确地做这个,如果StructureMap那么我怎么能修复我收到的错误。

我知道这是很多,但我真的很感激,如果有人可以帮忙。谢谢。

+1

*更少*如果你想要一个答案... – 2010-07-22 19:09:27

+0

你必须做很多事情 - 使用IDataContext,IRepository,当你实际上只需要一个接口来定义方法和一个实现它的类。你不必把所有东西都捆起来,大约2到3次。在Ninject网站的源代码中查看使用Ninject实现的DI。 Nate Kohari在他的GitHub上有它。 – mare 2010-07-22 23:29:46

回答

1

与MVC的店面系列SM建立ASP.NET MVC这里有一个很好的video

在我的项目中,我使用Autofac,并拥有所有我的容器逻辑在Bootsrapper.cs文件。然后在我的global.asax.cs它只是一个呼叫设置的IoC和属性来获取容器

private static IContainerProvider _containerProvider; 

public IContainerProvider ContainerProvider 
{ 
    get { return _containerProvider; } 
} 

protected void Application_Start() 
{ 
    // snip.. 

    _containerProvider = Bootstrapper.ConfigureAutofac(); 

    // snip.. 
} 

我不从LinqToSQL或Autofac移开计划,所以我没有打扰抽象访问任何一个组件都离开了。

+0

嗨,谢谢你的回复。 Autofac看起来很有前途。我现在就去用它。干杯 – nfplee 2010-07-26 10:18:18

0

用一粒盐拿这一点,但如果你只是习惯了MVC的IoC也许起初是有点大材小用。如果我刚刚开始,我不认为我起初会担心这一点。即使是标准入门教程的NerdDinner应用程序也不会使用IoC。 哎呀,它甚至不使用View类,它只是在视图中访问上下文。

我没有看到在您的文章一个错误的任何参考,但如果是我我就跳过国际奥委会现在只是专心学习MVC。

0

我的第一次扫描显示你正在比较服务位置在SM和NI之间是多么容易。这是一个错误的问题 - Ninject故意不以某种方式展现这一点 - 它试图让你陷入成功之坑(而且SM也应该 - 人们不会阅读文档,直到它不幸为时已晚)。使用搜索引擎查找服务位置与依赖注入。

我认为DI是足够重要的,你应该试着理解它,所以你可以明智地选择它对你是否重要,即使它没有公然清楚地表明它在小样本中是必要的。

我个人非常期待阅读并能够推荐(我毫不怀疑这将会是一本非常好的重要书籍)Dependency Injection in Action(它还没有写在纸上)。同时,我建议阅读所有Ninject帖子和Mark Seemann的帖子。