Home>
Question

When a .NET Standard class library is referenced in a .NET Framework project, a large amount of DLLs are output to the .NET Framework output folder.
I would like to know why so many DLLs are output.
Also, if you can tell me how to stop such DLL output, I would appreciate it.

Environmental information

OS: Windows 10 Pro 64bit (1803)
IDE: Visual Studio Community 2017 (v15.8.1)
.NET Framework: 4.6.1
.NET Standard: 2.0
Language: C #

[Sample Project Information]
HelloStandard: Class library (.NET Standard)
HogeConsole: Console app (.NET Framework)

IMHO

I would like to point out any recognition errors.
I think that the dependency ofnetstandard.dllis the cause.
However, .NET Standard 2.0 supports .NET Framework 4.6.1, and apart from the parts that only Framework has, it's not good that Standard and Framework have different dependencies.
(However, I think there is a lack of understanding in the first place)

Question background

When distributing the executable file, I asked the question because there was a high risk of DLL copy omissions due to some mischief, and there was a desire to reduce the number of dependent files.
I thought that there would be no problem if it was automated ... I think it would be hard to check if there is any.

The reason why I wanted to create a class library for .NET Standard is the trend of the times, but I migrated existing assets to the .NET Standard class library and moved to platforms other than Windows. This is because we want to make it expandable.

Sample project source code

Project:HelloStandard

HelloStandard.cs

using System;
namespace Standard
{
    public class HelloStandard
    {
        public HelloStandard (string message)
        {
            Message = message;
        }
        public string Message {get;}
        public void PrintOut ()
        {
            Console.WriteLine (Message);
        }
    }
}

HelloStandard.csproj

<Project Sdk = "Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <RootNamespace>Standard</RootNamespace>
  </PropertyGroup>
</Project>

Project:HogeConsole

Program.cs

using Standard;
namespace HogeConsole
{
    internal class Program
    {
        private static void Main (string [] args)
        {
            var helloStandard = new HelloStandard ("Hello .NET Standard !!");
            helloStandard.PrintOut ();
        }
    }
}
Hello .NET Standard !!

App.config

<? xml version = "1.0" encoding = "utf-8"?><configuration>
    <startup>
        <supportedRuntime version = "v4.0" sku = ". NETFramework, Version = v4.6.1" />
    </startup>
</configuration>

HogeConsole.csproj

<? xml version = "1.0" encoding = "utf-8"?>
<Project ToolsVersion = "15.0" xmlns = "http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project = "$(MSBuildExtensionsPath) \ $(MSBuildToolsVersion) \ Microsoft.Common.props" Condition = "Exists ('$(MSBuildExtensionsPath) \ $(MSBuildToolsVersion) \ Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition = "'$(Configuration)' == ''">Debug</Configuration>
    <Platform Condition = "'$(Platform)' == ''">AnyCPU</Platform>
    <ProjectGuid></ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>HogeConsole</RootNamespace>
    <AssemblyName>HogeConsole</AssemblyName>
    <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <Deterministic>true</Deterministic>
  </PropertyGroup>
  <PropertyGroup Condition = "'$(Configuration) | $(Platform)' == 'Debug | AnyCPU'">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin \ Debug \</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition = "'$(Configuration) | $(Platform)' == 'Release | AnyCPU'">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin \ Release \</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include = "System" />
    <Reference Include = "System.Core" />
    <Reference Include = "System.Xml.Linq" />
    <Reference Include = "System.Data.DataSetExtensions" />
    <Reference Include = "Microsoft.CSharp" />
    <Reference Include = "System.Data" />
    <Reference Include = "System.Net.Http" />
    <Reference Include = "System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include = "Program.cs" />
    <Compile Include = "Properties \ AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include = "App.config" />
  </ItemGroup>
  <ItemGroup>
    <ProjectReference Include = ".. \ HelloStandard \ HelloStandard.csproj">
      <Project></Project>
      <Name>HelloStandard</Name>
    </ProjectReference>
  </ItemGroup>
  <Import Project = "$(MSBuildToolsPath) \ Microsoft.CSharp.targets" />
</Project>

Nice to meet you.

  • Answer # 1

    Hello.

    As you know, NETStandard has no implementation. There is only "API definition with a large number of classes and method signatures". Specifically, it consists of a collection of "assemblies filled with empty class definitions".
    This is why NETStandard was designed from the beginning to create a cross-platform library, not "direct access to each platform API", but "call through a thin assembly". This makes it possible to replace the implementation. In C #, you can imagine a situation where you have a single interface while avoiding the direct use of objects. And that interface group is the identity of a large amount of DLL files in the image.

    Possibly, but I think that if the assembly that netstandard.dll is added to among those DLLs iscompletely deleted, the app will work. If the runtime is the .NET Framework, removing the reference assembly will directly reference the implementation assembly on the .NET Framework side. (Maybe!)


    You can't be afraid of that, so here is another perspective,

    "Create a release using Visual Studio'spublish"

    I recommend

    .
    Unlike normal builds, publish is the one that outputs the assembly and data necessary for the application in one place, and it is the safest and most reliable way to pack and use it for distribution and update as it is .
    If you are using the .NET Core SDK and you can use the dotnet command, you can do the same with thedotnet publishcommand, so scripting is also possible.


    Another suggestion is

    Make NETStandard library multi-target with net461

    There is a method called

    .
    This means that while the library is compatible with NETStandard, the net461 assembly can be provided to the .NET Framework, so the NETStandard interface reference is added to the net app. You can avoid that.
    If you use this method, the "development environment" of the library must be compatible with the .NET Framework. NETStandard single can be developed on Linux, but if you cross with net, you can build only on Windows.


    Neither method is better, but personally, I don't change the project, and if you can devise a publishing process, there are fewer concerns.
    Even if you choose multi-targeting, you may think about revising the build process for distribution.