【问题标题】:Inter-addin communication插件间通信
【发布时间】:2012-01-30 23:04:36
【问题描述】:

我已经能够使用CreateToolWindow2 以编程方式从 F# Interactive 创建一个 VS2010 插件工具窗口,它本身就是一个工具窗口。我传递给CreateToolWindow2AssemblyClass 参数对应于构成工具窗口的Panel (WinForms)。通过ControlObject out ref 参数“返回”对已创建面板的引用。

ComVisible(true) 属性标记了我的面板程序集后,我确实得到了返回的实例,除非我尝试访问实例的任何成员(从F# Interactive 的上下文中)我得到RemotingException:“这远程代理没有通道接收器,这意味着服务器没有注册的服务器通道正在侦听,或者此应用程序没有合适的客户端通道与服务器通信。"

有什么办法可以绕过这个障碍吗?

【问题讨论】:

  • this 有帮助吗?
  • @Daniel - 谢谢,我已经看到了,它看起来很相关,但没有看到答案对我有什么帮助(我几乎没有使用过 Remoting API)。我的部分麻烦可能是我的面板控件,已经从Panel 继承,不能也从MarshalByRefObject 继承。此外,CreateToolWindow2 实际上创建了我的面板实例并将其交还给我......不确定我缺乏对象所有权是否会使事情变得困难(参考“......在两端创建通道。”) .
  • @Daniel - 实际上,Panel 最终确实继承自 MarshalByRefObject,所以我想我有一些事情要做......

标签: c# f# remoting envdte f#-interactive


【解决方案1】:

这有点原始,我个人认为它很脏,但总是有使用文件系统来管理通信的回退。指定两个插件都可以访问的临时文件并管理它们之间的锁定,突然间你就有了一个跨插件通信系统。这当然假设您愿意更改两个插件以使用该方法(我不确定您是否会考虑预先打包的插件之一)。

【讨论】:

  • +1 表示一个古怪而合理的想法!但我肯定会坚持采用更清洁的方法!
【解决方案2】:

WCF service 使用 named pipes。我现在这样做是为了在一些 WF4 活动的设计表面和 Visual Studio 扩展之间进行交流。

做起来很简单。我无法显示所有代码,因为其中一些包含在控制打开和关闭通道的助手中,但定义非常简单,并且全部在代码中完成。

你只需要定义一个绑定

var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);
binding.ReceiveTimeout = TimeSpan.FromMinutes(1);

创建您的频道

var channelFactory = new ChannelFactory<IServiceInterface>(binding, endpointAddress);

并且您必须确保端点地址在客户端和服务器中都保证相同,它们共享相同的进程但存在于不同的AppDomain中。一种简单的方法是将地址范围限定为进程 ID...

private const string AddressFormatString =
    "net.pipe://localhost/Company/App/HostType/{0}";
private static string _hostAddress;

public static string HostAddress()
{
    if (_hostAddress == null)
        _hostAddress = string.Format(
                           AddressFormatString, 
                           Process.GetCurrentProcess().Id);
    return _hostAddress;
}

您将拥有两个实际副本(一个在客户端 appdomain 中,一个在插件 appdomain 中),但由于它们都在同一个进程中,因此主机地址保证在两者中相同,您不会遇到同时加载多个 VS 实例的问题(没有可怕的运行对象表,谢谢)。

我将此地址代码保存在基本主机类中。打开主播频道也很简单:

Host = new ServiceHost(this, new Uri(HostAddress()));

var binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);    
Host.AddServiceEndpoint(typeof(IServiceInterface), binding, HostAddress());
Host.Open();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2013-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多