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

两个Outlook VSTO插件间传递Object类型数据时出现类型转换异常的求助

解决Outlook插件跨项目传递自定义对象数组的COM代理转换错误

我之前也踩过跨Outlook COM加载项传递自定义对象的坑,你的错误Unable to cast object of type 'System.Runtime.Remoting.Proxies.__TransparentProxy'本质上是COM无法直接识别和传递你自定义的IProfileAttribute类型数组——当跨加载项调用方法时,.NET会把你的自定义对象包装成透明代理,而目标加载项无法将这个代理转换回你的原始自定义类型。

下面是几个经过验证的解决方案,按推荐程度排序:

方案1:序列化为字符串传递(最可靠,适配复杂类型)

把自定义对象序列化为JSON或XML字符串,以string类型传递(你已经确认string类型可以正常传递),目标加载项再反序列化回原始类型。

调用方代码修改:

public IProfileAttribute[] profileAttributes= null;
Outlook.Application outlookApp = new Outlook.Application();
this.profileAttributes = new FilingNotifiableIpmlementation().FilingNotification(); // 填充对象

// 使用Newtonsoft.Json序列化(也可以用System.Text.Json)
string attrJson = Newtonsoft.Json.JsonConvert.SerializeObject(this.profileAttributes);

object destAddinName = "Tikit.CarpeDiem.AddIn.Outlook";
Office.COMAddIn destAddIn = outlookApp.COMAddIns.Item(ref destAddinName);
destAddIn.Object.FilingNotification(attrJson);

目标加载项方法修改:

public void FilingNotification(string profileAttributesJson)
{
    if (!string.IsNullOrEmpty(profileAttributesJson))
    {
        // 反序列化回自定义数组
        var profileAttributesList = Newtonsoft.Json.JsonConvert.DeserializeObject<IProfileAttribute[]>(profileAttributesJson);
        var x = profileAttributesList;
    }
    else
    {
        string y = "Try again";
    }
}

方案2:改用COM原生支持的集合类型传递

如果不想用序列化,可以把自定义数组转换为COM原生支持的ArrayList(而非自定义数组),因为COM能识别ArrayList类型。

调用方代码修改:

public IProfileAttribute[] profileAttributes= null;
Outlook.Application outlookApp = new Outlook.Application();
this.profileAttributes = new FilingNotifiableIpmlementation().FilingNotification(); // 填充对象

// 转换为COM兼容的ArrayList
System.Collections.ArrayList attrList = new System.Collections.ArrayList(this.profileAttributes);

object destAddinName = "Tikit.CarpeDiem.AddIn.Outlook";
Office.COMAddIn destAddIn = outlookApp.COMAddIns.Item(ref destAddinName);
destAddIn.Object.FilingNotification(attrList);

目标加载项方法修改:

public void FilingNotification(System.Collections.ArrayList profileAttributesList)
{
    if (profileAttributesList != null)
    {
        // 转换回自定义类型数组
        var profileAttributes = profileAttributesList.Cast<IProfileAttribute>().ToArray();
        var x = profileAttributes;
    }
    else
    {
        string y = "Try again";
    }
}

关键注意事项(必看)

  • 不管用哪种方案,你的IProfileAttribute接口和实现类必须标记为COM可见,并且确保两个加载项引用的是同一个强命名且版本一致的程序集:
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)] // 确保COM能识别接口成员
    public interface IProfileAttribute
    {
        // 你的属性定义
        string AttributeName { get; set; }
        string AttributeValue { get; set; }
    }
    
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)] // 避免自动生成类接口
    public class ProfileAttribute : IProfileAttribute
    {
        public string AttributeName { get; set; }
        public string AttributeValue { get; set; }
    }
    
  • 部署时,要使用regasm.exe注册包含自定义类型的程序集,带上/codebase参数(如果程序集不在GAC中):
    regasm.exe YourCustomAssembly.dll /codebase /tlb
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 21:47:48