UnitsNet
UnitsNet copied to clipboard
Question about deserializing Lengthns were the XML only has a double value for the length
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;
}
}
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
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.
This issue was automatically closed due to inactivity.