Exception occurs when trying to import a *.ten file

TeeChart for Microsoft Visual Studio .NET, Xamarin Studio (Android, iOS & Forms) & Monodevelop.
Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Exception occurs when trying to import a *.ten file

Post by Mike Jones » Tue Dec 04, 2007 8:40 pm

Exact exception:

System.Reflection.TargetInvocationException was unhandled
Message="Exception has been thrown by the target of an invocation."
Source="mscorlib"
StackTrace:
at System.RuntimeMethodHandle._SerializationInvoke(Object target, SignatureStruct& declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.RuntimeMethodHandle.SerializationInvoke(Object target, SignatureStruct declaringTypeSig, SerializationInfo info, StreamingContext context)
at System.Reflection.RuntimeConstructorInfo.SerializationInvoke(Object target, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.CompleteISerializableObject(Object obj, SerializationInfo info, StreamingContext context)
at System.Runtime.Serialization.ObjectManager.FixupSpecialObject(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at Steema.TeeChart.Import.TemplateImport.Load(Stream stream) in C:\TCC\Development\3rd Party\Source\TeeChartNetV3\Sources\TeeChart\Export\Exports.cs:line 3298
at Steema.TeeChart.Import.TemplateImport.Load(String fileName) in C:\TCC\Development\3rd Party\Source\TeeChartNetV3\Sources\TeeChart\Export\Exports.cs:line 3332
at Steema.TeeChart.Import.TemplateImport.LoadFileDialog() in C:\TCC\Development\3rd Party\Source\TeeChartNetV3\Sources\TeeChart\Export\Exports.cs:line 3356
at GridFun.Form1.button1_Click(Object sender, EventArgs e) in C:\TCC\Projects\Temp\GridFun\GridFun\Form1.cs:line 25
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at GridFun.Program.Main() in C:\TCC\Projects\Temp\GridFun\GridFun\Program.cs:line 17
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()



I created the ten file by using the export feature from the standard chart editor

The exception occured in Export.cs file at

public Chart Load(Stream stream)
{
IChart tmpChart = chart.parent;

Export.SerializeBinder b = new Export.SerializeBinder();
b.BindToType(Texts.TeeChart, "Chart");

BinaryFormatter deserializer = new BinaryFormatter();
deserializer.AssemblyFormat = FormatterAssemblyStyle.Simple;
deserializer.Binder = b;
chart.RemoveAllComponents();

chart = (Chart)deserializer.Deserialize(stream); <- EXCEPTION

if (tmpChart != null)

I imported this TEN file by calling
tChart1.Import.Template.LoadFileDialog();
in a button_click event. Then browsed to the file.

I am using TeeChart.NET 3.2.2831.26851

I have uploaded CausesException.ten file to the Uploads area.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Dec 05, 2007 9:06 am

Hi Mike,

Thanks for the report. I've been able to reproduce the problem here. Could you please send us the code used to generate this chart?

Thanks in advance.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

code

Post by Mike Jones » Wed Dec 05, 2007 2:32 pm

I was using our product in which TeeChart is deeply integrated. It is not reasonable to send our entire source. I will have to try and create a project that will isolate the TeeChart control and reproduce the problem. This may take me a day or two to get to.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Wed Dec 05, 2007 3:26 pm

Hi Mike,

Thanks for the information. Ok, at first glance I haven't found what can be causing the problem. However we will try to investigate this more deeply and if we can't fine anything we will ask you for the code.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Possible root cause

Post by Mike Jones » Wed Dec 05, 2007 4:11 pm

After a little more investigating I think I have found the issue. I have created a series that inherits from Bubble series ( see http://www.teechart.net/support/viewtop ... 6281#26281)

When this series is a part of the TEN file there is an exception when importing.

Do you have a recommendation on how I might avoid this? It would be nice to get the import of a TEN file to work mainly for debugging
purposes.

I would recommend putting a try/catch around the import operation prevent catastrophic crashes.

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Fri Dec 07, 2007 11:42 am

Hi Mike,

Thanks for the information. In that case you need to use ICustomSerialization interface as in the example I posted here.

Hope this helps.
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Any hints on serializing ValueList

Post by Mike Jones » Mon Dec 10, 2007 4:05 am

I am a little inexperienced with custom serialization.

In my RectangleBubble series, the series is not compiled into the TeeChart.dll. Can I still serialize/deserialize this class?

Do you have any examples of serializing/deserializing ValueList? That is really the only custom data within RectangleBubble. When I import a saved TEN file that has my RectangleBubble series in it, get the error "Index was outside the bounds of the array". I am guessing because the Deserialization does not know about my RectangleBubble series class because it never calls my DeSerialize() method.

/// <summary>
/// Serialize custom properties
/// </summary>
/// <param name="info"></param>
public void Serialize(System.Runtime.Serialization.SerializationInfo info)
{
info.AddValue("_x2Values", _x2Values.Value);
info.AddValue("_y2Values", _y2Values.Value);


}

/// <summary>
/// Deserialize custom propeties
/// </summary>
/// <param name="info"></param>
public void DeSerialize(System.Runtime.Serialization.SerializationInfo info)
{
try
{
double[] x2 = (double[])info.GetValue("_x2Values", typeof(double[]));
double[] y2 = (double[])info.GetValue("_y2Values", typeof(double[]));
}
catch (Exception ex)
{
// TODO: Log error
System.Diagnostics.Debug.WriteLine("Error:" + ex.Message);
}

}

Narcís
Site Admin
Site Admin
Posts: 14730
Joined: Mon Jun 09, 2003 4:00 am
Location: Banyoles, Catalonia
Contact:

Post by Narcís » Mon Dec 10, 2007 4:36 pm

Hi Mike,

To be able to serialize/deserialize RectangleBubble series you need to do like this:

Code: Select all

  public class RectangleBubble : Bubble, Steema.TeeChart.Export.TemplateExport.ICustomSerialization
  {
    private Graphics3D g;
    private ValueList widthValues;
    private ValueList heightValues;

    public RectangleBubble() : this(null) { }
    public RectangleBubble(Steema.TeeChart.Chart c)
      : base(c)
    {
      g = c.Graphics3D;

      widthValues = new ValueList(this, "Rectangle Width Values");
      heightValues = new ValueList(this, "Rectangle Height Values");
      Pointer.Style = PointerStyles.Rectangle;
      Activate();
    }


    public ValueList WidthValues
    {
      get { return widthValues; }
      set { widthValues = value; }
    }

    public ValueList HeightValues
    {
      get { return heightValues; }
      set { heightValues = value; }
    }
	

    private void Activate()
    {
      if (!Utils.SeriesTypesOf.Contains(typeof(RectangleBubble)))
      {
        Utils.RegisterSeries(typeof(RectangleBubble), typeof(Steema.TeeChart.Editors.Series.PointSeries), 1, 0);
      }
    }

    public override void Draw()
    {
      base.Draw();
    }

    private void IncrementArray(ValueList list)
    {
      list.Count++;
      int tmp = list.Value.Length;
      if (list.Count > tmp)
      {
        if (list.Capacity > 0)
          tmp += list.Capacity;
        else
          if (list.Count > 3)
            tmp += list.Count / 4;
          else
            tmp += 100;

        double[] newValue = new double[tmp];
        list.Value.CopyTo(newValue, 0);
        list.Value = newValue;
      }
    }

    private void InsertChartValue(ValueList list, int valueIndex, double value)
    {
      IncrementArray(list);

      for (int t = list.Count - 1; t > valueIndex; t--) list.Value[t] = list.Value[t - 1];
      list.Value[valueIndex] = value;
    }

    public int Add(double x, double y, double w, double h, string text, Color color)
    {
      int tmp = Add(x, y, text, color);

      InsertChartValue(widthValues, tmp, w);
      InsertChartValue(heightValues, tmp, h);

      return tmp;
    }

    public void Add(Array xValues, Array yValues, Array wValues, Array hValues)
    {
      int numPoints = yValues.GetLength(0);
      widthValues.Count = numPoints;
      widthValues.Value = ConvertArray(wValues, numPoints);
      heightValues.Count = numPoints;
      heightValues.Value = ConvertArray(hValues, numPoints);

      //RadiusValues not used, to avoid axes calculation exception only
      RadiusValues.Count = numPoints;
      RadiusValues.Value = heightValues.Value;

      Add(xValues, yValues);
    }

    public override void DrawValue(int valueIndex)
    {
      if (widthValues.Count > valueIndex)
      {
        point.HorizSize = CalcXSizeValue(widthValues[valueIndex] / 2);
        point.VertSize = CalcYSizeValue(heightValues[valueIndex] / 2);

        //This draws using x and y values as the center of the Rectangle
        DrawPointer(CalcXPos(valueIndex), CalcYPos(valueIndex), ValueColor(valueIndex), valueIndex);
      }
    }

    #region ICustomSerialization Members


    public void Serialize(System.Runtime.Serialization.SerializationInfo info)
    {
      Trim(WidthValues); //HeightValues needs to be a *Public Property* otherwise it won't serialize.
      Trim(HeightValues);

      info.AddValue("WidthValues.Value", WidthValues.Value, WidthValues.Value.GetType());
      info.AddValue("WidthValues.Count", WidthValues.Count, WidthValues.Count.GetType());
      info.AddValue("HeightValues.Value", HeightValues.Value, HeightValues.Value.GetType());
      info.AddValue("HeightValues.Count", HeightValues.Count, HeightValues.Count.GetType());
    }

    private void Trim(ValueList v)
    {
      double[] newValue = new double[v.Count];
      Array.Copy(v.Value, 0, newValue, 0, v.Count);
      v.Value = newValue;
    }

    public void DeSerialize(System.Runtime.Serialization.SerializationInfo info)
    {
      HeightValues.Count = info.GetInt32("HeightValues.Count");
      WidthValues.Count = info.GetInt32("WidthValues.Count");

      WidthValues.Value = info.GetValue("WidthValues.Value", typeof(double[])) as double[];
      HeightValues.Value = info.GetValue("HeightValues.Value", typeof(double[])) as double[];
    }

    #endregion
  }
Best Regards,
Narcís Calvet / Development & Support
Steema Software
Avinguda Montilivi 33, 17003 Girona, Catalonia
Tel: 34 972 218 797
http://www.steema.com
Image Image Image Image Image Image
Instructions - How to post in this forum

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Thanks that seems to work for me

Post by Mike Jones » Mon Dec 10, 2007 5:32 pm

That seems to work. I learned a little more about serialization.

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Some issues with ICustomSerialization

Post by Mike Jones » Mon Dec 10, 2007 11:25 pm

I found that the DeSerialize method is never called. I put a break statement in this method in RectangleBubble. It is not accessed when I import my chart1.ten file. I found that the setter of the properties is getting called, instead

I think it is a bug in the TeeChart.dll. Custom serialization should call the custom Serialize/DeSerialize methods. It only appears to call the Serialize method.

The only way I can get the RectangleBubble class to work without any exceptions is to make the 2 ValueList properties public.

The ICustomSerialization methods do not work. I found when the Serialize method is called, it is not appending the "Series.#." in front of the objects getting serialized. I found this by inspecting the "info.m_member" passed into the Serialize method. So the second RectangleBubble instance throws an exception when serialized because it is missing the prefix "Series.#."

Christopher
Site Admin
Site Admin
Posts: 1349
Joined: Thu Jan 01, 1970 12:00 am
Location: Riudellots de la Selva, Catalonia
Contact:

Re: Some issues with ICustomSerialization

Post by Christopher » Tue Dec 11, 2007 11:30 am

Hello Mike,

You're right and I was wrong, ICustomSerialization is not necessary in this context. If you delete the reference to ICustomSerialization and its implementation in the example Narcís sent you, you will find that the valuelists serialize correctly. All that needs to be done is to make public properties of the values that need to be serialized. I created a dummy boolean public property that serialized/deserialized correctly in the example without ICustomSerialization and it also worked fine.

Many apologies for throwing you a red-herring in the form of ICustomSerialization, as in this instance it is not necessary.
Thank you!

Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Will you be fixing the issues with ICustomSerialization?

Post by Mike Jones » Tue Dec 11, 2007 1:59 pm

It appears to me their are a couple of bugs with ICustomSerialization? Will you be correcting these?

The issue appear to be:

1. No Prefix getting passed into the Serialize method (example Series.#.)
2. Deserialize method is not getting called

I think these are important to correct.

Christopher
Site Admin
Site Admin
Posts: 1349
Joined: Thu Jan 01, 1970 12:00 am
Location: Riudellots de la Selva, Catalonia
Contact:

Re: Will you be fixing the issues with ICustomSerialization?

Post by Christopher » Tue Dec 11, 2007 3:43 pm

Hello Mike,
Mike wrote:It appears to me their are a couple of bugs with ICustomSerialization? Will you be correcting these?

The issue appear to be:

1. No Prefix getting passed into the Serialize method (example Series.#.)
2. Deserialize method is not getting called

I think these are important to correct.
Well, in order to get ICustomSerialization to fit in with your needs, could you let me know how you'd like to use it?

As the TeeChart serialization code stands it seems to be sufficient for the serialization of derived teechart objects.
Thank you!

Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/

Mike Jones
Advanced
Posts: 192
Joined: Thu Feb 01, 2007 12:00 am
Contact:

Proposed behavior

Post by Mike Jones » Tue Dec 11, 2007 4:15 pm

My current requirements have been met, but request that these issues be considered because they are powerful and useful moving into future development of our application.

1. Seems to me if I needed to serialize my custom series that inherits from a Steema.TeeChart.Styles.Series and had an embedded class within my series that I did not want to make public, currently that would be a problem. I was hoping you could see a way to pass in the instance string like "Series.1." into the ICustomSerialization.Serialize. That way when I called info.Add(name, object, type) I could append the string to the name of my object to avoid duplicate names exception. Maybe create another interface that overloads the Serialize method. For example ICustomSerialization2.Serialize( System.Runtime.Serialization.SerializationInfo info, string instancePrefix)

2. Not sure why my ICustomSerialization.DeSerialize method was not getting called. I would have to dig deep into the Export.cs file to find this. Should be straight forward to track that down and fix.

Issue 2 is critical. Issue 1 would be nice to have.

Thanks for your consideration of these issues.

Christopher
Site Admin
Site Admin
Posts: 1349
Joined: Thu Jan 01, 1970 12:00 am
Location: Riudellots de la Selva, Catalonia
Contact:

Re: Proposed behavior

Post by Christopher » Tue Dec 11, 2007 4:54 pm

Hello Mike,
Mike wrote:My current requirements have been met, but request that these issues be considered because they are powerful and useful moving into future development of our application.
I'm glad to hear it. Ok.
Mike wrote: 1. Seems to me if I needed to serialize my custom series that inherits from a Steema.TeeChart.Styles.Series and had an embedded class within my series that I did not want to make public, currently that would be a problem. I was hoping you could see a way to pass in the instance string like "Series.1." into the ICustomSerialization.Serialize. That way when I called info.Add(name, object, type) I could append the string to the name of my object to avoid duplicate names exception. Maybe create another interface that overloads the Serialize method. For example ICustomSerialization2.Serialize( System.Runtime.Serialization.SerializationInfo info, string instancePrefix)
I think ICustomSerialization was designed with classes that serialize and deserialize themselves in mind, rather than classes that can hook into the rest of the teechart serialization/deserialization code. If you look at TeeChart.dll in Reflector and nagivate to Steema.TeeChart.Import.Imports.DeserializeFrom() you can see that the call to TryCustomSerialization lies outside of the loop which iterates through all the other teechart members.
Mike wrote: 2. Not sure why my ICustomSerialization.DeSerialize method was not getting called. I would have to dig deep into the Export.cs file to find this. Should be straight forward to track that down and fix.
Again, using Reflector, try navigating to Steema.TeeChart.Import.Imports.DeserializeFrom(). At the end of that method you will see:

Code: Select all

        if (this.chart is IChart)
        {
            this.TryCustomSerialization((this.chart as IChart).GetControl(), info);
        }
The problem here is that this.chart is of type Steema.TeeChart.Chart, which does not derive from Steema.TeeChart.IChart. That's why the Deserialize method was never getting called.
Mike wrote: Issue 2 is critical. Issue 1 would be nice to have.
Well, we can thank our lucky stars that Issue 2 wasn't critical to the problem which started this thread :)

There's is probably a good reason why TryCustomSerialization() needs a System.Windows.Forms.Control rather than just a System.ComponentModel.Component, which is what Steema.TeeChart.Chart derives from, but without investigating I don't know what it is.
Mike wrote: Thanks for your consideration of these issues.
Thank *you* for your input into this TeeChart area! I'll note these issues in our issue-tracking system and will look at them when I can.
Thank you!

Christopher Ireland (Steema crew)
Please be aware of the newsgroup archives:
http://www.teechart.net/support/search.php
http://groups.google.com
http://codenewsfast.com/

Post Reply