Entity Framework 上下文工厂和循环引用
Entity Framework Context Factory And Cyclic References
我尝试为 entity framework 上下文创建一个工厂。
1。目标
在PersonDataService中(在程序集DataService中)我想要以下方法:
public void GetPerson(int id)
{
using(var context = this.contextFactory.Create<IPersonContext>())
{
var personRepository = this.repositoryFactory.Create<IPersonRepository>(context);
return personRepository.Get(id);
}
}
2。鉴于
在我们的项目中,有一个名为 DependencyInjection 的程序集,我们在其中设置所有统一配置,因此该程序集引用了很多项目,包括程序集 DataAccess 其中 entity framework 是。
ContextFactory 应如下所示:
public class ContextFactory : IContextFactory
{
public T Create<T>() where T : IDbContext
{
return UnityConfig.GetConfiguredContainer().Resolve<T>();
}
}
程序集 DependencyInjection 还引用了程序集 DataService.
3。问题
DataService <-- DependencyInjection
^ ^
| |
DataAccess --------------
- 如果我将
ContextFactory
放在程序集 DependencyInjection 中(因为我需要 Unity)我不能在 DataService.
- 如果我将
ContextFactory
放在程序集 DataAccess 中,我就无法在工厂中使用 Unity
解决此循环引用问题的最佳方法是什么?
提前致谢
编辑: 我想介绍 ContextFactory
的原因是,我想在我的验收测试中使用 InMemoryContext 并能够设置一个假的当调用 Create<T>
时 ContextFactory
到 return 此 InMemoryContext
好的,我想,问题在于决定使用一个组件来配置容器。我没有看到很多好处。
作为解决方案,我建议您使用以下项目结构:
- 创建具有 public 个接口的程序集
- 使用接口的内部实现创建程序集
- 在程序集 2 中配置 Unity 容器
- 使用 UnityContainerExtension 公开 Unity 容器配置 class
例子
组装 1:
public interface ISecurityService
{
SignInStatus SignIn(string email, string password, bool isPersistent);
void SignOut();
}
程序集 2:
internal sealed class SecurityService : ISecurityService
{
private readonly SignInManager<User, long> _signInManager;
public SecurityService(SignInManager<User, long> signInManager)
{
_signInManager = signInManager;
_signInManager.UserManager.UserValidator = new UserValidator<User, long>(_signInManager.UserManager)
{
AllowOnlyAlphanumericUserNames = false
};
}
public SignInStatus SignIn(string email, string password, bool isPersistent)
{
var status = _signInManager.PasswordSignIn(email, password, isPersistent, shouldLockout: false);
return status;
}
public void SignOut()
{
_signInManager.AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie,
DefaultAuthenticationTypes.TwoFactorCookie);
}
}
public sealed class ApplicationExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
Container.RegisterType<IPrincipal>(new InjectionFactory(c => HttpContext.Current.User));
Container.RegisterType<ISecurityService, SecurityService>(new PerRequestLifetimeManager());
}
}
程序集 3:
public class UnityConfig
{
public static void RegisterTypes(IUnityContainer container)
{
var container = new UnityContainer();
container.AddExtension(new ApplicationExtension());
//use container
}
}
优点:
- 您的接口是 public 并与实现分离
- 实现是内部的,只能通过接口使用
- 您从程序集公开已配置的容器
我尝试为 entity framework 上下文创建一个工厂。
1。目标
在PersonDataService中(在程序集DataService中)我想要以下方法:
public void GetPerson(int id)
{
using(var context = this.contextFactory.Create<IPersonContext>())
{
var personRepository = this.repositoryFactory.Create<IPersonRepository>(context);
return personRepository.Get(id);
}
}
2。鉴于
在我们的项目中,有一个名为 DependencyInjection 的程序集,我们在其中设置所有统一配置,因此该程序集引用了很多项目,包括程序集 DataAccess 其中 entity framework 是。
ContextFactory 应如下所示:
public class ContextFactory : IContextFactory
{
public T Create<T>() where T : IDbContext
{
return UnityConfig.GetConfiguredContainer().Resolve<T>();
}
}
程序集 DependencyInjection 还引用了程序集 DataService.
3。问题
DataService <-- DependencyInjection
^ ^
| |
DataAccess --------------
- 如果我将
ContextFactory
放在程序集 DependencyInjection 中(因为我需要 Unity)我不能在 DataService. - 如果我将
ContextFactory
放在程序集 DataAccess 中,我就无法在工厂中使用 Unity
解决此循环引用问题的最佳方法是什么?
提前致谢
编辑: 我想介绍 ContextFactory
的原因是,我想在我的验收测试中使用 InMemoryContext 并能够设置一个假的当调用 Create<T>
时 ContextFactory
到 return 此 InMemoryContext
好的,我想,问题在于决定使用一个组件来配置容器。我没有看到很多好处。
作为解决方案,我建议您使用以下项目结构:
- 创建具有 public 个接口的程序集
- 使用接口的内部实现创建程序集
- 在程序集 2 中配置 Unity 容器
- 使用 UnityContainerExtension 公开 Unity 容器配置 class
例子
组装 1:
public interface ISecurityService
{
SignInStatus SignIn(string email, string password, bool isPersistent);
void SignOut();
}
程序集 2:
internal sealed class SecurityService : ISecurityService
{
private readonly SignInManager<User, long> _signInManager;
public SecurityService(SignInManager<User, long> signInManager)
{
_signInManager = signInManager;
_signInManager.UserManager.UserValidator = new UserValidator<User, long>(_signInManager.UserManager)
{
AllowOnlyAlphanumericUserNames = false
};
}
public SignInStatus SignIn(string email, string password, bool isPersistent)
{
var status = _signInManager.PasswordSignIn(email, password, isPersistent, shouldLockout: false);
return status;
}
public void SignOut()
{
_signInManager.AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie,
DefaultAuthenticationTypes.TwoFactorCookie);
}
}
public sealed class ApplicationExtension : UnityContainerExtension
{
protected override void Initialize()
{
Container.RegisterType<IAuthenticationManager>(new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
Container.RegisterType<IPrincipal>(new InjectionFactory(c => HttpContext.Current.User));
Container.RegisterType<ISecurityService, SecurityService>(new PerRequestLifetimeManager());
}
}
程序集 3:
public class UnityConfig
{
public static void RegisterTypes(IUnityContainer container)
{
var container = new UnityContainer();
container.AddExtension(new ApplicationExtension());
//use container
}
}
优点:
- 您的接口是 public 并与实现分离
- 实现是内部的,只能通过接口使用
- 您从程序集公开已配置的容器