实体框架上下文工厂和循环引用

时间:2017-09-27 07:57:08

标签: c# .net entity-framework refactoring unity-container

我尝试为实体框架上下文创建工厂。

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 的程序集,我们设置了所有的unity配置,因此这个程序集引用了很多项目,包括程序集 DataAccess where entity框架是。

ContextFactory应该如下所示:

public class ContextFactory : IContextFactory
{
    public T Create<T>() where T : IDbContext
    {
        return UnityConfig.GetConfiguredContainer().Resolve<T>();
    }
}

程序集 DependencyInjection 还有一个程序集 DataService 的引用。

3。问题

  

DataService&lt; - DependencyInjection
  ^ ^
  | |
  DataAccess --------------

  • 如果我将ContextFactory放入程序集 DependencyInjection (因为我需要Unity),我不能在 DataService 中使用它。
  • 如果我将ContextFactory放入程序集 DataAccess ,我就无法在工厂中使用Unity

解决此循环引用问题的最佳方法是什么?

提前致谢

编辑:我想介绍ContextFactory的原因是,我想在验收测试中使用InMemoryContext,并能够设置假{{1}当调用ContextFactory时发生

,返回此InMemoryContext

1 个答案:

答案 0 :(得分:1)

好吧,我认为,问题在于决定为容器配置安装一个程序集。我没有看到很多好处。

作为解决方案,我建议您使用以下项目结构:

  1. 使用公共接口创建程序集
  2. 创建具有接口内部实现的程序集
  3. 装配2中的Confugure Unity-container
  4. 使用UnityContainerExtension类公开Unity容器配置
  5. 实施例

    资料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
        }
    }
    

    优点:

    1. 您的界面是公开的,与实施分开
    2. 实施是内部的,只能通过接口
    3. 使用
    4. 您从程序集
    5. 公开已配置的容器