You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#如何通过继承重载运算符实现突变测试(无需修改业务类)

问题解决:通过继承基类替换业务类中的加法为减法

首先,你遇到的编译器错误是因为C#运算符重载的语法规则限制:定义二元运算符时,必须有一个参数属于包含该运算符的类型。你在Mutator中重载int + int,但Mutator和int无继承或包含关系,因此这种写法本身不合法,无法直接实现。

下面提供两种无需修改业务类代码的可行方案:


方案一:运行时IL拦截(动态代理)

利用动态代理框架(如Castle DynamicProxy)拦截业务类的方法执行,在运行时修改逻辑,将加法操作替换为减法。

实现步骤:

  1. 引入Castle.Core NuGet包
  2. 编写Mutator基类和拦截器:
using Castle.DynamicProxy;

public class Mutator
{
    protected Mutator()
    {
        // 构造时自动生成代理实例
        var proxyGenerator = new ProxyGenerator();
        var proxy = proxyGenerator.CreateClassProxy(GetType(), new AddToSubtractInterceptor());
        // 将代理的属性复制到当前实例
        CopyProxyMembers(proxy, this);
    }

    private void CopyProxyMembers(object proxy, object target)
    {
        foreach (var prop in proxy.GetType().GetProperties())
        {
            if (prop.CanRead && prop.CanWrite)
                prop.SetValue(target, prop.GetValue(proxy));
        }
        foreach (var field in proxy.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance))
        {
            field.SetValue(target, field.GetValue(proxy));
        }
    }
}

public class AddToSubtractInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // 先执行原方法
        invocation.Proceed();
        
        // 针对两数相加的场景,直接修改返回值为减法结果
        if (invocation.Method.ReturnType == typeof(int) && invocation.Arguments.Length == 2)
        {
            var num1 = (int)invocation.Arguments[0];
            var num2 = (int)invocation.Arguments[1];
            invocation.ReturnValue = num1 - num2;
        }
    }
}

说明:

  • 无需修改Service类代码,仅需继承Mutator即可生效
  • 上述为简化实现,通用场景可配合Mono.Cecil库直接修改IL指令,替换加法操作码为减法

方案二:编译时代码织入(Roslyn源代码生成器)

利用Roslyn编写源代码生成器,在编译阶段自动检测继承自Mutator的类,将其中的加法表达式替换为减法表达式。

实现步骤:

  1. 创建.NET Standard类库作为源代码生成器项目
  2. 编写生成器逻辑:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

[Generator]
public class AddToSubtractGenerator : ISourceGenerator
{
    public void Initialize(GeneratorInitializationContext context)
    {
        context.RegisterForSyntaxNotifications(() => new MutatorClassReceiver());
    }

    public void Execute(GeneratorExecutionContext context)
    {
        var receiver = (MutatorClassReceiver)context.SyntaxReceiver;
        foreach (var classNode in receiver.TargetClasses)
        {
            var semanticModel = context.Compilation.GetSemanticModel(classNode.SyntaxTree);
            var classSymbol = semanticModel.GetDeclaredSymbol(classNode);
            
            // 遍历类中所有方法,替换加法表达式
            foreach (var method in classSymbol.GetMembers().OfType<IMethodSymbol>())
            {
                var methodSyntax = method.DeclaringSyntaxReferences.First().GetSyntax() as MethodDeclarationSyntax;
                if (methodSyntax == null) continue;

                var modifiedMethod = methodSyntax.ReplaceNodes(
                    methodSyntax.DescendantNodes().OfType<BinaryExpressionSyntax>(),
                    (node, _) => node.Kind() == SyntaxKind.AddExpression 
                        ? SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, node.Left, node.Right) 
                        : node);

                // 生成修改后的代码文件
                context.AddSource($"{classSymbol.Name}_{method.Name}.generated.cs", modifiedMethod.ToFullString());
            }
        }
    }

    // 语法接收器:收集所有继承自Mutator的类
    private class MutatorClassReceiver : ISyntaxReceiver
    {
        public List<ClassDeclarationSyntax> TargetClasses { get; } = new();

        public void OnVisitSyntaxNode(SyntaxNode node)
        {
            if (node is ClassDeclarationSyntax classDec && 
                classDec.BaseList?.Types.Any(t => t.Type.ToString() == "Mutator") == true)
            {
                TargetClasses.Add(classDec);
            }
        }
    }
}

说明:

  • 编译阶段自动完成代码替换,运行时无额外性能开销
  • 业务类仅需继承Mutator,无需其他修改

内容的提问来源于stack exchange,提问作者Mao Shengelia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:30:35