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

时间:2017-01-29 07:00:17

标签: c# .net-core visual-studio-2017

在尝试从单独的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中的所有接口定义,因此必须找到该文件。我已多次清理/重建/检查文件位置,这很好。此外,我可以将此代码剪切/粘贴到非Core .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>

csproj用于接口DLL(Commons.DLL)

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

我已多次重建此项目,多次重新安装VS 2017RC并且我无法摆脱接口引用DLL的文件未找到错误。

1 个答案:

答案 0 :(得分:1)

<PackageReference Include="Microsoft.NETCore.App" Version="1.0.1" /> Microsoft.Extensions.Configuration之前似乎缺少ItemGroup

我建议您引用项目本身而不是引用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