我正在尝试使用 CoreRT 将我的代码(.NET Core 控制台应用程序)编译为 win-x64 的本机 EXE 文件。 我能够一直遵循文档,直到与反射和使用 rd.xml 文件有关的部分,这就是我目前陷入困境的地方。
我的项目使用 Dapper 作为 ORM,它依赖反射来绑定数据库中的对象。 我只有两种不同的类型要绑定,所以我的假设是我需要将这些类型包含在 rd.xml 文件中。
现在,当我尝试从 .NET Core CLI 运行
dotnet publish -r win-x64 -c release
时,它成功完成。但是,在运行时,我编译的 .exe 会引发异常,并显示以下代码片段:
--->(内部异常#0)System.TypeInitializationException:类型初始值设定项引发异常。要确定哪种类型,请检查 InnerException 的 StackTrace 属性。 ---> EETypeRva:0x01202268(System.Reflection.MissingRuntimeArtifactException): 无法调用该对象,因为它已启用元数据 仅浏览: 'Dapper.SqlMapper.TypeHandlerCache
.SetHandler(Dapper.SqlMapper.ITypeHandler)' 欲了解更多信息,请访问 http://go.microsoft.com/fwlink/?LinkID=616867
我的 rd.xml 文件如下所示:
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<Type Name="Dapper.SqlMapper.TypeHandlerCache{System.Data.DataTable}">
<MethodInstantiation Name="SetHandler" Arguments="Dapper.SqlMapper.ITypeHandler" Dynamic="Required" />
</Type>
</Application>
</Directives>
我认为我需要在此处包含对我的模型的引用,即
Foo
和 Bar
,但引发的错误具体指的是 Dapper。
rd.xml 文件位于我的项目目录中,并在 MyProject.csproj 文件中引用,如下所示:
<ItemGroup> <EmbeddedResource Include="rd.xml" /> </ItemGroup>
我想知道这个问题是否是由于我的结构造成的(也许 rd.xml 应该以不同的方式引用),或者是由于我的 rd.xml 文件的内容造成的。 有没有人处理过这个问题,或者在使用 Dapper 的项目中使用过 CoreRT?
尝试将其添加到指令中:
<Assembly Name="System.Data.Common">
<Type Name="System.Data.DataTable" Dynamic="Required All"/>
</Assembly>
要成功编译我的项目,我必须执行以下操作:
将 System.Data.SqlClient nuget 包中的所有引用包含为项目引用。在本例中,我还包括了 System.Configuration.ConfigurationManager 的那些。
从命令行发布所需操作系统:dotnetpublish -r win-x64
从发布路径将System.Data.SqlClient.dll和sni.dll文件复制到固定路径:..\SQLClient\win-x64\
在 csproj 文件中对 nuget 包和发布的 dll 进行条件引用,在本例中是通过参数 MSBuild NativeCompilation。
最后,从命令行使用 CoreRT 进行发布: dotnetpublish -r win-x64 / p: NativeCompilation = true
而且成功了!
获取IPVersionSQLSRV.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<OutputType>Exe</OutputType>
</PropertyGroup>
<ItemGroup Condition="'$(BuildingInsideVisualStudio)' == 'true' OR '$(NativeCompilation)' != 'true'">
<!--System.Data.SqlClient Nuget Reference -->
<PackageReference Include="System.Data.SqlClient" Version="4.6.1" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="4.5.0" />
<!--System.Data.SqlClient References-->
<PackageReference Include="Microsoft.Win32.Registry" Version="4.5.0" />
<PackageReference Include="System.Security.AccessControl" Version="4.5.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="4.5.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.0" />
<!--System.Configuration.ConfigurationManager References-->
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="4.5.0" />
<PackageReference Include="System.Security.Permissions" Version="4.5.0" />
</ItemGroup>
<ItemGroup Condition="'$(BuildingInsideVisualStudio)' != 'true' AND '$(NativeCompilation)'=='true'">
<!-- ILCompiler and rd.xml -->
<PackageReference Include="Microsoft.DotNet.ILCompiler" Version="1.0.0-alpha-*" />
<RdXmlFile Include="rd.xml" />
<!--System.Data.SqlClient published Dll Reference -->
<Reference Include="System.Data.SqlClient">
<HintPath>..\SQLClient\win-x64\System.Data.SqlClient.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
程序.cs
using System;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Net;
namespace GetIPVersionSQLSRV
{
class Program
{
private static String config = ConfigurationManager.AppSettings["texto"];
private static String cadena = ConfigurationManager.ConnectionStrings["default"].ConnectionString;
static void Main(string[] args)
{
Console.WriteLine("Hello World! " + config);
using(SqlConnection conn = new SqlConnection(cadena))
{
conn.Open();
using (SqlCommand comm = new SqlCommand("SELECT @@VERSION;", conn))
Console.WriteLine(comm.ExecuteScalar());
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(@"http://api.ipify.org?format=json");
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
using (Stream strm = res.GetResponseStream())
using (StreamReader read = new StreamReader(strm))
Console.WriteLine(read.ReadToEnd());
req = null;
Console.ReadKey(false);
}
}
}
应用程序配置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="texto" value="CONFIG2"/>
</appSettings>
<connectionStrings>
<add name="default" connectionString="User ID=user;PWD=p455w0rd;Initial Catalog=master;Data Source=localhost"/>
</connectionStrings>
</configuration>
rd.xml
<Directives>
<Application>
<Assembly Name="System.Configuration.ConfigurationManager">
<Type Name="System.Configuration.ClientConfigurationHost" Dynamic="Required All"/>
<Type Name="System.Configuration.AppSettingsSection" Dynamic="Required All"/>
</Assembly>
</Application>
</Directives>
nuget.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<add key="dotnet-core"
value="https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json"/>
<add key="nuget.org"
value="https://api.nuget.org/v3/index.json" protocolVersion="3"/>
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>