NET Core 从 DLL 加载接口获取错误找不到文件(VS2017 RC)

NET Core loading interfaces from DLL get error can't find the file (VS2017 RC)

在尝试从单独的 DLL(项目是同一解决方案的一部分)加载接口时,使用 Visual Studio 2017RC(1 月 27 日构建)的 dotnet 核心 c# 控制台应用程序遇到很多问题。我按照 Visual Studio 2017RC 说明在此处设置 dotnet 核心:https://www.microsoft.com/net/core#windowsvs2017

主要应用:

public class Core
{
    public static void Main(string[] args)
    {
    Console.WriteLine("Starting...");
        // Setup PubSub                      
        var pubSub = new PubSub();
    }
}

public class PubSub : IPubSub
{
    // Subscription table
    private static ConcurrentDictionary<ChannelKey, ChannelSub> subscriptions = new ConcurrentDictionary<ChannelKey, ChannelSub>();

    // User group table
    private static ConcurrentDictionary<string, List<string>> clientGroups = new ConcurrentDictionary<string, List<string>>();

    public PubSub()
    {
        try
        {
            List<string> users = new List<string>();
            clientGroups["ADMINS"] = new List<string> { "PubSub.myClient" };
            AddUpdChannel(new ChannelKey
            {
                network = Core.networkName,
                category = "LIGHTING",
                className = "CBUS",
                instance = "MASTERCOCOON"
            }, new ChannelSub
            {
                auth = new List<AccessAttribs>
            {
                new AccessAttribs
                {
                    name = "ADMINS",
                    access = "RW"
                }
            },
                clients = new List<AccessAttribs>
            {
                new AccessAttribs
                {
                    name = "PubSub.myClient",
                    access = "RW"
                }
            }
            });

            Subscribe("myClient", new ChannelKey
            {
                network = Core.networkName,
                category = "LIGHTING",
                className = "CBUS",
                instance = "MASTERCOCOON"
            });
        }
        catch (Exception ex)
        {

            throw ex;
        }
    }

    public bool Publish(string clientName, ChannelKey channel, string message, [CallerFilePath] string caller = "")
    {
        Logger.LogInformation("Client: " + clientName + " published to: " + channel.instance + " TEST");
        return true;
    }

    // Channels must be created before subscribed to.
    public bool AddUpdChannel(ChannelKey channel, ChannelSub channelSub, [CallerMemberName] string caller = "")
    {
        channelSub.author = caller;                                                             // Enforce author as caller, regardless of setting passed.
        subscriptions[channel] = channelSub;
        return true;
    }

    // Subscribe to channel for Ext/Plug.Client. Return null if channel does not exist else return access rights ("", R, RW) and update any old entries or add new
    public string Subscribe(string clientName, ChannelKey channel, [CallerFilePath] string caller = "")
    {
        string access = "";
        var fullClientName = Path.GetFileNameWithoutExtension(caller) + "." + clientName;

        if (subscriptions.TryGetValue(channel, out var subscription))                           // Get channel subscription info
        {
            foreach (var subGroup in subscription.auth)                                         // Get access rights for group client is a member of
            {
                clientGroups.TryGetValue(subGroup.name, out var clientGroup);                   // Lookup clients associated with group
                if (clientGroup.Contains(fullClientName))
                {
                    access = subGroup.access;
                    if (subGroup.access == "RW") break;                                         // RW access takes precidence if user is a member of multiple groups
                }
            }

            if (access != "")                                                                   // Some access allowed so setup
            {
                var newAccess = new AccessAttribs
                {
                    name = fullClientName,
                    access = access
                };
                var exists = subscription.clients.FindIndex(x => x.name == fullClientName);     // Look for fullClientName already in list (assume there could be any access strings)
                if (exists != -1)
                {
                    subscription.clients[exists] = newAccess;                                   // Update if existing
                }
                else
                {
                    subscription.clients.Add(newAccess);                                        // Add if new
                }
                subscriptions[channel] = subscription;                                          // Update subscription with new client access info
            }

            return access;
        }
        return null;                                                                            // subscription does not exist
    }
}

接口在单独的项目中定义如下:

namespace Interfaces
{
  public interface IExtension
  {
    string ExtStart(IPubSub myHost);
    string ExtStop(string param);
  }

public interface IPubSub
{
    bool AddUpdChannel(ChannelKey channel, ChannelSub channelSub, [CallerMemberName] string caller = "");
    string Subscribe(string clientName, ChannelKey channel, [CallerFilePath] string caller = "");
    bool Publish(string clientName, ChannelKey channel, string message, [CallerFilePath] string caller = "");
}

public struct ChannelKey
{
    public string network;
    public string category;
    public string className;
    public string instance;
}

public struct AccessAttribs
{
    public string name;
    public string access;
}

public class ChannelSub
{
    public bool active = true;
    public string desc = "";
    public string type = "GENERIC";
    public string author = "";
    public List<AccessAttribs> clients = new List<AccessAttribs>();                                         // List of clients subscribed & their access rights. This is set when subscribing to enable fast lookup when processing messages
    public List<AccessAttribs> auth = new List<AccessAttribs>();                                            // When subscribing, clients must be a member of one of these groups & will get the access rights of that group
    public List<KeyValuePair<string, string>> attribs = new List<KeyValuePair<string, string>>();
}

解决方案构建良好,智能感知在 DLL 中找到了所有接口定义,因此它一定是在寻找文件。我多次 clean/rebuilt/checked 文件位置,没问题。我也可以 cut/paste 将此代码添加到非核心 .NET 项目中并且它工作正常。

调试模式下首次启动报错为:

System.IO.FileNotFoundException 'Could not load file or assembly Commons, Version=1.0.0.0,
culture=neutral, PublicKeyToken=null". The system cannot find the file specified.

主项目的csproj:

<Project Sdk="Microsoft.NET.Sdk">
 <PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>netcoreapp1.1</TargetFramework>
 </PropertyGroup>
 <ItemGroup>
  <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.0" />
  <PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="1.1.0" />
  <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.0" />
  <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.0" />
 </ItemGroup>
 <ItemGroup>
  <Reference Include="Commons">
   <HintPath>..\Commons\bin\Debug\netcoreapp1.1\Commons.dll</HintPath>
   <Private>true</Private>
  </Reference>
 </ItemGroup>
</Project>

接口 DLL 的 csproj (Commons.DLL)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>
</Project>

这个项目我重建了很多次,重装了VS 2017RC好几次都解决不了接口引用DLL的找不到文件的错误

看来您在 ItemGroupMicrosoft.Extensions.Configuration 之前缺少 <PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" />

并且我建议您引用项目本身而不是引用 debug dll。结果 csproj 应如下所示:

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="**\*.cs" />
    <EmbeddedResource Include="**\*.resx" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" />
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="1.1.0" />
    <PackageReference Include="Microsoft.Extensions.Logging" Version="1.1.0" />
    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="1.1.0" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include="..\Commons\Commons.csproj" />
  </ItemGroup>
</Project>

您的 Common 项目是库,因此它不应该是 netcoreapp,但它应该是 .Net 标准库。它的 csproj 应该是这样的:

<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
  <PropertyGroup>
    <TargetFramework>netstandard1.4</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Compile Include="**\*.cs" />
    <EmbeddedResource Include="**\*.resx" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="NETStandard.Library" Version="1.6" />
  </ItemGroup>
</Project>

现在您应该能够成功编译并运行代码。

这里是示例存储库:https://github.com/Pzixel/Question41918456