2012-01-30 80 views
0

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

已经打上我的面板的与ComVisible(true)属性我得到恢复,实例除了当我尝试访问该实例的任何成员(从F#互动的上下文中)组装我得到一个RemotingException:“这个远程代理具有没有通道接收器,这意味着服务器没有正在监听的注册服务器通道,或者这个应用程序没有合适的客户端通道与服务器交谈。“

任何想法如何避开这个障碍?

+0

确实[这](http://stackoverflow.com/questions/1657863/remoting-and-missing-channel-sinks)帮助? – Daniel 2012-01-30 05:41:33

+0

@丹尼尔 - 谢谢,我已经看到了,它看起来很相关,但没有看到答案可以帮助我(我几乎没有使用过Remoting API)。我的一部分麻烦可能是我的面板控件已经从'Panel'继承,不能从MarshalByRefObject继承。此外,'CreateToolWindow2'实际上创建了我的面板实例并将其交给我......不确定是否缺少对象的所有权会使事情变得困难(指的是“......两端创建通道”)。 。 – 2012-01-30 05:52:51

+0

@Daniel - 实际上,'Panel'确实最终从MarshalByRefObject继承,所以我想我已经有一些东西在我身边了...... – 2012-01-30 06:02:48

回答

1

这有点原始,我个人认为它很脏,但始终存在使用文件系统来管理通信的后备。指定一个可由两个插件访问的临时文件并管理它们之间的锁定,并且突然间您有一个跨插件通信系统。这当然假设你很容易改变两个插件来使用这个方法(我不确定你会考虑其中一个插件是否被预先包装好)。

+0

对于一个古怪的,可信的想法+1!但我坚持一个更清洁的方法! – 2012-01-30 05:32:14

1

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)两个实际的副本,但由于它们都在同一个进程中,主机地址保证在两者中都是相同的,并且你不会遇到VS同时加载多个VS实例的问题(不要担心Running Object Table,谢谢)。

我将这个地址代码保存在基本主机类中。打开主机通道也很容易:

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

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