0

到目前爲止,我有如下安裝程序:如何使用DI與Castle正確實例化EF Object Data Context?

/// <summary> 
/// Registers all repositories. 
/// </summary> 
public class RepositoryInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(
      AllTypes.FromAssemblyContaining<EntityFrameworkLinkRepository>() 
       .BasedOn<IRepository>() 
       .WithService.Select(ByConvention) 
       .Configure(WithDependencies) 
       .LifestylePerWebRequest() 
      ); 
    } 

    private IEnumerable<Type> ByConvention(Type type, Type[] types) 
    { 
     if (type.BaseType == null || !type.Name.EndsWith(type.BaseType.Name)) 
     { 
      return Enumerable.Empty<Type>(); 
     } 
     return new[] { type.BaseType }; 
    } 

    private void WithDependencies(ComponentRegistration component) 
    { 
     Type type = component.Implementation; 
     string key; 
     if (type.BaseType == null || !type.Name.EndsWith(type.BaseType.Name)) 
     { 
      key = type.Name; 
     } 
     else 
     { 
      key = type.Name.Substring(0, type.Name.Length - type.BaseType.Name.Length); 
     } 
     component.DependsOn(new 
     { 
      connectionString = ConnectionString(key) 
     }); 
    } 

    private string ConnectionString(string key) 
    { 
     string connectionString = Config.GetConnectionString(key); 
     return connectionString; 
    } 
} 

它解決了倉庫。

現在,倉庫被實例化這樣的:

public class EntityFrameworkLinkRepository : LinkRepository 
{ 
    private readonly ObjectDataContext context; // TODO shouldn't this be receiving a lifetimed ODC, instead of just the connString? 

    public EntityFrameworkLinkRepository(string connectionString) 
    { 
     if (connectionString == null) 
     { 
      throw new ArgumentNullException("connectionString"); 
     } 
     this.context = new ObjectDataContext(connectionString); 
    } 

// etc... 

我在這裏的問題是,我應該如何解決對象數據的上下文,而不僅僅是創建一個新的(甚至不處置的話),使用DI通過Castle解決EF數據上下文的正確方法是什麼?

我想我會喜歡ODC跨越,涉及到同一個網頁請求的所有庫共享(這將是最有意義,以我的方式,對吧?)

但因爲我實現的ObjectContext特定於EntityFramework,我對於如何解決它有點失落,我是否應該明確註冊它?

container.Register(
    Component 
    .For<ObjectDataContext>() 
    .DependsOn(new 
    { 
     connectionString = ConnectionString("EntityFramework") 
    }) 
    .ImplementedBy<ObjectDataContext>() 
); 

回答

4

像這樣的東西應該工作:

container.Register(
    .Component.For<ObjectDataContext>() 
    .DependsOn(
     Dependency.OnValue(
      "connectionString", ConnectionString("EntityFramework"))) 
    .LifeStyle.PerWebRequest); 
2

您應該爲ObjectDataContext提供一個構造函數參數。如果你使用的是MVC,你還應該實現一個WindsorControllerFactory,所有你的控制器都是由Windsor創建的,並且爲你創建了任何構造器依賴關係。你不需要創建任何「服務」的實例

你如何註冊你的ObjectDataContext真的取決於你寫什麼接口/類,取決於它。所以,如果你已經將你的代碼寫入了ObjectDataContext本身,那麼你給出的例子就沒有問題。但是,如果你寫一個接口上,那麼就需要像這樣...

container.Register(
    Component 
     .For<IObjectDataContext>() 
     .ImplementedBy<ObjectDataContext>() 
     .DependsOn(new { connectionString = ConnectionString("EntityFramework") }) 
     .LifeStyle.PerWebRequest 
); 
+0

我有一個類似的問題,我使用的是註冊就像你推薦的那樣。你可以看看[我的問題](http://stackoverflow.com/questions/13271787/how-to-register-ef-objectcontext-with-castle-windsor-perwebrequest-lifestyle) – Rich 2012-11-07 21:04:16