前情提要:

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

最新文章

  1. hiho #1372:平方求 (bfs)
  2. out 和 ref 之间的区别整理
  3. hdu 5587 规律
  4. 147. Insertion Sort List
  5. C#sqlbulkcopy的优化
  6. Socket程序中的Error#10054错误
  7. 每个项目单独配置 git 用户
  8. ant编译java的例子
  9. Python学习笔记(九)
  10. Cmake 学习笔记
  11. BFS 模拟队列(水题)
  12. 魅族pro 7详细打开Usb调试模式的方法
  13. ab压力测试工具的使用
  14. Shell for while 循环
  15. Hadoop 部署文档
  16. [转]memcached+magent实现memcached集群
  17. 将一个list转成json数组-晚上坐49路回去打卡
  18. commons.httpclient-3.X.jar 和 httpclient-4.x.jar是个什么关系?
  19. CCF CSP 201312-3 最大的矩形
  20. SPOJ375 Query on a tree 【倍增,在线】

热门文章

  1. Error while importing sbt project:--创建sbt项目导入文件出错
  2. Python-列表做的购物车小程序
  3. Asp.Net Core 中IdentityServer4 实战之角色授权详解
  4. [模拟] Codeforces - 1191C - Tokitsukaze and Discard Items
  5. 洛谷P1003 铺地毯 模拟
  6. Electron 踩坑记录- require is not defined
  7. macOS 去掉系统软件更新红点提示
  8. ESPCMS-Seay自动加手工代码审计
  9. 生产-消费者,C++11实现
  10. windows远程桌面内部错误的处理方法