C# 如何自动为IMessageClient实现类的Response填充Source枚举值
可行技术方案整理
方案1:抽象基类封装Response创建逻辑(无额外依赖、最易维护)
在接口和实现类之间加一层抽象基类,统一封装Response实例的创建逻辑,自动绑定当前实例的Source值,子类只需关注业务逻辑返回数据即可。
代码示例:
public abstract class MessageClientBase : IMessageClient { // 子类仅需实现该Source属性 public abstract Source Source { get; } // 统一封装Response创建逻辑,自动赋值Source protected Response<T> CreateResponse<T>(T data) { return new Response<T> { Source = this.Source, Data = data }; } public abstract Response<string[]> GetMessages(); public abstract Response<string> GetMessage(); } // 子类实现示例 public class MessageClient : MessageClientBase { public override Source Source => Source.Source1; public override Response<string[]> GetMessages() { // 直接调用基类方法,无需手动赋值Source return CreateResponse(new[] {"1", "2"}); } public override Response<string> GetMessage() { return CreateResponse("test"); } }
优点:无第三方依赖、编译时类型安全、调试简单,适配绝大多数业务场景。
方案2:C# 8+ 接口默认方法(无需基类继承)
如果实现类已经存在其他父类无法多继承,可以用接口默认方法实现能力复用:
代码示例:
public interface IMessageClient { Source Source { get; } Response<string[]> GetMessages(); Response<string> GetMessage(); // 接口默认的Response创建方法 protected Response<T> CreateResponse<T>(T data) { return new Response<T> { Source = this.Source, Data = data }; } } // 实现类直接调用接口默认方法即可 public class MessageClient : IMessageClient { public Source Source => Source.Source1; public Response<string[]> GetMessages() { return (this as IMessageClient).CreateResponse(new[] {"1", "2"}); } public Response<string> GetMessage() { return (this as IMessageClient).CreateResponse("test"); } }
方案3:AOP动态代理(零侵入现有代码)
如果不想修改现有实现类的业务代码,可以用AOP框架(比如Castle DynamicProxy)在运行时拦截所有返回Response类型的方法,自动为返回值的Source属性赋值:
核心逻辑示例:
// 先定义一个非泛型的Response接口方便类型判断 public interface IResponse { Source Source { get; set; } } public class Response<T> : IResponse { public Source Source { get; set;} public T Data { get; set; } } public class SourceAssignInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { // 先执行原方法逻辑 invocation.Proceed(); // 自动为Response赋值Source if (invocation.ReturnValue is IResponse response && invocation.InvocationTarget is IMessageClient client) { response.Source = client.Source; } } }
优点:完全不需要修改现有实现类的业务代码,适合已有大量实现类不想逐个改造的场景,缺点是存在极小的运行时代理开销,调试复杂度略高。
方案4:.NET 源代码生成器(Source Generators)
如果需要零运行时开销、同时不想修改现有手写代码,可以用.NET的源代码生成器在编译阶段扫描所有实现了IMessageClient的类,自动为每个返回Response的方法注入Source赋值的代码,无需开发人员手动编写赋值逻辑。
该方案适合框架级别的封装,开发成本高于前三个方案,更适合大型项目使用。
内容的提问来源于stack exchange,提问作者filur
相关产品推荐
相关产品推荐

