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