I have the Viewmodel:
public class PartnerSearchResultVM
{
public int Id { get; set; }
public string Name { get; set; }
public string Latitude { get; set; }
public string Longitude { get; set; }
public double Distance { get; set; }
public string Classification { get; set; }
}
I get the distance in meters from the database like this: 2354,58764478263 m
I would like to present 2.35 km
How change the Viewmodel to make the convertion there (if it's the best place to do it)
I'd add a read-only property to your model.
public double Kilometers { get { return this.Distance / 1000; } }
If you want a formatted string back I'd create a second readonly property.
public string KilometerDisplay {
get {
return String.Format("{0:0.00}km", this.Kilometers);
}
}
Although, depending on your use case, a generalized format function might be appropriate. Perhaps as an extension method:
[Extension]
public string FormatDistance(this double distance) {
return distance.FormatDistance("");
}
[Extension]
public string FormatDistance(this double distance, string unitString) {
return return String.Format("{0:0.00}{1}", distance, unitString);
}
// for meters: result.Distance.FormatDistance("m");
// for kilometers: result.Kilometers.FormatDistance("km");
Then add some XML documentation to the Distance property explaining that it is in meters.
Related
I have a class defined as follows:
public class NearestLocation
{
public Int32 ID { get; set; }
public String Name { get; set; }
public String TypeID { get; set; }
public String SourceID { get; set; }
public String Code { get; set; }
public Double Latitude;
public Double Longitude;
public Int32? Distance { get; set; }
public String Direction { get; set; }
public String Relative { get; set; }
public DateTime? LastUpdatedOn { get; set; }
}
and a string jsonData returned from an API call that contains the following JSON:
{\"Latitude\":-45.861900329589844,\"Longitude\":170.36294555664063,\"Distance\":13,\"Direction\":\"E\",\"Relative\":\"Helicopters Otago (South)\",\"ID\":413,\"Code\":\"HOLS\",\"Name\":\"Helicopters Otago (South)\",\"TypeID\":\"helipad\",\"SourceID\":\"holcwh\",\"LastUpdatedOn\":\"2022-05-08T23:18:41.987\"}
When I deserialize jsonData into an object as follows:
NearestLocation nearest = JsonSerializer.Deserialize<NearestLocation>(jsonData);
nearest is only partially populated:
Code: "HOLS"
Direction: "E"
Distance: 13
ID: 413
LastUpdatedOn: {8/05/2022 11:18:41 pm}
Latitude: 0
Longitude: 0
Name: "Helicopters Otago (South)"
Relative: "Helicopters Otago (South)"
SourceID: "holcwh"
TypeID: "helipad"
Why are Latitude and Longitude not being populated? I can see the correct values in the JSON, and other values - of types String, Int32 and DateTime - are all being populated correctly. It is only the doubles that are not being populated correctly.
I don't seem to be able to trace into JsonSerializer to see what's going on under the hood - the debugger just steps over the line. I've checked the names in the JSON and in the class definition to make sure they match - which they do - but I am at a loss to understand why this is happening.
Latitude and Longitude are fields. Adding getter and setter in order to convert them to properties.
public class NearestLocation
{
// Other properties
public double Latitude { get; set; }
public double Longitude { get; set; }
}
From the documentation,
By default, fields are ignored. You can include fields.
To include field for serialization/deserialization, you need to apply the [JsonInclude] attribute as mentioned.
I'm working on a game that uses a grid of hex-shaped tiles. The tiles are saved as this class:
[System.Serializable]
public class Tile
{
public Hex location;
public TerrainType terrainType;
public Color color { get { return terrainType.color; } }
public int distance;
public string label;
public int cost { get { return terrainType.baseMPCost; } }
public int new_cost;
}
Hex is this struct, used to mark the coordinates of the tile in the hex grid:
public struct Hex
{
//private int _q, _r; originally this used a getter/setter for some reason
public int q;
public int r;
public Hex (int Q, int R)
{
q = Q;
r = R;
}
public int s
{
get { return -q - r; }
}
public float x
{
get { return (3f / 2f) * HexMetrics.outerRadius * q; }
}
public float y
{
get { return (Mathf.Sqrt(3f) / 2f * HexMetrics.outerRadius * q + Mathf.Sqrt(3f) * HexMetrics.outerRadius * r); }
}
}
Finally, TerrainType is this struct:
[System.Serializable]
public struct TerrainType
{
public TerrainType(string Name, int BaseMPCost, Color Color)
{
name = Name;
baseMPCost = BaseMPCost;
color = Color;
}
public string name;
public int baseMPCost;
public Color color;
}
All of the tiles are saved as a list in my map script. I'm using the JsonHelper Script from the top comment on this thread, which writes the list to an array, producing this file.
However, loading the file with the same script gives this error:
ArgumentException: JSON parse error: Invalid value.
UnityEngine.JsonUtility.FromJson (System.String json, System.Type type) (at <1a491ffb1c7c42349a050cc1542277fb>:0)
UnityEngine.JsonUtility.FromJson[T] (System.String json) (at <1a491ffb1c7c42349a050cc1542277fb>:0)
JsonHelper.FromJson[T] (System.String json) (at Assets/Scripts/JsonHelper.cs:9)
InputStateMapEdit.HandleInput () (at Assets/Scripts/StateMachine/InputStates/InputStateMapEdit.cs:57)
InputManager.Update () (at Assets/Scripts/InputManager.cs:40)
When I paste the file into json2csharp.com, it interprets it like this:
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class Color
{
public double r { get; set; }
public double g { get; set; }
public double b { get; set; }
public double a { get; set; }
}
public class Grid
{
public Location location { get; set; }
public TerrainType terrainType { get; set; }
public int distance { get; set; }
public string label { get; set; }
public int new_cost { get; set; }
}
public class Location
{
public int q { get; set; }
public int r { get; set; }
}
public class Root
{
public int Width { get; set; }
public int Height { get; set; }
public List<Grid> Grid { get; set; }
}
public class TerrainType
{
public string name { get; set; }
public int baseMPCost { get; set; }
public Color color { get; set; }
}
I'm not exactly sure why it can't convert this back into the structs and classes I wrote originally, but a lot of them seem to be renamed, are missing some data, etc. Also, the entire list of tiles doesn't appear at all, just their basic components. Is there something preventing them from being properly serialized and written to the JSON file? I think I could probably create another class that stores all the relevant data points as normal floats and integers, then create all new tiles based on them, but I don't want to do that for everything I try to save (especially scenarios, which will include units and such with lots of data) in the future.
Edit - Here is the actual code that writes the Json file:
var m = map.grid.ToArray();
string grid = JsonHelper.ToJson<Tile>(m);
File.WriteAllText("C:/SG/Strategy Game/Assets/test.json", grid);
And the code that reads it:
var m = JsonHelper.FromJson<Tile>("C:/SG/Strategy Game/Assets/test.json");
map.grid = m.ToList();
The problem is that the JsonUtility doesn't support serializing just an array..
... Similarly, passing an array to this method will not produce a JSON array containing each element, but an object containing the public fields of the array object itself (of which there are none). To serialize the actual content of an array or primitive type, it is necessary to wrap it in a class or struct.
To serialize the array properly, we just need a small wrapper class:
[System.Serializable]
public class TileListWrapper {
public Tile[] tiles;
}
and then we create a new TileListWrapper and serialize that instead:
var m = map.grid.ToArray();
var wrapper = new TileListWrapper() {
tiles = m,
};
string grid = JsonUtility.ToJson<TileListWrapper>(wrapper);
File.WriteAllText("C:/SG/Strategy Game/Assets/test.json", grid);
and also deserialize into TileListWrapper:
var wrapper = JsonUtility.FromJson<TileListWrapper>("C:/SG/Strategy Game/Assets/test.json");
map.grid = wrapper.tiles.ToList();
In C#, is it possible to read a class tree path in a string and access programmatically a value, given an instance of that class ?
For example:
public class LogGeometricModel
{
public double SmallEndDiameter { get; set; }
public double LargeEndDiameter { get; set; }
public class Log
{
public Guid Id { get; set; }
public LogGeometricModel GeometricModel { get; set; }
}
public class Solution
{
public DateTime TimeStamp { get; set; }
public double Price { get; set; }
public Log RotatedLog { get; set; }
}
The strings could be something like this (a path in the class tree):
SmallEndDiameter = "Solution/RotatedLog/GeometricModel/SmallEndDiameter"
LargeEndDiameter = "Solution/RotatedLog/GeometricModel/LargeEndDiameter"
Price = "Solution/Price"
Id = "Solution/Log/Id"
By reading those strings, I would like to access the actual values of SmallEndDiameter, LargeEndDiameter, Price and Id.
Absolutely possible yes.
public static object GetValue(object instance, string path)
{
object currentObject = instance;
foreach (string propertyName in path.Split('/'))
{
currentObject = currentObject
.GetType()
.GetProperty(propertyName)
.GetValue(currentObject, null);
}
return currentObject;
}
You don't need to include 'Solution' in the string. This obviously lacks error handling, which if you are parsing a string like this, you will want.
I am busy with a really small console application for c#. I am just new into c# and i'm only familiar with Java. My school gave the assignment to create a console application that simulates a car dealer. I already wrote a bunch of code to add cars by console. Things like brand and type and max speed are already implemented. The only thing i still need to realize is the auto creation and incremental of an ID for a car. It has the be unique of course.
My first approach was making the id field static and increment it in the constructor so that each time the object gets created the id gets ++;
I saw allot of people on stackoverflow doing allot of things but the solutions did not work or the where to big.
This is my code;
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public static int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID++;
}
}
I added 3 cars to my list but the result is that all cars have ID 3;
Maybe someone could help me, thanks in advance.
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; private set; }
public static int globalCarID;
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID = Interlocked.Increment(ref globalCarID);
}
}
This maintains a global ID counter, and increments it atomically to make it thread-safe.
Note that the first ID assigned this way would be 1. You can initialize globalCarID with -1 to start at 0.
Just to remove static and add lock section for avoiding duplicate of Ids
class Car : Vehicle
{
private static object sync = new object();
private static int _globalCount;
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
lock (sync)
{
this.carID = ++globalCount;
}
}
}
A static variable is shared between all instances of the class.
Incrementing it in the constructor makes all instances of that class 'see' the last value assigned to the static variable.
You should create a normal instance carID variable (not static) and use a protected static variable defined in the base class to grab the current value at constructor time, assign to your carID instance variable and then increment the base class value.
class Vehicle
{
protected static int FakeID = 1;
}
class Car : Vehicle
{
public string brand { get; set; }
public string type { get; set; }
public int maxSpeed { get; set; }
public double price { get; set; }
public int carID { get; set; }
public Car(string _brand, string _type, int _maxspeed, double _price)
{
this.brand = _brand;
this.type = _type;
this.maxSpeed = _maxspeed;
this.price = _price;
this.carID = base.FakeID++;;
}
}
void Main()
{
Car a = new Car("xyz", "Auto", 120, 12000);
Car b = new Car("kwx", "Moto", 180, 8000);
Console.WriteLine(a.carID);
Console.WriteLine(b.carID);
}
Keep in mind that this will work correctly if your code doesn't use multithreaded access to the constructor. In case of multithreading you need to look at Interlocked.Increment
i have a class with some properties like this:
public class Car
{
public long No { get; set; }
public string Name { get; set; }
public int Door { get; set; }
public Color Color { get; set; }
public int MaxSpeed { get; set; }
public int Price { get; set; }
}
(this class is an example, my real class is very bigger than it.)
In my program, I need to get difference properties of this class from db(not all properties each time). For example in one case I need name and color of some cars, and in other case I need name and door and price.
I want to create one method that support all difference conditions. I know that i could create it using ‘params’ and ‘enum’, but I am research about best way to do it. Thanks
You can just query the propertie when it is called.
public int Value{
get{
int myValue = getValue();
return myValue;
}
}
Try do this way:
public object[] GetProperties(int state)
{
object[] temp;
switch(state)
{
case(0):
{
temp=new object[]{Name,Color};
}break;
case(1):
{
temp=new object[]{Name,door};
}
}
}
After that, you know , what need return your function, and it's easy parse return result!