为什么NuGet在NuGet包更新期间将app.config与assemblyBinding一起添加到LIBRARY项目?

时间:2014-03-06 14:41:08

标签: nuget

仅在可执行文件的项目中是否需要此信息?

如何禁用此文件创建?

NuGet 2.8

修改

图书馆项目在NuGet 2.7中是例外,通过修复此问题在2.8中改变了行为:http://nuget.codeplex.com/workitem/3827并提交:https://github.com/NuGet/NuGet2/commit/448652d028e3f01ba4022e147baaf4e1fb3f969b

3 个答案:

答案 0 :(得分:15)

程序集绑定重定向在类库中与在可执行项目中一样有效。

想想这个;在构建应用程序时,编译器将如何知道要使用哪个版本的引用程序集(对于类库)?

通常这样可以正常工作,没有重定向,但是当你偶然发现装有GAC版本程序集的机器时,你可能会遇到麻烦。

我建议你阅读assembly binding redirect documentation以更好地了解它是什么和做什么。

NuGet添加带有重定向的app.config来帮助你,坦率地说,我没有得到关于额外app.config的模糊,以便按预期工作。

截至今天,它将向所有项目添加重定向,但以下类型除外:

  • 维克斯
  • JS​​
  • Nemerle
  • C ++
  • Synergex的
  • Visual Studio
  • Windows应用商店应用

据我所知,没有办法解决这个问题。如果这是一个问题,你可以create an issue at Github

可以找到添加装配绑定重定向的源代码here

答案 1 :(得分:1)

NuGet程序包管理器将程序集绑定重定向添加到库项目的原因是,因为某些类型的项目的输出类型是库,但是有一些特殊的机制可以确保库的应用程序或Web配置文件将在运行时应用。这与您可能熟悉的更典型的库用法相对,后者完全不使用库配置文件。

例如,Azure SDK 1.8+中的Azure Web和Worker角色项目将生成库,但是当它们由IIS包装在exe中时,库的配置文件将设置为默认库。该exe。这样,您就可以获取所有应用程序配置,而不必显式发布名称为包装可执行文件which is how it used to be done的特殊配置文件。现在,构建过程将输出重命名的配置文件(例如app.config-> myWebRoleLibrary.dll.config),一切都会正常进行。

XUnit also does something similar;加载测试程序集的app.config而不是测试运行器进程的app config。

值得一提的是,您也可以manually load a config file in any project,不存储。您必须确保将配置文件放置在正确的位置,但这是可能的。但是,这不适用于绑定重定向,因为通常这些重定向仅由CLR中的程序集加载器使用。我想您可以钩住AssemblyLoad,但现在我们可以很好地重新设计轮子了。

因此,答案是“我的图书馆项目是否有必要?”是也许。如果您的库项目不是Web角色或工作人员角色或测试项目,并且没有手动加载配置文件,则app.config可能是有益的,但不必要。

关于禁用它,您只能在Visual Studio级别上执行。您可以在VS2019中找到该选项,位于:工具->选项...-> NuGet软件包管理器->常规->跳过应用绑定重定向。

什么使用我的配置文件?

编译器(csc.exe)

出于以下原因,编译器使用正在构建的程序集的配置文件:[查找和使用supportPortability元素](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-options/appconfig-compiler-option )。

上面的链接列出了罕见的情况,您需要该编译器选项,但绝大多数用户则不需要。只需说一句,如果您不知道自己是否正在使用该功能,那您就不用了。

它不解析配置文件的任何其他元素,包括程序集绑定重定向,这是NuGet添加的元素。

构建引擎(msbuild)

MSBuild在其一些步骤中使用应用程序配置,但重要的是 not 来找到主要依赖项,它将以/reference:选项的形式传递给csc.exe。

为了找到主要引用,MSBuild(特别是ResolveAssemblyReference任务)将搜索the common targets file中列举的路径的集合。如果无法在csproj中找到显式的依赖项,则它将发出警告,并可能进一步提示是否需要依赖项进行编译。

之后,它将搜索可传递依赖项。它不会将这些文件传递给编译器,而是使用它们来生成文件列表,在后续的构建步骤中需要考虑这些文件,例如生成许可证文件,信任信息和建议的绑定重定向。此步骤确实考虑了项目的配置文件,并专门使用其绑定重定向来通知传递依赖项列表。重要的是要注意,构建exe会在构建过程中考虑其库的app.config文件,并且库的app.config不会更改生成库dll的方式。

运行时(CLR)

CLR使用config fileschange the way it locates assemblies

IIS

IIS将读取您的web.config文件的元素,以更改您的Web应用程序的行为方式。例如,caching characteristics

应用程序

应用程序可以使用ConfigurationManager从配置文件中手动检索配置数据。

答案 2 :(得分:-2)

我创建了一个小的控制台应用程序,它检查app.config文件的所有日期,然后从.csproj和文件中自动删除它们。 Todo:从tfs删除。 也许这可能有所帮助。

class Program
{
    private static string RootFolder;
    private static string AppConfigName;
    private static bool AskConfirmation = true;
    static void Main(string[] args)
    {
        try
        {
            AppConfigName = "app.config";
            RootFolder = @"<Your project path>";
            ScanDir(RootFolder);
            Console.WriteLine();
            Console.WriteLine("DONE!");
            Console.WriteLine("Press ENTER to finish...");
            Console.ReadLine();

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private static void ScanDir(string directoryParent)
    {
        var dirs = Directory.GetDirectories(directoryParent);
        foreach (var dir in dirs)
        {
            var dirInfo = new DirectoryInfo(dir);
            if (dirInfo.Name == "bin" || dirInfo.Name == "obj" || dirInfo.Name == "debug" || dirInfo.Name == "tempPE" || dirInfo.Name == "java" || dirInfo.Name == "res") continue;
            var files = Directory.GetFiles(dir, "app.config");
            if (files.Length == 0)
            {
                ScanDir(dir);
                continue;
            }
            Process(dir);
            //ScanDir(dir);
        }
    }

    private static void Process(string dir)
    {
        var fi = new FileInfo(Path.Combine(dir, AppConfigName));
        if (fi.CreationTime.Date != DateTime.Now.Date) return;
        if (AskConfirmation)
        {
            Console.WriteLine("Scan " + dir.Replace(RootFolder, ""));
            Console.Write("Remove (y)es or (n)o ?");
            var key = Console.ReadKey();
            Console.WriteLine();
            if (key.Key.ToString() =="Y")
                // remove app.config
                RemoveAppConfig(dir, fi);
        }
        else
            RemoveAppConfig(dir, fi);
    }

    private static void RemoveAppConfig(string dir, FileInfo fi)
    {
        var csProjs = Directory.GetFiles(dir, "*.csproj");
        foreach (var csProj in csProjs)
        {
            var txt = File.ReadAllText(csProj);
            txt = Regex.Replace(txt,"<None Include=\"App.Config\" />", "",RegexOptions.IgnoreCase);
            File.Delete(csProj);
            File.WriteAllText(csProj, txt);
        }
        File.Delete(fi.FullName);
        // todo: undo in tfs
        Console.WriteLine("Deleted");
    }
}