--- trunk/libxmltv/Core/XMLTVInstance.cs 2013/03/08 03:41:18 45 +++ trunk/libxmltv/Core/XMLTVInstance.cs 2013/03/08 12:20:50 58 @@ -3,36 +3,217 @@ using System.Linq; using System.Text; using libxmltv.Interfaces; +using System.ComponentModel; +using System.Windows.Forms; +using System.Threading; +using System.Reflection; +using System.Globalization; +using System.Diagnostics; namespace libxmltv.Core { - internal class XMLTVRuntimeInstance : MarshalByRefObject, IXMLTVRuntimeInstance + [Serializable] + internal class XMLTVRuntimeInstance : MarshalByRefObject, + IXMLTVRuntimeInstance, + ISerializer, + IGetCreatedInstanceEvent, + ISetCreatedInstanceEvent, + IDestroyInstance, + IRuntimeInstanceLoader { - public XMLTVRuntimeInstance(string xmlfile) { CreateInstance(xmlfile); } - private void CreateInstance(string xmlfile) + [NonSerialized] + Thread worker; + public XMLTVRuntimeInstance() { - using (Instance = new XMLTVInstance(xmlfile, this)) + } + public XMLTVRuntimeInstance(string xmlfile) + { + worker = new Thread(new ParameterizedThreadStart(CreateInstance)); + //CreateInstance(xmlfile); + worker.Start(xmlfile); + } + //public XMLTVRuntimeInstance(string xmlfile) : this(xmlfile, null) { } + //public XMLTVRuntimeInstance(string xmlfile, EventHandler t) { CreateInstance(xmlfile,t); } + private void CreateInstance(object xmlfile) + { + //CancelEvent = t; + using (XMLTVInstance instance = new XMLTVInstance(xmlfile.ToString(), this)) { + if (OnInstanceCreated != null) + { + OnInstanceCreated.Invoke(this,new EventArgs()); + } } } - internal XMLTVInstance Instance { get; private set; } + + //internal XMLTVInstance Instance { get; private set; } #region IXMLTV_LOADER members - public System.IO.FileInfo XmlFile { get; set; } - public System.Xml.Linq.XDocument XmlDoc { get; set; } + private System.IO.FileInfo _XmlFile; + public System.IO.FileInfo XmlFile { get { return _XmlFile; } set { _XmlFile = value; } } + private string _XmlDoc; + public string XmlDoc { get { return _XmlDoc; } set { _XmlDoc = value; } } #endregion #region IXMLTV_PARSER Members - public IXMLTVSource Source { get; set; } - public Dictionary Channels { get; set; } - public Dictionary Programs { get; set; } + private IXMLTVSource _Source; + public IXMLTVSource Source { get { return _Source; } set { _Source = value; } } + private Dictionary _Channels; + public Dictionary Channels { get { return _Channels; } set { _Channels = value; } } + private Dictionary _Programs; + public Dictionary Programs { get { return _Programs; } set { _Programs = value; } } #endregion - //public void Dispose() - //{ - // IsDisposing = true; - // //throw new NotImplementedException(); - //} - public bool IsDisposing { get; private set; } + [NonSerialized] + private EventHandler _OnInstanceCreated; + public EventHandler OnInstanceCreated { get { return _OnInstanceCreated; } set { _OnInstanceCreated = value; } } + public EventHandler GetOnInstanceCreated() { return OnInstanceCreated; } + public void SetOnInstanceCreated(EventHandler event_instance) { OnInstanceCreated = event_instance; } + + public IXMLTVSerializer Serializer + { + get + { + ///* We have to set CancelEvent to null, before returning a new instance of the serializer otherwise all subscribers to the event will have to be marked as serializeable. + // Most subscribers will be of type: System.Windows.Forms which is not marked as serializable and will fail to serialize. */ + //if (CancelEvent != null) { CancelEvent = null; } + return new XMLTVSerializer(this); + } + } + public void DestroyInstance() + { + xmltv_logger.Debug.WriteLine("Destoying Instance of: '{0}'", this.GetType().Name); + this.IsAborting = true; + if (worker == null) + { + xmltv_logger.Debug.WriteLine("Unable to destroy instance of: '{0}' - worker thread is null", this.GetType().Name); + return; + } + else + { + if (worker.IsAlive) + { + xmltv_logger.Verbose.Debug.WriteLine("Requesting Instance to Abort..."); + while (worker.IsAlive) + { + worker.Abort(); + Application.DoEvents(); + } + } + else + { + xmltv_logger.Debug.WriteLine("Instance of: '{0}'- already destroyed.", this.GetType().Name); + } + } + } + private bool _IsAborting; + public bool IsAborting + { + get { return _IsAborting; } + private set { _IsAborting = value; } + } + public XMLTVRuntimeInstance LoadFromInstance(XMLTVRuntimeInstance instance) + { + if (instance == null) + { + throw new NullReferenceException("Failed to load from instance because the instance is null."); + } + + if (instance.Source != null) + { + xmltv_logger.Debug.WriteLine("Loading from instance..."); + xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Created by '{1}' - original source file: '{2}'", instance.Source.SourceName, instance.Source.GeneratorName, instance.XmlFile.FullName); + } + else + { + xmltv_logger.Error.WriteLine("The Instance's Source Property is null."); + throw new NullReferenceException("The Instance's Source Property is null."); + } + if (instance.Channels != null) + { + xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Channels from source '{1}'", instance.Channels.Count, instance.Source.SourceName); + } + else + { + xmltv_logger.Error.WriteLine("The Instance's Channels Property is null."); + throw new NullReferenceException("The Instance's Channels Property is null."); + } + if (instance.Programs != null) + { + xmltv_logger.Info.WriteLine("Source Loaded: '{0}' Programs from source '{1}", instance.Programs.Count, instance.Source.SourceName); + } + else + { + xmltv_logger.Error.WriteLine("The Instance's Programs Property is null."); + throw new NullReferenceException("The Instance's Programs Property is null."); + } + CloneFromInstance(ref instance); + //if (OnInstanceCreated != null) + //{ + // OnInstanceCreated.Invoke(this, new EventArgs()); + //} + return instance; + } + private void CloneFromInstance(ref XMLTVRuntimeInstance instance) + { + //if (!instance.GetType().IsSerializable) + //{ + // throw new ArgumentException("Loaded instance is not serializable.", "instance"); + //} + //if (Object.ReferenceEquals(instance, null)) + //{ + // throw new NullReferenceException("Failed to load from instance because the instance is null."); + //} + BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + CultureInfo culture = CultureInfo.CurrentCulture; + Type t = typeof(XMLTVRuntimeInstance); + foreach (var field in t.GetFields(flags)) + { + try + { + if (field.IsNotSerialized) + { + continue; + } + + var f = instance.GetType().GetField(field.Name, flags); + + var v = f.GetValue(instance); + field.SetValue(this, v); + } + catch (Exception ex) + { + throw new Exception(string.Format("Unable to copy value for field: '{0}' from instance", field.Name), ex); + } + } + foreach (var property in t.GetProperties(flags)) + { + try + { + //if (property.Attributes.HasFlag(FieldAttributes.NotSerialized)) + //{ + // continue; + //} + var f = instance.GetType().GetProperty(property.Name); + object value = null; + + try + { + value = f.GetValue(instance, null); + } + catch (ArgumentException ex) { if (ex.Message == "Property get method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } } + try + { + property.SetValue(this, value, null); + } + catch (ArgumentException ex) { if (ex.Message == "Property set method not found.") { Debug.WriteLine(ex.ToString()); } else { throw ex; } } + + } + catch (Exception ex) + { + throw new Exception(string.Format("Unable to copy value for property: '{0}' from instance", property.Name), ex); + } + } + } } internal class XMLTVInstance : IDisposable