前情提要:

  现有一个网站框架,包括主体项目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摆出一万种姿势。

记录:如何使用ASP.NET Core和EnityFramework Core实现服务和数据分离的更多相关文章

  1. 【ASP.NET Core】EF Core - “影子属性” 深入浅出经典面试题:从浏览器中输入URL到页面加载发生了什么 - Part 1

    [ASP.NET Core]EF Core - “影子属性”   有朋友说老周近来博客更新较慢,确实有些慢,因为有些 bug 要研究,另外就是老周把部分内容转到直播上面,所以写博客的内容减少了一点. ...

  2. 用ASP.NET Core构建可检测的高可用服务--学习笔记

    摘要 随着现代化微服务架构的发展,系统故障的定位与快速恢复面临着诸多挑战,构建可检测的服务,帮助线上保障团队时刻掌控应用的运行状况越来越重要.本次分享会讲解如何让 ASP .NET Core 应用与现 ...

  3. asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密。

    原文:asp.net core 使用中间件拦截请求和返回数据,并对数据进行加密解密. GitHub demo https://github.com/zhanglilong23/Asp.NetCore. ...

  4. 使用 ASP.NET Core 3.1 的微服务开发指南

    使用 ASP.NET Core 3.1 的微服务 – 终极详细指南 https://procodeguide.com/programming/microservices-asp-net-core/ A ...

  5. asp.net core + mysql + ef core + linux

    asp.net core + mysql + ef core + linux 以前开发网站是针对windows平台,在iis上部署.由于这次需求的目标服务器是linux系统,就尝试用跨平台的.NET ...

  6. 003.ASP.NET Core tutorials--【Asp.net core 教程】

    ASP.NET Core tutorials Asp.net core 教程 2016-10-14 1 分钟阅读时长 本文内容 1.Building web applications 构建web应用 ...

  7. ASP.NET Core教程【二】从保存数据看特有属性与服务端验证

    前文索引: 在layout.cshtml文件中,我们可以看到如下代码: <a asp-page="/Index" class="navbar-brand" ...

  8. Asp.net Core中SignalR Core预览版的一些新特性前瞻,附源码(消息订阅与发送二进制数据)

    目录 SignalR系列目录(注意,是ASP.NET的目录.不是Core的) 前言 一晃一个月又过去了,上个月有个比较大的项目要验收上线.所以忙的脚不沾地.现在终于可以忙里偷闲,写一篇关于Signal ...

  9. ABP 教程文档 1-1 手把手引进门之 ASP.NET Core & Entity Framework Core(官方教程翻译版 版本3.2.5)

    本文是ABP官方文档翻译版,翻译基于 3.2.5 版本 官方文档分四部分 一. 教程文档 二.ABP 框架 三.zero 模块 四.其他(中文翻译资源) 本篇是第一部分的第一篇. 第一部分分三篇 1- ...

随机推荐

  1. hbase 面试问题汇总

    一.Hbase的六大特点: (1).表大:一个表可以有数亿行,上百万列. (2).无模式:每行都有一个可排序的主键和任意多的列,列可以根据需要动态增加,同一个表中的不同行的可以有截然不同的列. (3) ...

  2. Django ajax的简单使用、自定义分页器

    一. ajax初识 1. 前后端传输数据编码格式contentType 使用form表单向后端提交数据时,必须将form表单的method由默认的get改为post,如果提交的数据中包含文件,还要将f ...

  3. 拜托,别再问我什么是 B+ 树了

    前言 每当我们执行某个 SQL 发现很慢时,都会下意识地反应是否加了索引,那么大家是否有想过加了索引为啥会使数据查找更快呢,索引的底层一般又是用什么结构存储的呢,相信大家看了标题已经有答案了,没错!B ...

  4. 【笔记3-27】Python语言基础

    流程控制语句 if语句 input() if-else if-elif-else

  5. K折-交叉验证

    k-折交叉验证(k-fold crossValidation):在机器学习中,将数据集A分为训练集(training set)B和测试集(test set)C,在样本量不充足的情况下,为了充分利用数据 ...

  6. effective-java学习笔记---使用枚举类型替代整型常量34

    1.要将数据与枚举常量相关联,请声明实例属性并编写一个构造方法,构造方法带有数据并将数据保存在属性中. // Enum type with data and behavior public enum ...

  7. OpenCV-Python 光流 | 四十八

    目标 在本章中, 我们将了解光流的概念及其使用Lucas-Kanade方法的估计. 我们将使用cv.calcOpticalFlowPyrLK()之类的函数来跟踪视频中的特征点. 我们将使用cv.cal ...

  8. java——构造器理解

    构造器理解 什么是构造器 构造器也叫构造方法:用于对象的初始化: 写构造器注意事项 构造器名与类名一致:有返回值但是不能定义返回类型(返回值类型是本类,可以加一个空的return): 构造器的调用 通 ...

  9. 一个基于深度学习回环检测模块的简单双目 SLAM 系统

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12634631.html 写在前面 最近在搞本科毕设,关于基于深度学 ...

  10. [noip模拟]数字对<RMQ&二分>

    数字对 [题目描述] 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= ...