none
Не работает подписка на событие com сервера c# из клиента c# RRS feed

  • Вопрос

  • Всех приветствую.

    Сделал COM сервер, с возможностью подписки на одно событие, со следующим кодом:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace AsteriskNotifierCom
    {        
        //интерфейс обработки событий
        [Guid("65520F46-0CC6-4F4A-BDE2-D0527C0DBDB8")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIDispatch)]
        public interface IComEvents
        {
            void OnOperationCompleted(string message);
        }
        
        //Интерфейс обработки СОМ объекта
        [Guid("C9239D8C-68BB-4656-81FC-65AD038AFA04")]
        [ComVisible(true)]
        internal interface ICOMfunctions
        {
            [DispId(1)]
            void message(string msg);
        }
    
    
        //Класс обработки СОМ объекта
        [ComVisible(true)]
        [Guid("202802A2-8E85-4073-9A67-534EDE33D580"), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(IComEvents))]
        public class COMfunctions : ICOMfunctions
        {
            public void message(string msg)
            {
                MessageBox.Show(msg, "Это сообщение COM", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    ComEvents Ev=new ComEvents();
                    Ev.GenerateEvent(3);
            }
        }
    
        //Класс обработки событий СОМ объекта
        [ComVisible(true)]
        [ComSourceInterfaces(typeof(IComEvents))]
        public class ComEvents 
        {      
            public ComEvents()
            {
            }
            public delegate void OperationCompletedDel(string message); //No need to expose this delegate
            public event OperationCompletedDel OnOperationCompleted;   
            public void GenerateEvent(int i)
            {                
                    OnOperationCompleted(i.ToString());          
            }
        }
    
    }
    

    Теперь не могу понять как в клиенте правильно подписаться на это событие, делаю так:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using AsteriskNotifierCom;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                
                /*AsteriskNotifierCom. ICOMEvents_OnOperationCompleted coE = new AsteriskNotifierCom.ComEvents();
                AsteriskNotifierCom.Co.OperationCompletedDel ev = new AsteriskNotifierCom.AsteriskNotifierComE.OperationCompletedDel(Form1_OnOperationCompleted);
                coE.OnOperationCompleted += ev; */
    
                ComEvents.OperationCompletedDel dev = new ComEvents.OperationCompletedDel(Form1_OnOperationCompleted);
                ComEvents ev = new  ComEvents();
                ev.OnOperationCompleted+= dev;
                AsteriskNotifierCom.COMfunctions co = new AsteriskNotifierCom.COMfunctions();
                co.message("привет");
                
            }
            public void Form1_OnOperationCompleted(string msg)
            {
                MessageBox.Show(msg);
            }
        }
    }
    

    Но отрабатывает только вызов функции COM объекта, а вот обработка события не срабатывает, может кто подскажет что я делаю не так, в первый раз столкнулся с COM объектами?

    Причем вылетает ошибка NullReferenceException при генерации события, видимо все-таки в клиенте как-то неправильно подписываюсь на это событие?

    Или может кто свой пример выложит, никак не могу разобраться?

    17 августа 2013 г. 20:43

Ответы

  • Какая-то сложная у Вас получилась схема. Во-первых, зачем COM, если сервер и клиент - сборки .NET. Во-вторых, у Вас 2 класса помечены аттрибутом источника событий, а событие декларировано только у второго (COMEvents). Не логичнее ли было завести событие непосредственно у COMfunctions? Тогда второй класс не нужен. Вот, например, так:

    	public delegate void DynamicArrayEventHandler(double val);
    
    	[Guid("9DB136FF-6FE7-4392-A427-5FF0B4CBD5B0")]
    	public interface IDynamicArray2
    	{
    		void Add(double val);
    		...
    	}
    
    	[Guid("8CF17C7A-15E3-4ec2-B568-801A478741EC")]
    	public interface IDynamicArrayEvents
    	{
    		void OnAdd(double val);
    	}
    
    	[Guid("C6BAA99A-4CA0-4082-8236-01A09A4FE58E")]
    	[ComSourceInterfaces(typeof(IDynamicArrayEvents))]
    	public class DynamicArray2 : IDynamicArray2
    	{
    		public event DynamicArrayEventHandler OnAdd;
    
    		public void Add(double val)
    		{
    			...
    			if (OnAdd != null) OnAdd(val);
    		}
    		...
    	}
    

    12 сентября 2013 г. 12:10