1

我正在尝试使用CoreRT将我的代码(.net 核心控制台应用程序)编译为 win-x64 的本机 .exe 。我能够一直关注文档,直到与反射有关的部分和使用 rd.xml 文件,这是我目前卡住的地方。

我的项目使用Dapper作为 ORM,它依赖于反射来绑定数据库中的对象。我只绑定了 2 种不同的类型,所以我的假设是我需要在 rd.xml 中包含这些类型。

现在,当我尝试dotnet publish -r win-x64 -c release从 .net 核心 cli 运行时,它成功完成,但是在运行时,我编译的 .exe 会引发异常,并带有以下代码段:

--->(内部异常 #0)System.TypeInitializationException:类型初始化程序引发了异常。要确定哪种类型,请检查 InnerException 的 StackTrace 属性。---> EETypeRva:0x01202268(System.Reflection.MissingRuntimeArtifactException):无法调用此对象,因为它已启用元数据以供浏览:'Dapper.SqlMapper.TypeHandlerCache<System.Data.DataTable>.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>

我假设我需要在此处包含对我的模型的引用,这将是Fooand Bar,但是抛出的错误专门针对 Dapper。

rd.xml 文件位于我的项目目录中,并在 MyProject.csproj 中被引用,如下所示:

<ItemGroup> <EmbeddedResource Include="rd.xml" /> </ItemGroup>

我想知道这个问题是由于我的结构(也许应该以不同的方式引用 rd.xml),还是由于我的 rd.xml 文件的内容。有没有人处理过这个问题,或者在使用 Dapper 的项目中使用过 CoreRT?

4

2 回答 2

1

尝试将此添加到指令中:

<Assembly Name="System.Data.Common">
    <Type Name="System.Data.DataTable" Dynamic="Required All"/>
</Assembly>
于 2019-05-15T15:36:26.280 回答
1

要成功编译我的项目,我必须执行以下操作:

  • 将 System.Data.SqlClient nuget 包中的所有引用包括为项目引用。在这种情况下,我还包括了 System.Configuration.ConfigurationManager 的那些。

  • 从所需操作系统的命令行发布:dotnet publish -r win-x64

  • 从发布路径复制 System.Data.SqlClient.dll 和 sni.dll 文件到固定路径:..\SQLClient\win-x64\

  • 在 csproj 文件中,对 nuget 包和已发布的 dll 进行条件引用,在这种情况下,通过参数 MSBuild NativeCompilation。

  • 最后,从命令行使用 CoreRT 发布:dotnet publish -r win-x64 / p: NativeCompilation = true

它奏效了!


GetIPVersionSQLSRV.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>
于 2019-05-20T15:58:47.183 回答