locked
Object of type 'X' cannot be converted to type 'X'. It is the same object so why can't it convert? RRS feed

  • Question

  • Hi, I've created a Class called FullFileName & I serialise it. (it is used to set an item in a Property Dialog)

    Once it is reading the data it has serialised it seems to work without error. But the 1st time I execute it. (after a new recompile) I get the following error message.
    Failed to set property 'FileFatigueZone' for indicator 'TI Stochastic': Object of type 'TradersInternational.Structures.FileFullName' cannot be converted to type 'TradersInternational.Structures.FileFullName'.

    I believe this occurs in the property setter on line
            set { fileFatigued = value; }

    Do I need to write some kind of TypeConverter Class to make the assignement. Or am I looking in the wrong place ie:It is reading an empty or invalid values when trying to DeSerialize the object. Or something else dumb?

    Any tips gratefully recieved.

    Dave

    The full code for the "Property setter" method is

    [Editor(typeof(UIFileFullNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
    TypeConverterAttribute(typeof(FileFullNameConverter)),
    DescriptionAttribute("Name of .wav File for Reversing or Leaving a Fatigue Zone. Default: Fatigued.wav")]
    [GridCategory("Properties - Fatigue Zone")]
    [Gui.Design.DisplayName("Sound: SD Fatigued")]		
    public FileFullName FileFatiguedZone
    {
      get { return fileFatigued; }
      set {fileFatigued = value; }
    }
    

    The full code for the FileFullName Class is below

     

    #region Using declarations
      using System;
      using System.ComponentModel;
      using System.Diagnostics;
      using System.Drawing;
      using System.Drawing.Drawing2D;
      using System.Xml.Serialization;
      using NinjaTrader.Cbi;
      using NinjaTrader.Data;
      using NinjaTrader.Gui.Chart;
    
      using System.Reflection; // for Assembly
      using System.Windows.Forms; //for FileDialog
      using System.IO;	// for Path, Directory, DirectoryInfo
      using System.Drawing.Design; // for UITypeEditioEditStyle
      using System.Globalization; // for CultureInfo
      using System.Runtime.Serialization;
      using TradersInternational.Structures;
    #endregion
    
    namespace TradersInternational.Structures
    {
      #region Sound FileFullName Splitter
    
      [DescriptionAttribute("Expand to split the File Name and Path.")]
      [Serializable()]
      public class FileFullName : ISerializable
      {
        private string _FilePath = @"C:\Program Files\NinjaTrader 7\sounds"; // The Directory the file is located. Not including the Filename.
        private string _FileName = @"Alert4.Wav"; // Only the Filename an Extension. Not including the path.
        // A field that is not serialized.
        //  	[NonSerialized()] private string InvalidErrorMessage; // Pass back a string to be displayed via Ninja Log, if Path or Filename fail IsValid() check
    
        #region -- Serialization Code --
        /// <summary> Method to Custom Serialize this object
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
          //use the info object to add the items you want serialized
          info.AddValue("_FilePath", _FilePath);
          info.AddValue("_FileName", _FileName);
        }
    
        /// <summary> Custom Constructor to DeSerialize this object
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        public FileFullName(SerializationInfo info, StreamingContext context)
        {
          if (info == null)
          {
            //let's bring back our File name into the local variables.
            this._FilePath = @"C:\Program Files\NinjaTrader 7\sounds";
            this._FileName = @"Alert4.Wav";
          }
          else
          {
            //let's bring back our File name into the local variables.
            this._FilePath = info.GetString("_FilePath");
            this._FileName = info.GetString("_FileName");
          }
        }
        #endregion
    
        /// <summary> Default Constructor
        /// </summary>
        public FileFullName()
        {
        }
    
        // ---< Used to let the string be initialised in the Variables section >---
        /// <summary> Constructor to permit initialising via a Fully Qualified Filename
        /// </summary>
        /// <param name="FullFileName">String Fully Qualified Filename</param>
        public FileFullName(string FullFileName)
        {
          if (FullFileName == null)
          {
            throw new System.ArgumentException("Parameter cannot be null", "FullFileName");
          }
          _FileName = Path.GetFileName(FullFileName);
          _FilePath = Path.GetDirectoryName(FullFileName);
          this.IsValid();
        }
    
        /// <summary> Name of File including Extension
        /// </summary>
        /// <returns>Filename. ie Alert1.wav</returns>
        [DefaultValueAttribute("MarketUp.wav")]
        public string FileName
        {
          get { return _FileName; }
          set
          {
            _FileName = value;
            this.IsValid();
          }
        }
    
        /// <summary> File Directory without the Filename
        /// </summary>
        /// <returns>Directory. Default C:\Program Files\NinjaTrader 7\sounds</returns>		
        [DefaultValueAttribute(@"C:\Program Files\NinjaTrader 7\sounds")]
        public string FilePath
        {
          get { return _FilePath; }
          set
          {
            _FilePath = value;
            this.IsValid();
          }
        }
    
        /// <summary> Fully Qualified FileName
        /// </summary>
        /// <returns>Fully Qualified FileName. Path + Filename + Extension</returns>
        public override string ToString()
        {
          return Path.Combine(_FilePath, _FileName);
        }
    
        /// <summary> Sets for Filepath & FileName Properties at the same time. Error checking only done once.
        /// </summary>
        /// <param name="FullFileName">Fully Qualified FileName. Path + Filename + Extension</param>
        public void FromString(string FullFileName)
        {
          if (FullFileName == null) {
            throw new System.ArgumentNullException("Parameter cannot be null", "FullFileName");
          }
          _FileName = Path.GetFileName(FullFileName);
          _FilePath = Path.GetDirectoryName(FullFileName);
          this.IsValid();
        }
    
        /// <summary> Checks to see if FileName exists on the disk
        /// </summary>
        /// <param name="ErrorMessage">String containing a message explaining why the Filepath is invalid.</param>
        /// <returns>FALSE: When Filename points to an invalid location. See ErrorMessage for details. TRUE: ErrorMessage is an empty string.</returns>
        public bool IsValid()
        {
          //string ErrorMessage){
          try
          {
            // ---< if Path exists, all is valid. >---
            if (File.Exists(Path.Combine(_FilePath, _FileName)))
            {
              return true;
            }
    
            if (Directory.Exists(_FilePath))
            {
              // -- Directory Exists but Path doesn't, So Invalid File.
              throw new System.IO.FileNotFoundException(string.Format("Unable to open sound file: Directory {0} doesn't contain a file called {1}. Check if it exists", _FilePath, _FileName));
            }
            else
            {
              // -- Directory doesn't exist, so Invalid File.
              throw new System.IO.DirectoryNotFoundException(string.Format("Unable to open sound file: Directory {0} not found.", _FilePath));
            }
          }
          catch (Exception e)
          {
            throw new System.Exception(e.ToString());
            //				ErrorMessage = string.Format("Unable to open sound file: {0} in directory {1} Check if it exists", _FileName, _FilePath);
          }
          finally { }
          return false;
        }
    
        /// <summary> Finds the Sound Directory for the sound files supplied with Ninja
        /// </summary>
        /// <returns>Default sound directory for Ninja Instalation</returns>
        public string GetNinjaSoundDirectory()
        {
          // -- Default location in v7.0 = C:\\Program Files\\NinjaTrader 7\\sounds\\ 
          try
          {
            // ===< Get Default Directory >===
    
            // --- Find the Ninja Trader Instalation Directory default for Ver 7.0 = C:\Program Files\NinjaTrader 7\bin >---
            DirectoryInfo NinjaExePath = new DirectoryInfo(Assembly.ReflectionOnlyLoadFrom(@"NinjaTrader.exe").Location);
    
            // --- Get the Parent Dir of the directory containing the NinjaTrader Executable
            DirectoryInfo parentDir = NinjaExePath.Parent.Parent;
    
            // --- Find the subdir that contains the sounds.
            string soundDirectory = Path.Combine(parentDir.FullName, "sounds");
    
            // --- Return a valid sound directory --
            if (Directory.Exists(soundDirectory))
              return soundDirectory;
    
          }
          catch (Exception e)
          {
            throw new System.Exception(e.ToString());
            //--- Need to figure out how to write to the Ninja Log, & remove namespace conflicts.
            //      	Log(string.Format("Unable to open sound file directory: {0}", e.ToString()), NinjaTrader.Cbi.LogLevel.Warning);
          }
          finally { }
    
          return "";
        }
      }
    
      public class FileFullNameConverter : ExpandableObjectConverter
      {
        // ===< State that converting from this object to a string is supported. >===    
        public override bool CanConvertTo(ITypeDescriptorContext context, System.Type destinationType)
        {
          if (destinationType == typeof(FileFullName))
            return true;
    
          return base.CanConvertTo(context, destinationType);
        }
    
        // ===< Merge the Properties into a String >===
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, System.Type destinationType)
        {
          if (destinationType == typeof(System.String) && value is FileFullName)
          {
            FileFullName FN = (FileFullName)value;
            if (FN.FilePath == null && FN.FileName == null)
              return @"";
            if (FN.FilePath != null)
              return FN.FileName; //Shrunk to only show Filename but really track file path as well.
          }
          return base.ConvertTo(context, culture, value, destinationType);
        }
    
        // ===< Enable the String Representation to be Edited >===
        public override bool CanConvertFrom(ITypeDescriptorContext context, System.Type sourceType)
        {
          if (sourceType == typeof(string))
            return true;
    
          return base.CanConvertFrom(context, sourceType);
        }
        // ===< Convert from a String to a FileName >===
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
          if (value is string)
          {
            try
            {
              string path = (string)value;
    
              FileFullName myFile = new FileFullName();
              myFile.FileName = Path.GetFileName(path);
              myFile.FilePath = Path.GetDirectoryName(path);
              myFile.FilePath = Path.GetDirectoryName(path);
              if (myFile.FilePath == null)
              {
                // File was in Root level directory ie: C:\.
                myFile.FilePath = Path.GetPathRoot(path);
              }
              return myFile;
            }
            catch (System.IO.PathTooLongException)
            {
              throw new PathTooLongException("Can not convert '" + (string)value + "' to type FileFullName Path too Long");
            }
            catch (System.ArgumentException)
            {
              new ArgumentException("Can not convert '" + (string)value + "' to type FileFullName");
            }
            catch
            {
              throw new ArgumentException("Can not convert '" + (string)value + "' to type FileFullName");
            }
          }
          return base.ConvertFrom(context, culture, value);
        }
      }
    
      public class UIFileFullNameEditor : System.Drawing.Design.UITypeEditor
      {
        /// <summary> Determines if an: Ellipsis Button, Dropdown Arrow or nothing should be displayed
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
          if (context != null && context.Instance != null)
          {
            if (!context.PropertyDescriptor.IsReadOnly)
            {
              return UITypeEditorEditStyle.Modal;
            }
          }
          return UITypeEditorEditStyle.None;
        }
    
        /// <summary> Show the Dialog Box that assists to Edit the Prameter value
        /// </summary>
        /// <param name="context"></param>
        /// <param name="provider"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        [RefreshProperties(RefreshProperties.All)]
        public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
        {
          if (context == null || provider == null || context.Instance == null)
          {
            return base.EditValue(provider, value);
          }
    
          FileDialog fileDlg;
          if (context.PropertyDescriptor.Attributes[typeof(SaveFileAttribute)] == null)
          {
            fileDlg = new OpenFileDialog();
          }
          else
          {
            fileDlg = new SaveFileDialog();
          }
          fileDlg.Title = "Select " + context.PropertyDescriptor.DisplayName;
    
          FileFullName FNS = (FileFullName)value;
          fileDlg.FileName = FNS.FileName;
          fileDlg.InitialDirectory = FNS.FilePath;
          fileDlg.Filter = "Sound files (*.wav)|*.wav|All files (*.*)|*.*";
          fileDlg.FilterIndex = 1;
    
          fileDlg.DefaultExt = "wav";
    
          FileDialogFilterAttribute filterAtt = (FileDialogFilterAttribute)context.PropertyDescriptor.Attributes[typeof(FileDialogFilterAttribute)];
          if (filterAtt != null)
          {
            fileDlg.Filter = filterAtt.Filter;
          }
          if (fileDlg.ShowDialog() == DialogResult.OK)
          {
            FNS.FilePath = Path.GetDirectoryName(fileDlg.FileName);
            FNS.FileName = Path.GetFileName(fileDlg.FileName);
            //value = FNS;
          }
          fileDlg.Dispose();
          return value;
        }
    
        [AttributeUsage(AttributeTargets.Property)]
        public class FileDialogFilterAttribute : Attribute
        {
          private string _filter;
    
          public string Filter
          {
            get { return this._filter; }
          }
    
          public FileDialogFilterAttribute(string filter)
          {
            this._filter = filter;
          }
        }
    
        [AttributeUsage(AttributeTargets.Property)]
        public class SaveFileAttribute : Attribute
        {
        }
    
      }
      #endregion
    }
    

     

     

     

    Friday, April 22, 2011 12:12 PM

