为 ASP.NET 4 和 ASP.NET Core 1.0 创建一个 Nuget 包
Create one Nuget Package for both ASP.NET 4 & ASP.NET Core 1.0
我们有一个在 ASP.NET 4 中工作并使用 HttpContext.Current
的库。我们知道我们 但应该使用 IHttpContextAccessor
。
我们如何更改此库,以便我们 支持 ASP.NET 4(通过使用 HttpContext.Current
)和 ASP.NET 核心(IHttpContextAccessor
) 并打包为 one NuGet package?
一种可能:
创建三个库。
- 使用 HttpContext
- 使用 IHttpContextAccessor
- 从这些库之一加载的工厂。
1 和 2 具有相同的程序集名称,Factory 仅引用两者之一。
文件夹中一次只有两个程序集作为参考。参考文献中的工厂和其他两个中的一个。
创建包含所有三个程序集的 nuget 包。 1 和 2 放在不同的文件夹中,我们称它为 aspnet4 和 aspnet5。
包还包含 aspnet 项目使用的目标文件。目标文件根据 aspnet 项目中存在的 属性 将工厂和其中一个库复制到引用文件夹中。这个 属性 可能类似于 aspnet=aspnet5.
这可能太大了,可能存在更简单的解决方案。我会想一个更简单的解决方案。
示例代码
//4. AspNetUsageBaseClass Assembly
namespace AspNetUsage
{
//rest of code
public abstract AspNetUsageBaseClass
{
//rest of code
public abstract void HttpContextIHttpContextAccessor();
}
}
//1. AspNetUsage Assembly, Reference AspNetUsageBaseClass Assembly
using AspNetUsage;
public class AspNetUsage:AspNetUsageBaseClass
{
public override void HttpContextIHttpContextAccessor()
{
//HttpContext based code
}
}
//2. AspNetUsage Assembly, Reference AspNetUsageBaseClass Assembly
using AspNetUsage;
public class AspNetUsage:AspNetUsageBaseClass
{
public override void HttpContextIHttpContextAccessor()
{
//IHttpContextAccessor based code
}
}
现在共有3个程序集。一个底座 class 组件。另外两个实现特定功能。
内部 nuget 包结构应该是:
AspNetUsageBaseClass.dll
- 基础 class 程序集
AspNet4\AspNetUsage.dll
- HttpContext 程序集
AspNet5OrCore\AspNetUsage.dll
- IHttpContextAccessor 程序集
AspNet.target
- 这将导入到 asp 网络项目中,并根据 属性 的值提取两个 dll 之一。
在 AspNet 项目中,您将拥有:
AspNetUsageBaseClass context = new AspNetUsage();
context.HttpContextIHttpContextAccessor();
这不是基于 Factory
模式,但可以通过一些修改扩展到基于 Factory
模式。
我在没有VS的情况下用记事本打的逻辑可能会有些错误
如果您在 project.json
中定义了两个目标框架(如 aspnetcore
和 net451
),那么将创建两个单独的 dll 并放入 lib/aspnetcore
和 lib/net451
在 nuget 包里面。 Nuget 将根据使用包的项目的目标框架知道使用哪一个。
现在,您可以在库中使用 #ifdef
语句来区分代码的哪些部分应该只针对特定平台进行编译。
一个简单的例子:
using System;
namespace MyLib
{
#if NETFX
using HttpContext = System.Web.HttpContext;
#elif NETCORE
using HttpContext = Microsoft.AspNetCore.Http.HttpContext;
#endif
public class MyClass
{
public string GetUserAgent(HttpContext ctx)
{
return ctx.Request.Headers["User-Agent"];
}
public void WriteToResponse(HttpContext ctx, string text)
{
#if NETFX
ctx.Response.Output.Write(text);
#elif NETCORE
var bytes = System.Text.Encoding.UTF8.GetBytes(text);
ctx.Response.Body.Write(bytes, 0, bytes.Length);
#endif
}
}
}
要使这些开关起作用,您必须在 project.json:
中定义特定于框架的常量
"frameworks": {
"netcoreapp1.0": {
"buildOptions": {
"define": [
"NETCORE"
]
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Http": "1.0.0"
}
},
"net451": {
"buildOptions": {
"define": [
"NETFX"
]
},
"dependencies": {
"Microsoft.AspNet.WebApi": "5.2.3"
},
"frameworkAssemblies": {
"System.Web": "4.0.0.0"
}
}
},
请注意,这两个框架具有不同的依赖集。 HttpContext
为 netcoreapp 和 net451 编译时,这里将是不同的类型。幸运的是,这些类型具有非常相似的方法,因此通常您可以以相同的方式使用它们,而无需 #ifdef
s(如 GetUserAgent
)。其他时候,您将无法避免它(例如 WriteToResponse
)。
现在,在 AspNet Core 项目中,您可以像这样使用这个库:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (ctx, next) => {
var lib = new MyLib.MyClass();
var msg = lib.GetUserAgent(ctx);
lib.WriteToResponse(ctx, "user agent is: " + msg);
});
}
在旧的 AspNet MVC 中:
public class HomeController : Controller
{
public ActionResult Index()
{
var lib = new MyLib.MyClass();
var msg = lib.GetUserAgent(System.Web.HttpContext.Current);
lib.WriteToResponse(System.Web.HttpContext.Current, "user agent is: " + msg);
return new HttpStatusCodeResult(200);
}
}
上的完整源代码
答案是不可能。同样,您不能创建一个 NuGet 包来同时针对 MVC1 和 MVC2(两者都不是可用的 Nuget 包)
当然可以使用程序集绑定,但前提是没有重大更改。
Microsoft 在那里命名 ASP.NET 核心包 "AspNetCore",例如Microsoft.AspNetCore.Mvc vs Microsoft.AspNet.Mvc
我们有一个在 ASP.NET 4 中工作并使用 HttpContext.Current
的库。我们知道我们 IHttpContextAccessor
。
我们如何更改此库,以便我们 支持 ASP.NET 4(通过使用 HttpContext.Current
)和 ASP.NET 核心(IHttpContextAccessor
) 并打包为 one NuGet package?
一种可能:
创建三个库。
- 使用 HttpContext
- 使用 IHttpContextAccessor
- 从这些库之一加载的工厂。
1 和 2 具有相同的程序集名称,Factory 仅引用两者之一。
文件夹中一次只有两个程序集作为参考。参考文献中的工厂和其他两个中的一个。
创建包含所有三个程序集的 nuget 包。 1 和 2 放在不同的文件夹中,我们称它为 aspnet4 和 aspnet5。
包还包含 aspnet 项目使用的目标文件。目标文件根据 aspnet 项目中存在的 属性 将工厂和其中一个库复制到引用文件夹中。这个 属性 可能类似于 aspnet=aspnet5.
这可能太大了,可能存在更简单的解决方案。我会想一个更简单的解决方案。
示例代码
//4. AspNetUsageBaseClass Assembly
namespace AspNetUsage
{
//rest of code
public abstract AspNetUsageBaseClass
{
//rest of code
public abstract void HttpContextIHttpContextAccessor();
}
}
//1. AspNetUsage Assembly, Reference AspNetUsageBaseClass Assembly
using AspNetUsage;
public class AspNetUsage:AspNetUsageBaseClass
{
public override void HttpContextIHttpContextAccessor()
{
//HttpContext based code
}
}
//2. AspNetUsage Assembly, Reference AspNetUsageBaseClass Assembly
using AspNetUsage;
public class AspNetUsage:AspNetUsageBaseClass
{
public override void HttpContextIHttpContextAccessor()
{
//IHttpContextAccessor based code
}
}
现在共有3个程序集。一个底座 class 组件。另外两个实现特定功能。 内部 nuget 包结构应该是:
AspNetUsageBaseClass.dll
- 基础 class 程序集
AspNet4\AspNetUsage.dll
- HttpContext 程序集
AspNet5OrCore\AspNetUsage.dll
- IHttpContextAccessor 程序集
AspNet.target
- 这将导入到 asp 网络项目中,并根据 属性 的值提取两个 dll 之一。
在 AspNet 项目中,您将拥有:
AspNetUsageBaseClass context = new AspNetUsage();
context.HttpContextIHttpContextAccessor();
这不是基于 Factory
模式,但可以通过一些修改扩展到基于 Factory
模式。
我在没有VS的情况下用记事本打的逻辑可能会有些错误
如果您在 project.json
中定义了两个目标框架(如 aspnetcore
和 net451
),那么将创建两个单独的 dll 并放入 lib/aspnetcore
和 lib/net451
在 nuget 包里面。 Nuget 将根据使用包的项目的目标框架知道使用哪一个。
现在,您可以在库中使用 #ifdef
语句来区分代码的哪些部分应该只针对特定平台进行编译。
一个简单的例子:
using System;
namespace MyLib
{
#if NETFX
using HttpContext = System.Web.HttpContext;
#elif NETCORE
using HttpContext = Microsoft.AspNetCore.Http.HttpContext;
#endif
public class MyClass
{
public string GetUserAgent(HttpContext ctx)
{
return ctx.Request.Headers["User-Agent"];
}
public void WriteToResponse(HttpContext ctx, string text)
{
#if NETFX
ctx.Response.Output.Write(text);
#elif NETCORE
var bytes = System.Text.Encoding.UTF8.GetBytes(text);
ctx.Response.Body.Write(bytes, 0, bytes.Length);
#endif
}
}
}
要使这些开关起作用,您必须在 project.json:
中定义特定于框架的常量 "frameworks": {
"netcoreapp1.0": {
"buildOptions": {
"define": [
"NETCORE"
]
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0"
},
"Microsoft.AspNetCore.Http": "1.0.0"
}
},
"net451": {
"buildOptions": {
"define": [
"NETFX"
]
},
"dependencies": {
"Microsoft.AspNet.WebApi": "5.2.3"
},
"frameworkAssemblies": {
"System.Web": "4.0.0.0"
}
}
},
请注意,这两个框架具有不同的依赖集。 HttpContext
为 netcoreapp 和 net451 编译时,这里将是不同的类型。幸运的是,这些类型具有非常相似的方法,因此通常您可以以相同的方式使用它们,而无需 #ifdef
s(如 GetUserAgent
)。其他时候,您将无法避免它(例如 WriteToResponse
)。
现在,在 AspNet Core 项目中,您可以像这样使用这个库:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.Use(async (ctx, next) => {
var lib = new MyLib.MyClass();
var msg = lib.GetUserAgent(ctx);
lib.WriteToResponse(ctx, "user agent is: " + msg);
});
}
在旧的 AspNet MVC 中:
public class HomeController : Controller
{
public ActionResult Index()
{
var lib = new MyLib.MyClass();
var msg = lib.GetUserAgent(System.Web.HttpContext.Current);
lib.WriteToResponse(System.Web.HttpContext.Current, "user agent is: " + msg);
return new HttpStatusCodeResult(200);
}
}
上的完整源代码
答案是不可能。同样,您不能创建一个 NuGet 包来同时针对 MVC1 和 MVC2(两者都不是可用的 Nuget 包)
当然可以使用程序集绑定,但前提是没有重大更改。
Microsoft 在那里命名 ASP.NET 核心包 "AspNetCore",例如Microsoft.AspNetCore.Mvc vs Microsoft.AspNet.Mvc