Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about deserializing Lengthns were the XML only has a double value for the length #1247

Open
flycast opened this issue May 4, 2023 · 1 comment

Comments

@flycast
Copy link

flycast commented May 4, 2023

I have XML that looks like this:

<Line>
	<Name>Line1</Name>
	<Volume>235.84905660377359</Volume>
	<StartPoint>
		<X>0.11207695625525477</X>
		<Y>0.13272960272211731</Y>
		<Z>0</Z>
	</StartPoint>
	<EndPoint>
		<X>0.15749675983630079</X>
		<Y>0.30305386615104046</Y>
		<Z>0</Z>
	</EndPoint>
</Line>

I need to deserialize this to custom classes called Line and Point. The X, Y and Z of point or of the type Length. The data deserializes just fine except for the 'Length" types. Those end up with a value of zero. Is there a way to use the XML data above an deserialize to a default LengthUnit type like meter?

Line:

public class Line : IEntity, IDebugOutputable, ISplitable, ILength, IRobotElement
    {
        public string Name { get; set; }

        public Point StartPoint { get; set; } = new(new Length(), new Length(), new Length());
        public Point EndPoint { get; set; } = new(new Length(), new Length(), new Length());
        public double Volume { get; set; } = 0;

        public Length Length
        {
            get
            {
                LengthUnit unit = Length.Info.UnitType;
                double a = Math.Pow(EndPoint.X.Value - StartPoint.X.Value, 2);
                double b = Math.Pow(EndPoint.Y.Value - StartPoint.Y.Value, 2);
                double c = Math.Pow(EndPoint.Z.Value - StartPoint.Z.Value, 2);
                var result =  Length.From( Math.Sqrt(a + b + c), unit) ;
                return result;
            }
        }

        public string DebugOutput()
        {
            StringBuilder result = new();
            result.AppendLine();
            result.AppendLine(Name);
            result.AppendLine($"Start point: {StartPoint.DebugOutput()}");
            result.AppendLine($"End point: {EndPoint.DebugOutput()}");
            result.AppendLine($"Volume: {Math.Round(Volume, 3)}");
            return result.ToString();
        }

        public IEntity Split(double percent)
        {
            if (percent <= 0 || percent >= 1) throw new ArgumentOutOfRangeException("percent must be between 0 and 1");

            Line secondLine = new()
            {
                //Fix start point
                StartPoint = Utils.InterpolatePoint(StartPoint, EndPoint, percent),
                EndPoint = EndPoint,
                Volume = Volume * (1 - percent),
                Name = Name + $" - Remainder"
            };

            //Fix first line
            EndPoint = secondLine.StartPoint;
            Volume *= percent;
            Name += $" - Base";

            return secondLine;
        }
    }

Point:

public class Point : IDebugOutputable
    {
        //public Point() { }

        public Point(Length x, Length y, Length z)
        {
            X = x;
            Y = y;
            Z = z;
        }



        public Length X { get; set; }

        public Length Y { get; set; }

        public Length Z { get; set; }

        public string DebugOutput()
        {
            string result = "";
            result += $"X: {Math.Round(X.Value, 3)}, ";
            result += $"Y: {Math.Round(Y.Value, 3)}, ";
            result += $"Z: {Math.Round(Z.Value, 3)}";
            return result;
        }


    }
@angularsen
Copy link
Owner

angularsen commented May 7, 2023

You are probably better off having a non-UnitsNet type for serializing/deserializing, then mapping to UnitsNet after deserializing.

Most serializers support some form of plugins to add converters from/to specific types, but the simplest approach is to have separate types for serialization using standard .NET BCL types (double, decimal, string etc), then manually mapping from/to your domain types that use more complex types like UnitsNet quantities.

For example, you can have two classes: SerializablePoint and Point

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants