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的帖子。