C#运行时动态包装子类实例中重写的基类方法
运行时给重写方法注入额外逻辑的实现方案
嘿,这个需求我之前也碰到过,咱们先回顾下你的代码结构,再一步步拆解可行的实现方式:
public class ABaseClass { public virtual void DoAThing() { Console.WriteLine("print this base"); } } public class AChildClass : ABaseClass { public override void DoAThing() { Console.WriteLine("child override"); base.DoAThing(); } }
你想要在运行时实例化AChildClass时,给它重写的DoAThing方法(或连带基类方法逻辑)添加额外执行逻辑,下面是几种实用的方案:
方案1:装饰器模式(轻量OOP实现)
装饰器模式是最直观的方式,不用修改原有类代码,通过包装对象动态添加功能。我们可以创建一个装饰器类,继承自基类,把原子类实例包进去,在方法调用前后注入逻辑:
public class AChildDecorator : ABaseClass { private readonly ABaseClass _wrappedChild; public AChildDecorator(ABaseClass wrappedChild) { _wrappedChild = wrappedChild; } public override void DoAThing() { // 注入前置逻辑 Console.WriteLine("[Decorator] 准备执行DoAThing"); // 调用原子类的方法 _wrappedChild.DoAThing(); // 注入后置逻辑 Console.WriteLine("[Decorator] DoAThing执行完成"); } }
使用时直接包装子类实例:
var originalChild = new AChildClass(); var decoratedChild = new AChildDecorator(originalChild); decoratedChild.DoAThing();
输出结果:
[Decorator] 准备执行DoAThing child override print this base [Decorator] DoAThing执行完成
这个方案的优点是简单易懂,不需要额外框架,完全基于基础OOP特性实现,适合轻量场景。
方案2:动态代理(灵活的运行时拦截)
如果需要更通用、更灵活的注入(比如批量处理多个类,或者不想提前写装饰器),可以用动态代理库,比如Castle DynamicProxy,它能在运行时生成子类的代理类,拦截所有虚方法调用。
首先安装Castle.Core NuGet包:
Install-Package Castle.Core
然后创建一个拦截器类,实现IInterceptor接口来定义注入逻辑:
using Castle.DynamicProxy; public class MethodInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { // 前置逻辑:比如记录方法开始执行 Console.WriteLine($"[Proxy] 即将执行方法:{invocation.Method.Name}"); // 执行原方法逻辑 invocation.Proceed(); // 后置逻辑:比如记录方法执行结束 Console.WriteLine($"[Proxy] 方法执行完成:{invocation.Method.Name}"); } }
运行时生成代理实例:
var proxyGenerator = new ProxyGenerator(); var interceptor = new MethodInterceptor(); // 生成AChildClass的代理实例 var proxiedChild = proxyGenerator.CreateClassProxy<AChildClass>(interceptor); proxiedChild.DoAThing();
输出结果:
[Proxy] 即将执行方法:DoAThing child override print this base [Proxy] 方法执行完成:DoAThing
这个方案的优势是可以拦截任意虚方法,甚至能修改方法参数、返回值,非常适合做通用的切面逻辑(比如日志、性能监控、权限校验)。
方案3:子类继承(直接重写扩展)
如果你的场景允许创建AChildClass的子类,也可以直接在新子类里再次重写DoAThing,注入额外逻辑:
public class AGrandChildClass : AChildClass { public override void DoAThing() { // 前置逻辑 Console.WriteLine("[GrandChild] DoAThing执行前的额外逻辑"); // 调用父类(AChildClass)的方法 base.DoAThing(); // 后置逻辑 Console.WriteLine("[GrandChild] DoAThing执行后的额外逻辑"); } }
运行时直接实例化这个新子类:
var grandChild = new AGrandChildClass(); grandChild.DoAThing();
这个方案最直接,但缺点是需要提前定义子类,不能完全在运行时动态修改,适合你能提前预知注入需求的场景。
内容的提问来源于stack exchange,提问作者Shabloinker
相关产品推荐
相关产品推荐

