using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.Contracts; using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Runtime.InteropServices; using System.Windows.Forms; namespace SystemX.Net.Platform.Common.Event { public interface ISysXEventField : ISynchronizeInvoke { void ProcessEvent(IObservableEvent evt); } public class OSCAREventHandler : ISubscribable { public Subject ApplicationSubject = new Subject(); protected List _applicationSubscriptions = new List(); public ISysXEventField TheApplicationTarget { get; set; } public static OSCAREventHandler TheApplication { get; private set; } public OSCAREventHandler(ISysXEventField eventField) { Contract.Requires(eventField is Form); Contract.Requires(TheApplication == null); TheApplication = this; TheApplicationTarget = eventField; var observable = Observable .Interval(TimeSpan.FromSeconds(1)) .Take(5); var observer = System.Reactive.Observer.Create( x => Console.WriteLine("Value published to subject #1: {0}", x), () => Console.WriteLine("Sequence Completed.")); AddSubscription(ApplicationSubject.Subscribe(evt => OnApplicationEvent(evt))); } /// /// Applicatino event 처리. /// Note: ObservableEventTask{Starting, Finished} 는 별도 subscription 을 통해서 처리 됨. /// /// private void OnApplicationEvent(IObservableEvent evt) { // 샘플 코드 bool onMainThread = !TheApplicationTarget.InvokeRequired; //System.Media.SystemSounds.Beep.Play(); // thread 상에서 호출되었다면, main UI thread 상에서 수행되도록 한다. //TheApplicationForm.Do(() => //{ //logger.Info($"Application got event : {evt}"); //((IOSCAREventField)TheApplicationForm).HandleStationEvent(evt); ProcessObservableEventHandler(evt); //}); } protected delegate void ObservableEventHandler(IObservableEvent evt); private void ProcessObservableEventHandler(IObservableEvent evt) { if (TheApplicationTarget.InvokeRequired) { ObservableEventHandler delState = new ObservableEventHandler(ProcessObservableEventHandler); (TheApplicationTarget as Control).Invoke(delState, evt); } else { TheApplicationTarget.ProcessEvent(evt); } } public void AddSubscription(IDisposable subscription) { _applicationSubscriptions.Add(subscription); } public void Dispose() { Dispose(true); // true : 명시적 dispose 호출 GC.SuppressFinalize(this); // 사용자에 의해서 명시적으로 dispose 되었으므로, GC 는 이 객체에 대해서 손대지 말것을 알림. } private bool _disposed; protected virtual void Dispose(bool disposing) { if (_disposed) return; if (disposing) { // AwaitTermination() call hangs. Need to check Akka document. // CommonApplication.ActorSystem.AwaitTermination(); _applicationSubscriptions.ForEach(s => s.Dispose()); } _disposed = true; } } public class TestEvent : IObservableEvent { public string Process { private set; get; } public string Path { set; get; } public TestEvent(string process, string strPath) { Process = process; Path = strPath; } } /// /// Rx event 에 대한 subscribe 가 가능한 객체가 구현해야 할 interface /// Dispose 시에 모든 subscription 을 dispose 해야 한다. /// public interface ISubscribable : IDisposable { /* Usage sample private List _subscriptions = new List(); public void AddSubscription(IDisposable subscription) { _subscriptions.Add(subscription); } // Requires disposal of subscriptions on Dispose() method * */ void AddSubscription(IDisposable subscription); } /// Configuration interface [Guid("8501C86A-61E7-4F92-B90A-1779CCF6AAF3")] [InterfaceType(ComInterfaceType.InterfaceIsDual)] [ComVisible(true)] public interface IConfiguration : ICloneable { /// Save configuration to file void QSave(string fileName); /// Load configuration from file void QLoad(string fileName); } /// /// Rx: System.Reactive.Subjects.Subject 에 대한 base interface /// [ComVisible(false)] public interface IObservableEvent { } public interface IObservableUIEvent : IObservableEvent { } }