当前位置: 移动技术网 > IT编程>软件设计>领域驱动 > 记录:如何使用ASP.NET Core和EnityFramework Core实现 数据库操作 和 数据库实体 的项目分离

记录:如何使用ASP.NET Core和EnityFramework Core实现 数据库操作 和 数据库实体 的项目分离

2020年04月20日  | 移动技术网IT编程  | 我要评论

前情提要:

  现有一个网站框架,包括主体项目webapp一个,包含 iidentityuser 接口的基架项目 a。用于处理用户身份验证的服务 authenticationservice 位于命名空间b。用于保存数据的实体 user : iidentityuser 位置项目c。项目之间的关系是b和c依赖项目a。

 

需求:

  现在有一个新项目d,在这个项目里有一个duser : iidentityuser 。如何处理才能最优雅的在不添加引用和修改项目b的前提下,将用户保存至duser。

 

实际例子:

  在asp.net core中,有一个东西叫identityserver。里面就有这个东西,他写的是类似identityserverbuilder.addservice<tuser, trole>()这种代码,如何实现?

 

解决方案:

  1、新建一个泛类(这个类可以标记为internal,外部不需要了解,也不需要访问):

public class usercontext<tuser>
        where tuser : class, iidentityuser, new ()
    {
        public yourcontext dbcontext;
        public usercontext(yourcontext ctx) => dbcontext = ctx;

        public dbset<tuser> users
        {
            get
            {
                return dbcontext.set<tuser>();
            }
        }

        public void savechanges()
        {
            dbcontext.savechanges();
        }
    }

  2、新建一个用以操作的服务(注意,所有需要的操作都往这个里面写,未来暴露的也是这个接口)

public class userservice<tuser> : iuserservice
        where tuser: class, iidentityuser, new()
    {
        private usercontext<tuser> dbcontext;
        public userservice(yourcontext ctx, iserviceprovider provider)
        {
            dbcontext = new permissioncontext<tuser>(ctx.dbcontext);
        }
     
   public tuser getuserbyid(guid id)
   {
      return dbcontext.users.firstordefault(e => e.id == id);
   }
    }

  

  3、添加一个注射器

    public static class authenticationinject
    {
        public static iservicecollection addauthenticationcontext<tuser>(this iservicecollection services)
            where tuser: iidentityuser
        {
            var servicetype = typeof(userservice<>).makegenerictype(typeof(tuser));
            services.addsingleton(typeof(iuserservice), servicetype );

            return services;
        }
    }

  技术点:使用makegenerictype方法可以动态加载泛类实例。如果类型是 userservice<tuser, trole>,则写成 typeof(userservice<,>).makegenerictype(typeof(t1), typeof(t2))

  至此,我们就已经将泛类的类型名拆到了变量里面。然后就可以玩出一万种花样了。

  4、在webapp里,注入相关变量

        // this method gets called by the runtime. use this method to add services to the container.
        // for more information on how to configure your application, visit https://go.microsoft.com/fwlink/?linkid=398940
        public void configureservices(iservicecollection services)
        {
            services.addauthenticationcontext<duser>();
        }

  

  分析依赖关系:

  执行项目webapp依赖a,b,d,b和d项目只依赖a。甚至于,这里还能再解耦。把函数addauthenticationcontext从泛型函数改成 addauthenticationcontext(type usertype),还可以再进一步,改成addauthenticationcontext(string type),通过反射和配置来取类型,做到a项目和d项目解耦。

  扩展性:

  在未来,有新项目e,euser。只需要将d和a解除分离,再将e和a进行关联。只需要修改 addauthenticationcontext 函数,即可满足要求。当然,如果要有心情,你甚至可以搞一个自动发现的代码(比如我项目里就是这么搞的,自动分析iidentityuser的对象,然后附加给context,为了保证有多个实现时能正确附加,我做了一个attribute用来标记这个项目要用哪个user)。再有心情还可以做成配置式的,反正你可以把ef core摆出一万种姿势。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网