我正在移植一个旧的类库,因此它可以多个目标.net4.0和.net标准。我需要在.net核心项目中使用相同的库。
图书馆严重依赖System.Web.Mvc
,我正在使用此处描述的策略1:
Upgrading ASP.NET Libraries to .NET Standard
我无法解决的错误是:
1 - 对'HtmlString类型的引用声称它是在'System.Web'中定义的,但是找不到它
2 - 'MvcHtmlString'不包含'ToHtmlString'的定义,也没有可以找到接受类型'MvcHtmlString'的第一个参数的扩展方法'ToHtmlString'(你是否缺少using指令或汇编引用?)
我创建了一个新的.net标准类库项目并将文件复制过来。这是我的csproj文件:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net40</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.AspNet.Mvc" Version="3.0.50813.1" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Web" />
</ItemGroup>
</Project>
我尝试将其添加到netstandard2.0
ItemGroup,但它没有帮助:
<Reference Include="System.Web" />
我需要做些什么来修复?我已经阅读了一些关于这个主题的内容,但它仍然令人困惑,我找到的链接也无济于事。
我最终只为.NET Core
使用了新的代码库。
我的.csproj
是这样的:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="1.1.0" />
</ItemGroup>
</Project>
正如@ NightOwl888解释的那样,我需要Microsoft.AspNetCore.Html.Abstractions
,因此我可以使用HtmlString
代替MvcHtmlString
。
Microsoft.AspNetCore.Mvc.ViewFeatures
是必要的,因此SelectExtensions
例如DropDownListFor
可能会返回与HtmlString
兼容的类型。
我还必须将所有HtmlHelper
替换为IHtmlHelper
,将ModelMetaData
替换为ModelExplorer
。
ModelMetadata.FromLambdaExpression
现在是ExpressionMetadataProvider.FromLambdaExpression
。
答案 0 :(得分:2)
如果库没有调用超出.NET Standard 2.0可用范围的任何功能,则兼容模式将起作用。
在.NET Standard上代替MvcHtmlString
,您可以按照this answer使用Microsoft.AspNetCore.Html.HtmlString
类型。
由于.NET 4.0中MvcHtmlString
的基类是HtmlString
,因此您应该返回HtmlString
,它将在两种情况下都有效(尽管您需要为每个引用一个不同的命名空间)。
#if NET40
using HtmlString = System.Web.HtmlString;
#else
using HtmlString = Microsoft.AspNetCore.Html.HtmlString;
#endif
您需要在netstandard2.0
定向引荐中引用Microsoft.AspNetCore.Html.Abstractions
才能使用该类型。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net40</TargetFrameworks>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
<PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.0.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Web" />
</ItemGroup>
</Project>
至于ToHtmlString()
,我很困惑Microsoft intends to do about it。但是,在#if NETSTANDARD2.0
和#endif
块之间添加扩展方法(或者有条件地包含在编译中的文件)在您的库中是一个非常直接的事情。
然而,正如John Skeet在评论中指出的那样,通过相同的API公开2种不同的类型可能不是最好的主意。您可能最好为.NET Framework和.NET Core制作单独的API,并将它们放在单独的以平台为目标的库中,这些库引用包含共享业务逻辑的.NET Standard
库。