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

如何解决继承Form时Castle动态代理的TypeLoadException问题?

解决Castle DynamicProxy拦截继承Form类时的TypeLoadException问题

问题原因

当你的MyUserInterface继承自System.Windows.Forms.Form时,Form类本身实现了多个.NET内部标记为internal的接口(如System.ComponentModel命名空间下的部分内部扩展接口)。Castle DynamicProxy默认会尝试为目标类实现的所有接口生成代理,但这些内部接口对动态生成的代理程序集DynamicProxyGenAssembly2是不可访问的,因此触发TypeLoadException。


具体解决方案

方案1:自定义代理生成Hook,过滤不可访问接口

创建一个ProxyGenerationHook实现,在代理生成阶段移除那些不可访问的内部接口,避免DynamicProxy尝试实现它们:

public class SkipInaccessibleInterfacesHook : IProxyGenerationHook
{
    public void MethodsInspected() { }
    public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo) { }

    public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
    {
        return true; // 可根据需求调整为只拦截特定方法
    }

    public bool ShouldProxyMethod(Type type, MethodInfo methodInfo)
    {
        return true;
    }

    public bool ShouldProxyType(Type type)
    {
        return true;
    }

    // 核心逻辑:移除不可访问的接口
    public void ProxyGenerationCompleted(ProxyGenerationResult result)
    {
        var inaccessibleInterfaces = result.Interfaces
            .Where(i => !i.IsPublic && !i.IsNestedPublic)
            .ToList();

        foreach (var iface in inaccessibleInterfaces)
        {
            result.Interfaces.Remove(iface);
        }
    }
}

在生成代理时指定这个Hook:

var proxyGenerator = new ProxyGenerator();
var hook = new SkipInaccessibleInterfacesHook();
var proxyOptions = new ProxyGenerationOptions(hook);
var uiProxy = proxyGenerator.CreateClassProxy<MyUserInterface>(proxyOptions, new YourInterceptor());

方案2:仅拦截自定义业务方法

如果不需要拦截Form类自带的方法,只需要记录自己定义的业务方法调用,可在拦截器中过滤方法来源:

public class YourInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // 仅处理MyUserInterface自身定义的方法
        if (invocation.Method.DeclaringType == typeof(MyUserInterface))
        {
            Console.WriteLine($"记录方法调用:{invocation.Method.Name}");
        }
        // 直接执行原方法,跳过Form类方法的拦截逻辑
        invocation.Proceed();
    }
}

方案3:提取业务逻辑到接口,拦截接口代理

将MyUserInterface的业务逻辑提取到公共接口,通过拦截接口代理来避免直接处理Form类的内部接口问题:

// 定义业务接口
public interface IUserInterfaceLogic
{
    void ProcessUserAction();
}

// 让Form类实现接口
public class MyUserInterface : Form, IUserInterfaceLogic
{
    public void ProcessUserAction()
    {
        // 自定义业务逻辑
    }
}

生成接口代理:

var targetForm = new MyUserInterface();
var proxy = proxyGenerator.CreateInterfaceProxyWithTarget<IUserInterfaceLogic>(targetForm, new YourInterceptor());

这种方式更符合设计原则,同时彻底规避Form类内部接口带来的代理问题。


关于注册环节的说明

并非遗漏了基础配置,而是Castle DynamicProxy的默认行为会代理目标类的所有接口和可重写方法,而Form类的内部接口特性触发了权限问题。通过上述自定义Hook或接口分离的方式,即可解决该异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:52:21