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

.NET AppDomain无法附加AssemblyResolve事件的问题求助

问题:跨AppDomain绑定AssemblyResolve事件时类型解析失败

程序结构

  • VB6 可执行程序(主调用端,通过COM调用testpi.dll)
  • VB.NET 编写的 testpi.dll(COM兼容,编译为x86架构)
  • C# 编写的 PlugIn1.dll(被testpi.dll引用)

PlugIn1.dll(C#代码)

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web;
using CommonInterface;

namespace PlugIn1
{
    [Serializable]
    public class PlugIn : MarshalByRefObject, IPlugIn
    {
        private Dictionary<string, RuleHandle> dHandleRules = new Dictionary<string, RuleHandle>();
        private string name;

        public string Name { get { return name; } }

        public void Initialize()
        {
            name = "PlugIn 1";            
        }

        public object GetHandle(string Name, ref string msgErr) {
            msgErr = "";
            try
            {
                if (String.IsNullOrEmpty(Name)) return null;
                if (dHandleRules == null) return null;

                dHandleRules.TryGetValue(Name, out var handle);
                return handle;
            }
            catch (Exception ex)
            {
                msgErr = Error(ex, "PlugIn.LoadAssembly");
            }
            return null;
        }

        public object LoadAssembly(string sInput, string RuleName, string sPrefixClassName, ref string msgErr) {
            RuleHandle hR = null;
            msgErr = "";
            try
            {
                if (System.IO.File.Exists(sInput))
                {
                    Byte[] rawAssembly = LoadFile(sInput);
                    Assembly assemblyr = Assembly.Load(rawAssembly);

                    Type TypeR = assemblyr.GetType("MyScript." + sPrefixClassName + RuleName);
                    Object instance = Activator.CreateInstance(TypeR);

                    hR = new RuleHandle(TypeR, instance);

                    if (dHandleRules == null) dHandleRules = new Dictionary<string, RuleHandle>();    
                    if (dHandleRules.ContainsKey(RuleName)) dHandleRules.Remove(RuleName);
                    dHandleRules.Add(RuleName, hR);

                }
                else {
                    msgErr = "FILE NON TROVATO:" + sInput; 
                }
            }
            catch (Exception ex)
            {
                msgErr=Error(ex, "PlugIn.LoadAssembly");
            }
            return hR;
        }

        private byte[] LoadFile(String filename) {
            Byte[] buffer = File.ReadAllBytes(filename);
            return buffer;            
        }

        private string Error(Exception ex,string procedure) { 
            return  procedure + "\r\n" + ex.Message + "\r\n" + ex.StackTrace.ToString();            
        }

        public void FinalizeInterface() {
            if (dHandleRules != null) dHandleRules.Clear();
            dHandleRules = null;
        }

        ~PlugIn()
        {
            FinalizeInterface();
        }
    }
}

VB6 按钮点击事件代码

Private Sub Command1_Click()  
   Dim obj As Object  
   Set obj = New testpi.tClass1  
   obj.TESTClick
End Sub

testpi.dll(VB.NET代码)

Imports System.Reflection

<Serializable>
Public Class tClass1

Public Sub New()
End Sub

Protected Overrides Sub Finalize()
   MyBase.Finalize()
End Sub

Public sub TESTClick() 
        Dim setup As AppDomainSetup = New AppDomainSetup() With {
            .ApplicationName = "PlugIn1",
            .ConfigurationFile = "PlugIn1" & ".dll.config",
            .ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
        }
    
        Dim appDm As AppDomain = AppDomain.CreateDomain(setup.ApplicationName,          
                                 AppDomain.CurrentDomain.Evidence, setup)
    
        AddHandler appDm.AssemblyResolve, AddressOf AssemblyResolve
End sub    

End Class

触发的错误

unresolved type for member testpi.tclass1, testpi, version 1.0.0.0, Culture neutral PublicKeyToken = null


解决方案

问题根源

AssemblyResolve事件的处理方法属于testpi.tClass1类型,绑定事件时需要将该方法的委托跨AppDomain传递。当前tClass1仅标记了Serializable但未继承MarshalByRefObject,.NET会尝试将整个tClass1实例序列化复制到新AppDomain,而新域无法正确解析tClass1的类型信息,导致错误。

具体修复步骤

  1. 修改tClass1继承MarshalByRefObject
    让tClass1继承MarshalByRefObject,这样跨AppDomain传递的是对象代理而非完整副本,避免序列化问题:

    Imports System.Reflection
    Imports System.IO ' 需添加此引用用于文件路径处理
    
    <Serializable>
    Public Class tClass1
        Inherits MarshalByRefObject ' 新增继承
    
        Public Sub New()
        End Sub
    
        Protected Overrides Sub Finalize()
            MyBase.Finalize()
        End Sub
    
        Public Sub TESTClick() 
            Dim setup As AppDomainSetup = New AppDomainSetup() With {
                .ApplicationName = "PlugIn1",
                .ConfigurationFile = "PlugIn1" & ".dll.config",
                .ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
            }
        
            Dim appDm As AppDomain = AppDomain.CreateDomain(setup.ApplicationName,          
                                     AppDomain.CurrentDomain.Evidence, setup)
        
            AddHandler appDm.AssemblyResolve, AddressOf AssemblyResolve
        End sub    
    
        ' 必须补全AssemblyResolve的实现,否则绑定事件无意义
        Private Function AssemblyResolve(sender As Object, args As ResolveEventArgs) As Assembly
            ' 示例:从当前目录加载目标程序集
            Dim assemblyFileName = $"{args.Name.Split(",")(0)}.dll"
            Dim assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, assemblyFileName)
            
            If File.Exists(assemblyPath) Then
                Return Assembly.LoadFrom(assemblyPath)
            End If
            Return Nothing
        End Function
    End Class
    
  2. 确保新AppDomain的程序集访问路径
    确认AppDomainSetup.ApplicationBase指向包含testpi.dll和PlugIn1.dll的目录,当前代码设置为当前域的BaseDirectory,一般无需修改;若DLL在其他路径,需调整该参数。

  3. 重新注册COM组件
    修改testpi.dll后,以管理员身份运行命令行,执行regasm.exe /codebase testpi.dll重新注册组件,确保VB6能获取到最新版本的组件。

额外提示

  • 跨AppDomain的事件绑定、回调场景,优先使用MarshalByRefObject而非仅依赖Serializable,避免复杂类型的序列化问题。
  • AssemblyResolve方法必须有实际逻辑,否则遇到程序集加载失败时会抛出未处理异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 17:20:41