Rules of referenced assemblies copying

后端 未结 4 1628
南笙
南笙 2021-02-19 02:32

Which rules does VS (msbuild?) follow during solution build? In which cases it will copy indirectly referenced asemblies to output folder and in which not?

相关标签:
4条回答
  • 2021-02-19 03:06

    There is a subtlety not addressed by previous answers, namely whether the referenced assembly is in the GAC.

    Consider a project that references assembly A, which in turn depends on assemblies B and C. Assembly C happens to have been installed into the GAC by some "other product". I have found that Visual Studio 2013 copies A and B, but not C, to the output folder, because C is already in the GAC. If I then run the application on a machine that doesn't have "other product" installed, I get a runtime binding failure.

    I've also noticed that Microsoft's documentation in this area appears to be wrong, at least for VS2013.

    Managing Project References states

    If you deploy an application that contains a reference to a custom component that is registered in the GAC, the component will not be deployed with the application, regardless of the CopyLocal setting. In earlier versions of Visual Studio, you could set the CopyLocal property on a reference to ensure that the assembly was deployed. Now, you must manually add the assembly to the \Bin folder

    My tests with VS2013 show that, contrary to the above, CopyLocal=True always copies the directly-referenced assembly to the output folder, regardless of whether it's in the GAC. But indirectly-referenced assemblies appear to be copied only if they are not in the GAC.

    This behaviour means that to be sure that indirectly-referenced assemblies are deployed with your application you should add explicit references to them, with CopyLocal=True (or manually copy them). Note that by default CopyLocal will be set to False if the assembly is in the GAC.

    0 讨论(0)
  • 2021-02-19 03:10

    My experience is that it copies all directly referenced assemblies, recursively - that is, anything directly referenced in your code, and anything that these reference too.

    Anything that is not referenced at compile time in your code will not be referenced. So references that only resolved at run time will not be copied. This is because, even though you may know exactly what it references, the copmpiler doesn't. Whether reflection or using the activator to reference it ( as in the two answers already given ) because at compile time, the actual type of the objects cannot be determined.

    The references in the project indicate where code references should be resolved to, but that is all - I think the evidence is that they wil not be copied - it is all based on the compile time coded references.

    This is one reason why some of the injection techniques can work, before the resolution of the reference need not be done at the point of compilation or even deployment.

    0 讨论(0)
  • 2021-02-19 03:17

    It should copy all the recursive references. For example:

    enter image description here

    --- EDIT---

    The rules (at least in VS2010) seem to be as follows:

    • An indirect reference is copied only if actually used.
    • A direct reference is copied no matter what - even if not actually used.

    So, if you want to ensure that the assembly required for reflection is deployed, reference it from the root project.

    Reflection concerns aside, it seems to be enough to just add the minimal set of references at each level of project hierarchy.

    0 讨论(0)
  • 2021-02-19 03:19

    I've just been a bit of experimentation, and it looks like any indirectly referenced assembly which has a type directly referenced by code in another assembly will be copied. If there's nothing in code, it won't be. Here's my sample scenario:

    • MainProgram: Console application with a direct reference to DirectAssembly. Code in Main:

      var foo = new DirectAssembly.SampleClass();
      
    • DirectAssembly: Class library with a direct reference to IndirectAssembly. Contains SampleClass:

      public class SampleClass
      {
          // Comment out this line to change the behaviour...
          IndirectAssembly.IndirectClass neverUsed = null;
      
          public SampleClass()
          {
              object x = Activator.CreateInstance("IndirectAssembly",
                                                  "IndirectAssembly.IndirectClass");
      
          }
      }
      
    • IndirectAssembly: Contains a public class IndirectClass with a public parameterless constructor

    As described above, it works because IndirectAssembly is copied into the output folder of MainProgram. If you comment out the line indicated in SampleClass, IndirectAssembly is not copied (even though it's still a reference) and the code will fail at execution time.

    I'm not saying these are all the rules, but they're at least a start...

    0 讨论(0)
提交回复
热议问题