1

编码

所以我有两个程序集

“AssemblyWithClassAndModuleInit”包含一个类

public class MyBaseClass
{
}

"AssemblyWithInterfaceAndModuleInit" 包含一个接口

public interface MyInterface
{
}

两者都包含一个模块初始化器

public static class ModuleInitializer
{
    public static void Initialize()
    {
        Environment.SetEnvironmentVariable("ModuleInitializer", "true");
    }
}

测试“AssemblyWithClassAndModuleInit”(注意MyBaseClass用作 的基础ClassTests

[TestFixture]
public class ClassTests : MyBaseClass
{
    [Test]
    public void EnsureModuleInitIsCalled()
    {
        Assert.AreEqual("true", Environment.GetEnvironmentVariable("ModuleInitializer"));
    }
    [Test]
    public void EnsureAssemblyIsLoaded()
    {
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        Assert.IsTrue(assemblies.Any(x => x.GetName().Name == "AssemblyWithClassAndModuleInit"));
    }
}

测试“AssemblyWithInterfaceAndModuleInit”(注意MyInterface用作接口InterfaceTests

[TestFixture]
public class InterfaceTests : MyInterface
{
    [Test]
    public void EnsureModuleInitIsCalled()
    {
        Assert.AreEqual("true", Environment.GetEnvironmentVariable("ModuleInitializer"));
    }
    [Test]
    public void EnsureAssemblyIsLoaded()
    {
        var assemblies = AppDomain.CurrentDomain.GetAssemblies();
        Assert.IsTrue(assemblies.Any(x => x.GetName().Name == "AssemblyWithInterfaceAndModuleInit"));
    }
}

唯一失败的测试是InterfaceTests.EnsureModuleInitIsCalled.

问题

那么这是为什么呢?InterfaceTests实现的事实不应该MyInterface导致模块初始化程序运行吗?

我如何注入模块初始化程序

我正在使用 IL 编织。具体https://github.com/Fody/ModuleInit

它检测到这个

public static class ModuleInitializer
{
    public static void Initialize()
    {
        //Init code
    }
}

并添加了这个

static <Module>()
{
    ModuleInitializer.Initialize();
}

更新

  • 顺便说一句,如果我添加一个字段Type interfaceType = typeof(MyInterface);InterfaceTests那么所有测试都会通过。
  • 编码是针对 .net 4.5 完成的

完整来源

这是带有单元测试的重现https://github.com/SimonCropp/Experiments/tree/master/ModuleInitRepro

4

1 回答 1

0

一件明显可能相关的事情:您的测试类派生自 prod 程序集中的基类。因此,创建测试类的实例需要(隐式)调用基类中的构造函数,这意味着需要完全加载和初始化基类,因此需要初始化程序集。

将其与您的接口版本进行比较 - 您在测试类中实现 prod-assembly 接口这一事实在执行时实际上是无关紧要的,因为您没有做任何需要该接口的事情。

怀疑如果你有:

public void Foo(MyInterface x)
{
}

[Test]
public void EnsureAssemblyIsLoaded()
{
    Foo(this);
    ... assertions ...
}

那么这可能会初始化程序集。如果您在接口中声明了任何方法,并且您从 调用了这些方法之一Foo,那么我肯定希望程序集能够被初始化。

于 2013-03-29T18:18:25.480 回答