NetStandard2.0类库使用HttpContext兼容.NET Framework与Core的方案咨询
你的改造思路完全正确,是兼顾新旧两套框架、最小化迁移成本的合理方案,不需要重构原有业务逻辑,只需要补充.NET Framework侧的适配逻辑即可。
1. 基础类库依赖确认
你的.NetStandard 2.0类库需要安装Microsoft.AspNetCore.Http.Abstractions NuGet包,这个包兼容.NetStandard 2.0、.NET Framework 4.6.1+、.NET Core 2.0+所有目标框架,包含IHttpContextAccessor、HttpContext等核心抽象定义。
2. .NET Framework侧实现适配
你只需要在.NET Framework 4.8的项目中实现IHttpContextAccessor接口,把原生System.Web.HttpContext封装成适配类即可,也可以直接使用官方提供的适配包简化操作:
方案A:使用官方System.Web适配包(推荐)
安装Microsoft.AspNetCore.SystemWebAdapters.FrameworkServices NuGet包到你的.NET Framework 4.8项目,这个包已经内置了兼容.NET Framework的IHttpContextAccessor实现,直接在你的DI容器中注册即可:
// 以ASP.NET MVC的Unity DI为例,其他DI容器同理 container.RegisterSingleton<IHttpContextAccessor, SystemWebHttpContextAccessor>();
方案B:手动实现适配(不需要额外依赖)
如果不想引入额外包,自己手写适配也非常简单,用到多少属性就映射多少属性即可:
using Microsoft.AspNetCore.Http; using System.Web; public class SystemWebHttpContextAccessor : IHttpContextAccessor { public HttpContext HttpContext { get { var systemWebContext = HttpContext.Current; if (systemWebContext == null) return null; // 按需映射你实际用到的HttpContext属性即可 var coreContext = new DefaultHttpContext(); // 映射Query参数 foreach (var key in systemWebContext.Request.QueryString.AllKeys) { coreContext.Request.Query[key] = systemWebContext.Request.QueryString[key]; } // 映射Form参数 foreach (var key in systemWebContext.Request.Form.AllKeys) { coreContext.Request.Form[key] = systemWebContext.Request.Form[key]; } // 映射Session coreContext.Session = new SystemWebSessionWrapper(systemWebContext.Session); return coreContext; } set => throw new NotSupportedException(); } } // 用到Session的话补充Session包装类即可 public class SystemWebSessionWrapper : ISession { private readonly HttpSessionState _systemWebSession; public SystemWebSessionWrapper(HttpSessionState systemWebSession) => _systemWebSession = systemWebSession; public string this[string key] { get => _systemWebSession[key]?.ToString(); set => _systemWebSession[key] = value; } // 其他ISession接口方法按需实现,未用到的可以直接抛NotImplementedException }
3. 注册使用
.NET Framework侧的DI容器注册完IHttpContextAccessor的实现后,你改造后的.NetStandard基础类库就可以直接注入使用,和.NET Core侧的使用方式完全一致,不需要修改任何基础类库的代码。
如果你的静态HttpContext引用特别多,不想逐个修改构造函数注入,也可以在.NetStandard类库中提供一个静态兼容层进一步降低改造成本:
public static class HttpContextProvider { public static IHttpContextAccessor Accessor { get; set; } public static HttpContext Current => Accessor?.HttpContext; }
然后在.NET Core和.NET Framework的启动入口分别给HttpContextProvider.Accessor赋值DI容器中注册的IHttpContextAccessor实例,原有代码可以直接把HttpContext.Current替换为HttpContextProvider.Current即可。
内容的提问来源于stack exchange,提问作者samh1234

