C#隐藏参考文献

时间:2014-09-03 22:50:03

标签: c# .net dll .net-assembly

我正在尝试确定我的程序集需要编译的dll。我在一个解决方案中有两个示例项目,Scratch和ScratchTest。这是Scratch的Program.cs:

using System.ServiceProcess;

namespace Scratch
{
    public class A : ServiceBase
    {
        static void Main(string[] args)
        {
        }
    }
}

Scratch引用了System.ServiceProcess.dll。

这是ScratchTest的program.cs:

namespace ScratchTest
{
    class Program
    {
        static void Main(string[] args)
        {
        Scratch.A o;
        }
    }
}

ScratchTest必须引用BOTH Scratch和System.ServiceProcess.dll。但是,生成的ScratchTest.dll没有引用System.ServiceProcess.dll,只有Scratch。通过查看

我知道这一点
Assembly.GetReferencedAssemblies()

并使用.net反射器。所以我的问题是,如何判断ScratchTest是否需要编译System.ServiceProcess.dll?特别是考虑到SratchTest不一定要引用所有Scratch的引用,因为可能存在一些相互矛盾的引用。谢谢,埃里克

2 个答案:

答案 0 :(得分:2)

首先,您遇到的问题并非特定于ServiceBase Class。它与CLR如何检测C#程序的类型依赖关系并加载引用的程序集有关。 C#编译器只是在编译时自己提前给出错误,因为当CLR尝试运行程序时,它也会在运行时失败。这是我在解释您的问题的解决方案时所假设的:

ScratchTest是您的初创项目,尽管您已在解决方案中定义了两个入口点,因为“Scratch”和“ScratchTest”项目中都存在Main方法。为避免混淆,您应该只为解决方案提供一个主要方法(入口点),尽管它对您当前的问题没有影响。

解决方案:当您在scratchTest项目中引用A类时,您不仅仅指类A而是指类ServiceBase,因为类“A”继承自它。因此,当编译器尝试编译ScratchTest项目时,它会尝试在当前引用的程序集中找到依赖项类型,即“A”和ServiceBase。这里重要的一点是,CLR总是试图仅在程序集中找到依赖关系类型,这些程序集的引用直接存在于您尝试加载的程序集本身的清单元数据中(在本例中为ScratchTest)。依赖类型永远不会像您构建解决方案那样以递归方式进行搜索。基本上期望CLR在所有引用的程序集中搜索依赖项类型,反过来,它们引用的程序集在启动.Net应用程序时会对性能产生很大的影响。

与此同时,MsCorLibSystemSystem.CoreSystem.Data等核心.Net库通常会在您创建的大多数C#项目中引用。然后考虑这种情况,否则CLR实现了通过引用的程序集递归地查找依赖类型的逻辑,那么每次在搜索依赖类型时是否已经超过特定程序集时进行检查都会做出额外的努力。这将进一步损害启动性能。

要修复代码,您可以执行以下两项操作:

  • 根据C#编译器的建议,向ScratchTest项目添加对System.ServiceProcess.dll的引用。

OR

  • 在“ScratchTest”项目中使用A类,因为它已包含对System.ServiceProcess.dll的引用

答案 1 :(得分:0)

我认为您不需要在测试文件上显式调用System.ServiceProcess。

Test文件没有使用任何对System.ServiceProcess中的任何方法或类的引用,只是使用Scratch。

您无需要求引用的所有库使用的所有库,只需要您班级当前使用的库。

因此ScratchTest仅使用Scrath而Scratch正在使用System.ServiceProcess。