前情提要:

  现有一个网站框架,包括主体项目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. VMware Tools失效的处理方案

    VMware Tools是一个实现主机与虚拟机文件分享,具有可支持自由拖拽的功能的工具,如果没有VM tools,那么没有了复制粘贴切换的虚拟机是很不方便的. 长时间未开的虚拟机,一次尝试拖拽Wind ...

  2. 【狂神说】JAVA Mybatis 笔记+源码

    简介 自学的[狂神JAVA]MyBatis GitHub源码: https://github.com/Donkequan/Mybatis-Study 分享自写源码和笔记 配置用的 jdk13.0.2 ...

  3. 使用PostgreSQL注意事项

    一.大小写特别敏感 大写字段需要用“”引号(pg字段名使用“”,MySQL字段名使用``) ******表名以及字段名如果是小写但是为关键字,比如name,则也需使用"": 二.分 ...

  4. 我国三大坐标系的区别(西安80、北京54、WGS-84)

    1.北京54坐标系(BJZ54) 北京54坐标系为参心大地坐标系,大地上的一点可用经度L54.纬度M54和大地高H54定位,它是以克拉索夫斯基椭球为基础,经局部平差后产生的坐标系. 1954年北京坐标 ...

  5. zookeeper java代码实现master 选举

    1,master选举使用场景及结构 现在很多时候我们的服务需要7*24小时工作,假如一台机器挂了,我们希望能有其它机器顶替它继续工作.此类问题现在多采用master-salve模式,也就是常说的主从模 ...

  6. Redis启动出现creating server tcp listening socket错误

    错误如图所示 解决方法 在命令行中运行 redis-cli.exe 127.0.0.1:6379>shutdown not connected>exit 然后重新运行redis-serve ...

  7. SQL 实习

    一. tem表 group by 分组后,有三个编号,找出最下的订单时间,比较选出时间段内的数据.注意group by 和 having的用法. group by 的用法 不用聚合函数的时候,每类出现 ...

  8. Codeforces Round #565 (Div. 3)--D. Recover it!--思维+欧拉筛

    D. Recover it! Authors guessed an array aa consisting of nn integers; each integer is not less than ...

  9. 关于代码覆盖 or 冲突

    关于代码覆盖 or 冲突 在使用git同步代码时,步骤一般为 commit -> pull -> push 那这个过程的意义何在呢? 首先是区分本地仓库 与 远程仓库,可以理解为本地git ...

  10. Java中的数据结构-HashMap

    Java数据结构-HashMap 目录 Java数据结构-HashMap 1. HashMap 1.1 HashMap介绍 1.1.1 HashMap介绍 1.1.2 HashMap继承图 1.2 H ...