Page 1 of 2

Exception occurs when trying to import a *.ten file

Posted: Tue Dec 04, 2007 8:40 pm
by 8739068
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.

Posted: Wed Dec 05, 2007 9:06 am
by narcis
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.

code

Posted: Wed Dec 05, 2007 2:32 pm
by 8739068
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.

Posted: Wed Dec 05, 2007 3:26 pm
by narcis
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.

Possible root cause

Posted: Wed Dec 05, 2007 4:11 pm
by 8739068
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.

Posted: Fri Dec 07, 2007 11:42 am
by narcis
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.

Any hints on serializing ValueList

Posted: Mon Dec 10, 2007 4:05 am
by 8739068
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);
}

}

Posted: Mon Dec 10, 2007 4:36 pm
by narcis
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
  }

Thanks that seems to work for me

Posted: Mon Dec 10, 2007 5:32 pm
by 8739068
That seems to work. I learned a little more about serialization.

Some issues with ICustomSerialization

Posted: Mon Dec 10, 2007 11:25 pm
by 8739068
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.#."

Re: Some issues with ICustomSerialization

Posted: Tue Dec 11, 2007 11:30 am
by Chris
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.

Will you be fixing the issues with ICustomSerialization?

Posted: Tue Dec 11, 2007 1:59 pm
by 8739068
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.

Re: Will you be fixing the issues with ICustomSerialization?

Posted: Tue Dec 11, 2007 3:43 pm
by Chris
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.

Proposed behavior

Posted: Tue Dec 11, 2007 4:15 pm
by 8739068
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.

Re: Proposed behavior

Posted: Tue Dec 11, 2007 4:54 pm
by Chris
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.