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

如何在C#类中模拟WCF行为,实现方法调用前触发逻辑?

嘿,我来帮你搞定在普通C#类里模拟WCF那种「方法调用前触发自定义逻辑」的需求!其实核心就是实现AOP(面向切面编程)的方法拦截,和WCF里用自定义属性+调用器的思路本质是一样的,下面给你两种可行的实现方案:

模拟WCF前置触发逻辑的具体实现

1. 先定义你的自定义验证属性

首先把WCF里的属性逻辑迁移过来,让属性成为标记方法的“触发器”,并包含具体的验证逻辑:

/// <summary>
/// 验证属性基类,标记方法需要执行前置验证
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public abstract class ValidationRequiredAttribute : Attribute
{
    /// <summary>
    /// 执行前置验证的抽象方法,子类实现具体逻辑
    /// </summary>
    /// <param name="methodInfo">当前被调用的方法信息</param>
    /// <param name="parameters">方法传入的参数</param>
    public abstract void Validate(MethodInfo methodInfo, object[] parameters);
}

/// <summary>
/// 令牌验证的具体属性,继承基类实现验证逻辑
/// </summary>
public class TokenValidationRequiredAttribute : ValidationRequiredAttribute
{
    public override void Validate(MethodInfo methodInfo, object[] parameters)
    {
        // 这里写你的令牌验证逻辑——比如从参数里取令牌、校验签名等
        Console.WriteLine($"正在对方法 {methodInfo.Name} 执行令牌验证...");
        // 验证失败直接抛异常中断方法执行
        // if (!IsTokenValid(parameters[0].ToString()))
        //     throw new UnauthorizedAccessException("令牌无效,拒绝访问");
    }
}

2. 实现方法拦截逻辑

接下来需要一个“拦截器”,它会在调用目标方法前检查属性、执行验证。这里给你两种方案,一种是原生反射实现(不用额外依赖),另一种是用成熟的AOP库(更优雅)。

方案A:原生反射+包装类(零依赖)

自己写一个通用的服务包装类,手动处理反射和属性检查:

public class ServiceInterceptor<T> where T : class, new()
{
    // 实际的业务服务实例
    private readonly T _targetService = new T();

    // 调用无返回值方法(简单版)
    public void CallMethod(string methodName, params object[] parameters)
    {
        var method = typeof(T).GetMethod(methodName) 
            ?? throw new ArgumentException($"找不到方法 {methodName}");

        // 执行所有标记的前置验证
        RunPreValidation(method, parameters);

        // 调用目标方法
        method.Invoke(_targetService, parameters);
    }

    // 调用有返回值方法(类型安全版,用表达式树解析方法)
    public TResult CallMethod<TResult>(Expression<Func<T, TResult>> methodExpression)
    {
        var methodCall = methodExpression.Body as MethodCallExpression
            ?? throw new ArgumentException("请传入合法的方法调用表达式");

        var method = methodCall.Method;
        var parameters = methodCall.Arguments
            .Select(arg => Expression.Lambda(arg).Compile().DynamicInvoke())
            .ToArray();

        // 执行前置验证
        RunPreValidation(method, parameters);

        // 执行方法并返回结果
        return methodExpression.Compile()(_targetService);
    }

    // 提取公共的验证逻辑
    private void RunPreValidation(MethodInfo method, object[] parameters)
    {
        var validationAttrs = method.GetCustomAttributes<ValidationRequiredAttribute>(true);
        foreach (var attr in validationAttrs)
        {
            attr.Validate(method, parameters);
        }
    }
}

使用示例:

// 你的业务服务类,用属性标记需要验证的方法
public class MyBusinessService
{
    [TokenValidationRequired]
    public void ProcessOrder(string token, Order order)
    {
        Console.WriteLine($"开始处理订单:{order.Id}");
    }

    [TokenValidationRequired]
    public UserInfo GetUserInfo(string token, int userId)
    {
        return new UserInfo { Id = userId, Name = "张三" };
    }
}

// 用拦截器调用服务方法
var interceptor = new ServiceInterceptor<MyBusinessService>();
// 调用无返回值方法
interceptor.CallMethod("ProcessOrder", "valid_token_123", new Order { Id = "ORD001" });
// 调用有返回值方法(类型安全)
var user = interceptor.CallMethod(s => s.GetUserInfo("valid_token_123", 1001));
Console.WriteLine($"获取到用户:{user.Name}");

方案B:用Castle DynamicProxy(更优雅的AOP实现)

如果可以引入第三方库,Castle DynamicProxy能帮你省去手动写反射的麻烦,实现更简洁的拦截:

首先安装NuGet包:Install-Package Castle.Core

然后写拦截器类:

public class ValidationInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // 检查当前方法的验证属性并执行
        var validationAttrs = invocation.Method.GetCustomAttributes<ValidationRequiredAttribute>(true);
        foreach (var attr in validationAttrs)
        {
            attr.Validate(invocation.Method, invocation.Arguments);
        }

        // 继续执行目标方法
        invocation.Proceed();
    }
}

使用示例:

var proxyGenerator = new ProxyGenerator();
var interceptor = new ValidationInterceptor();

// 创建业务服务的代理对象
MyBusinessService serviceProxy = proxyGenerator.CreateClassProxy<MyBusinessService>(interceptor);

// 直接调用方法就行,拦截器会自动触发前置验证
serviceProxy.ProcessOrder("valid_token_123", new Order { Id = "ORD002" });
var user = serviceProxy.GetUserInfo("valid_token_123", 1002);
Console.WriteLine($"获取到用户:{user.Name}");

3. 和WCF机制的对比

WCF里是通过IOperationBehavior或者DispatchMessageInspector在消息处理管道中拦截方法调用,我们这里的实现核心思路完全一致:用属性标记需要拦截的方法→在方法执行前触发属性中的逻辑→再执行目标方法,完美模拟了WCF的行为。

内容的提问来源于stack exchange,提问作者Rafael León

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:57:16