如何解决继承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
相关产品推荐
相关产品推荐