Answers

  • Hi David,

    I used your code and as you said it compiles first time without error!! Its absolutely right and second time I get an error

    Failed to set property 'FileFatigueZone' for indicator 'TI Stochastic': Object of type 'TradersInternational.Structures.FileFullName' cannot be converted to type 'TradersInternational.Structures.FileFullName'. 

    To the best what I did was I just right clicked and went in project properties and disabled the Generate Serializable Assembly checkbox which removed my error.  Try using it.  It will surely be helpful to you.  Try Advanced Settings Options also as your code contains explicit references to local file system.

    Thanking You,

    Roozan Bharucha

    MCT, MCPD Framework 4.0 Windows

    • Proposed as answer by Rex Honour Monday, April 25, 2011 7:27 AM
    • Marked as answer by eryang Monday, May 2, 2011 3:51 AM
    Monday, April 25, 2011 7:26 AM

All replies

  • The problem with the binary serializer is that the serialization format is very tightly coupled to an assembly and assemblies change.  This is one of the primary reasons that XML is such a popular serialization format - it is easy to read and write and since it is an external schema it only changes when you decide to change it.  In your case, even relatively minor changes to a class followed by a recompile can cause your serialized data to no longer match your type.  When you deserialize an object serialized by a previous version of your assembly, while they may appear to be the same type, they actually aren't, so the assignment fails.

    That's just a guess.  These kind of issues are the reason I don't use the binary serializer - ever.

    Evan

    Friday, April 22, 2011 11:44 PM
  • Hi David,

     

    How did you serialize/deserialize the FullFileName object? You also mentioned "Once it is reading the data it has serialised it seems to work without error. But the 1st time I execute it. (after a new recompile) I get the following error message. ", what changes you made before the new recompilation?

     

    Could you please check the Generate serialization assembly option of your project's Properties page, you can disable the option and retry.


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, April 25, 2011 4:09 AM
  • Hi David,

    I used your code and as you said it compiles first time without error!! Its absolutely right and second time I get an error

    Failed to set property 'FileFatigueZone' for indicator 'TI Stochastic': Object of type 'TradersInternational.Structures.FileFullName' cannot be converted to type 'TradersInternational.Structures.FileFullName'. 

    To the best what I did was I just right clicked and went in project properties and disabled the Generate Serializable Assembly checkbox which removed my error.  Try using it.  It will surely be helpful to you.  Try Advanced Settings Options also as your code contains explicit references to local file system.

    Thanking You,

    Roozan Bharucha

    MCT, MCPD Framework 4.0 Windows

    • Proposed as answer by Rex Honour Monday, April 25, 2011 7:27 AM
    • Marked as answer by eryang Monday, May 2, 2011 3:51 AM
    Monday, April 25, 2011 7:26 AM
  • I understand from Evan and Eryang's answers the object can't be deserialize after recompilation. As Evan said XML serialization is a flexible one, you can even edit the xml file if you know about the schema. However if your class structure (only instance members) changed after the serialization it won't deserialize back as there is conflicts with initialization of new fields. Both XML and Binary serialization provides a way to define optional fields. Keep all the newly added fields as optional and if you know how to populate the new fields do it on the deserialization events. .Net framework 3 and above provides an advanced way on XML serialization, the DataContract serialization.

    Here is a link about .Net version tolerant serialization http://msdn.microsoft.com/en-us/library/ms229752%28v=vs.80%29.aspx

    Link on XmlIgnore attribute http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlattributes.xmlignore.aspx

    Link on Non Serialized attribute in binary serialization http://msdn.microsoft.com/en-us/library/system.nonserializedattribute%28v=vs.80%29.aspx

    Discussion on XML serializer Vs Datacontract. http://www.danrigsby.com/blog/index.php/2008/03/07/xmlserializer-vs-datacontractserializer-serialization-in-wcf/ basically Datacontract uses opt-in where xml serializer uses opt-out in view of optional fields.

     

     


    Monday, April 25, 2011 7:53 AM
  • Thanks Roozan,

     

     You solved my issue. In .net 2010 for Generate Serializable Assembly microsoft has provided dropdown list. To solve the issue set  Generate Serializable Assembly to OFF


    Zalak Shah
    Thursday, September 1, 2011 9:38 AM