【问题标题】:Creating a dynamic fake class inside of an assembly在程序集中创建一个动态假类
【发布时间】:2015-08-20 14:43:00
【问题描述】:

可能我要问的是不可能的,但这是我的问题和疑问。首先是 C# 和 .NET。
我想以这样的方式将类的空实现(空方法,返回默认值的函数)定义为接口,如果我更改接口,则不需要调整代码。不幸的是,我无法生成包含程序集的实现,也无法在其上定义动态模拟,因为实例化是通过反射自动完成的。这是更广泛地解释的问题:

我有一个 dll/程序集,我们称之为 IMyInterface.dll,其中包含一个接口:IMyInterface。
上面的层我在单独的 dll/程序集中实现了让我们称之为 MyInterfaceImplementation.dll。
在中间/之间,我有一个自动化测试框架,它可以依赖于 IMyInterface.dll 但不依赖于 MyInterfaceImplementation.dll。
现在这个测试框架使用了通过反射实例化类型的生产代码基础设施。它是一个依赖注入类型的框架。 所以你对生产代码基础设施说,从这个程序集中给我这个接口实现。
在我们的例子中,你说给我一个来自 MyInterfaceImplementation.dll 的 IMyInterface。 在测试框架中,您不能依赖 MyInterfaceImplementation,因此您可以在第三个程序集中定义一个基于 IMyInterface 的假/存根/模拟类,让我们称之为:MyInterfaceFakeImplementation.dll
在测试框架中,你说给我一个来自 MyInterfaceFakeImplementation.dll 的 IMyInterface,你很好。
注意:对于我们的模块层次结构,不可能重构依赖关系。关于模拟框架,我没有控制实例化。实例化在依赖注入框架内完成。

当您在 MyInterfaceFakeImplementation.dll 中编写代码时,您可以这样写:

class MyInterfaceFakeImplementation : IMyInterface 
{
  // IMyInterface implementation. 
}

现在我想提供的是IMyInterface的动态类,所以当接口发生变化时,我不需要适应假的。

我想要的很短:

鉴于:
IMyInterface.dll 中的 IMyInterface 接口
MyInterfaceFakeImplementation.dll中IMyInterface的MyInterfaceFakeImplementation实现
MyInterfaceFakeImplementation 有空函数并返回默认值。

时间:
我更改了 IMyInterface(例如更改函数签名)。

然后:
我不需要更改 MyInterfaceFakeImplementation,只需重新编译 MyInterfaceFakeImplementation.dll。注意:无法生成此程序集,需要编译。

这是一种解决方法。
在 IMyInterface.dll 中的 IMyInterface 旁边做一个假实现(类),我们称之为 MyInterfaceFakeBase。 在 MyInterfaceFakeImplementation.dll 中,从这个基类 MyInterfaceFakeBase 派生 MyInterfaceFakeImplementation 并将其留空。 改变接口时(IMyInterface)适配MyInterfaceFakeBase,不用担心MyInterfaceFakeImplementation和MyInterfaceFakeImplementation.dll。

好的,对于那些想从这里开始编码的人来说,这是一个示例控制台类型的应用程序,它可能会有所帮助。向此代码添加一个类,以便它找到实现接口的类型,如果您更改接口,则无需更改该类。 (不要修改 Main 函数。)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DynamicFake3
{
    public interface IMyInterface
    {
        void SimpleMethod();
        bool SimpleFunction();
        void OneParameterMethod(int i);
    }

    class Program
    {
        static void Main(string[] args)
        {

            Assembly anAssembly = Assembly.LoadFrom("DynamicFake3.exe");

            foreach (Type aType in anAssembly.GetTypes())
            {
                if (aType.GetInterfaces().Contains(typeof(IMyInterface)))
                {
                    Console.WriteLine(aType.FullName);
                }
            }
        }
    }
}

再见 拉斯洛

【问题讨论】:

  • 您知道Mocking 用于单元测试的框架,对吧?他们或多或少和你描述的完全一样。
  • 抱歉拼错了,有点问题:我不能在它上面定义动态模拟,因为实例化是通过反射自动完成的。需要让这一点更加明显。
  • 尽管我理解你的问题和限制,但我会要求你修改它,并且不要以多种方式重复问题场景多次..
  • 好吧,你是个非凡的人。 :-)

标签: c# .net dynamic reflection .net-assembly


【解决方案1】:

好吧,没有人回答,所以不可能做这样的事情。 可以在运行时为接口创建动态装饰器或代理或模拟,或者生成具有接口假实现的程序集,但不是我想要的。 C#、.NET、CLR 不允许这样做。或者更好地说,C# 不允许这种动态(解释)行为是一件好事。

【讨论】:

    【解决方案2】:

    您可以使用类型转发将类型声明为移动到运行时生成的程序集(请参阅 assemblybuilder),您可以在其中发出您的类型(请参阅 typebuilder)。

    【讨论】:

    • 需要查找这种类型的转发。 :-) 我会写下我的发现。 :-)
    猜你喜欢
    • 1970-01-01
    • 2011-04-12
    • 2017-04-15
    • 1970-01-01
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    相关资源
    最近更新 更多