I need to serialize 3 different objects into 3 different XMLs. Further, i will deserialize it.
My Class Design:
class Program
{
public static void Main()
{
CarsPersistence cars = new CarsPersistence()
{
Cars = new Car[]
{
new Car{ Name = "Car1", Speed = 201},
new Car{ Name = "Car2", Speed = 202},
new Car{ Name = "Car3", Speed = 203},
new Car{ Name = "Car4", Speed = 204},
new Car{ Name = "Car5", Speed = 205},
}
};
WaysPersistence ways = new WaysPersistence()
{
Ways = new Way[]
{
new Way{Number = 100, Length = 200 },
new Way{Number = 101, Length = 201 },
new Way{Number = 102, Length = 202 },
new Way{Number = 103, Length = 203 },
new Way{Number = 104, Length = 204 },
new Way{Number = 105, Length = 205 },
new Way{Number = 106, Length = 206 },
new Way{Number = 107, Length = 207 },
}
};
CarsWaysPersistence carsWays = new CarsWaysPersistence()
{
CarsWays = new KeyValuePair<Car, Way>[]
{
new KeyValuePair<Car, Way>(cars.Cars[0], ways.Ways[2]),
new KeyValuePair<Car, Way>(cars.Cars[3], ways.Ways[1])
}
};
}
}
[Serializable]
public class Car
{
public int Speed { get; set; }
public string Name { get; set; }
}
[Serializable]
public class CarsPersistence
{
public Car[] Cars { get; set; }
}
[Serializable]
public class Way
{
public int Number { get; set; }
public int Length { get; set; }
}
[Serializable]
public class WaysPersistence
{
public Way[] Ways { get; set; }
}
public class CarsWaysPersistence
{
public KeyValuePair<Car, Way>[] CarsWays { get; set; }
}
I will serialize 3 persistence classes (CarsPersistence, WaysPersistence, CarsWaysPersistence) in different XML files.
My problem is duplication: CarsWaysPersistence have Car and Way objects which are already consists in other XML files. Probably, i can not save reference in XML file.
How this duplication can be solved.
Thanks
1) Serialize all cars.
2) Serialize all ways.
3) Use Name of the car as a unique identifier. You have to provide some unique key to Way as well. This would allow you to map them by the key: <car_name, way_key>.
Related
This is the code behind of the main page in my xamarin app
public partial class MainPage : ContentPage
{
PenStockVM<PenStock> penstocks;
public MainPage()
{
InitializeComponent();
penstocks = new PenStockVM<PenStock>();
//I get the error at this point saying that this cast is invalid. How to fix this?
listView.ItemsSource = (System.Collections.IEnumerable)penstocks;
BindingContext = penstocks;
}
}
This is my Penstock ViewModel class:
class PenStockVM<Penstock>
{
public List<PenStock>PenStocks { get; set; }
public PenStockVM()
{
PenStocks = new List<PenStock>();
FillPenStockData();
}
private ObservableCollection<Graph> FillGraphData()
{
ObservableCollection<Graph> entries = new ObservableCollection<Graph>();
Random random = new Random();
for (int i = 0; i < 10; i++)
{
entries.Add(new Graph { Time = i, Units = random.Next(100) });
}
return entries;
}
private void FillPenStockData()
{
PenStock object1 = new PenStock { Id = 1, Name = "Main PenStock", Data =
FillGraphData(), Rotations = 100 };
PenStocks.Add(object1);
PenStock object2 = new PenStock { Id = 2, Name = "Weir", Data = FillGraphData(),
Rotations = 100 };
PenStocks.Add(object2);
PenStock object3 = new PenStock { Id = 3, Name = "Spillway", Data = FillGraphData(),
Rotations = 100 };
PenStocks.Add(object3);
PenStock object4 = new PenStock { Id = 4, Name = "Sub PenStock 1", Data =
FillGraphData(), Rotations = 100 };
PenStocks.Add(object4);
PenStock object5 = new PenStock { Id = 5, Name = "Sub PenStock 2", Data =
FillGraphData(), Rotations = 100 };
PenStocks.Add(object5);
PenStock object6 = new PenStock { Id = 6, Name = "Sub PenStock 3", Data =
FillGraphData(), Rotations = 100 };
PenStocks.Add(object6);
}
}
This is my PenStock model class:
public class PenStock
{
public int Id { get; set; }
public string Name { get; set; }
public ObservableCollection<Graph> Data { get; set; }
public int Rotations { get; set; }
}
This is my other Graph model class:
public class Graph: INotifyPropertyChanged
{
private int time;
private int units;
public event PropertyChangedEventHandler PropertyChanged;
public int Time
{
get { return time; }
set
{
time = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Time"));
}
}
public int Units
{
get { return units; }
set
{
units = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Time"));
}
}
}
Do I get this error because I am trying to cast a generic list and the listView only accepts non-generic collections as item source? I am new to xamarin and please help me! Thank you.
I would set ItemsSource to PenStockVM.PenStocks. ItemsSource property specifies the items to display, which are defined in a list. A ListView is populated with data using the ItemsSource property, which is of type IEnumerable.
listView.ItemsSource = penstocks.PenStocks;
so today I tried to create a class for my inventory and add items to it. I created 2 classes, one with my inventory: name,amount,slot and one with a list List<Inventory>. But it always showed exceptions with this code:
public class Inventory
{
public string name { get; set; }
public int amount { get; set; }
public int slot { get; set; }
}
public class InventoryList
{
public List<Inventory> invList = new List<Inventory>();
}
In my startup code i serialized it,which worked, but i tried to deserialize it, and it threw exceptions.
Inventory inventory = new Inventory() { name = "Burger", amount = 1, slot = 2 };
string jsonString = JsonSerializer.Serialize(inventory);
So first of all, when i try to get the items in the list i get this error:
What i want: I want a clear JSON-String, which i can deserialize in C#.
i want, that the list looks like this:
[
{
"name":"cheese",
"amount":5,
"slot":1,
},
{
"name":"Bread",
"amount":2,
"slot":4,
},
]
You basically want to serialize/deserialize a LIST of objects. Here's a working example:
Inventory inventory = new Inventory() { name = "cheese", amount = 5, slot = 1 };
Inventory inventory2 = new Inventory() { name = "Bread", amount = 2, slot = 4 };
var inventoryList = new List<Inventory>()
{
inventory,
inventory2
};
var options = new JsonSerializerOptions()
{
WriteIndented = true
};
string jsonString = JsonSerializer.Serialize(inventoryList, options);
Console.Write($"Serialized list {jsonString} {Environment.NewLine}");
var list = JsonSerializer.Deserialize<List<Inventory>>(jsonString);
Console.Write($"Deserialization completed");
Result:
The example above matches the JSON structure that you said you need.
If you still need an object wrapper it should work like this:
class Program
{
static void Main(string[] args)
{
Inventory inventory = new Inventory() { name = "cheese", amount = 5, slot = 1 };
Inventory inventory2 = new Inventory() { name = "Bread", amount = 2, slot = 4 };
var invList = new List<Inventory>()
{
inventory,
inventory2
};
InventoryList inventoryList = new InventoryList() {invList = invList };
var options = new JsonSerializerOptions()
{
WriteIndented = true
};
string jsonString = JsonSerializer.Serialize(inventoryList, options);
Console.Write($"Serialized list {Environment.NewLine} {jsonString} {Environment.NewLine}");
var list = JsonSerializer.Deserialize<InventoryList>(jsonString);
Console.Write($"Deserialization completed");
}
}
public class Inventory
{
public string name { get; set; }
public int amount { get; set; }
public int slot { get; set; }
}
public class InventoryList
{
public List<Inventory> invList { get; set; }
}
Note the change for invList. It's a get/set property now.
However, this wrapper will add another layer of curly brackets to your json:
Result:
You're trying to Deserialize Inventory type and assign the result object to InventoryList
You can learn from this sample (different json format)
public class Inventory
{
public string name { get; set; }
public int amount { get; set; }
public int slot { get; set; }
}
public class InventoryList
{
public List<Inventory> invList { get; set; }
}
//SAMPLE 1
InventoryList lInventory = new InventoryList()
{
invList = new List<Inventory>
{
new Inventory {name = "cheese", amount = 5, slot = 1 },
new Inventory {name = "Bread", amount = 2, slot = 4 }
}
};
//it will produce
//{"invList":[{"name":"cheese","amount":5,"slot":1},{"name":"Bread","amount":2,"slot":4}]}
string jsonString = JsonSerializer.Serialize(lInventory);
//How to deserialize
InventoryList inventoryList = (InventoryList)JsonSerializer.Deserialize<InventoryList>(jsonString);
//SAMPLE 2
List<Inventory> invList = new List<Inventory>
{
new Inventory {name = "cheese", amount = 5, slot = 1 },
new Inventory {name = "Bread", amount = 2, slot = 4 }
};
//it will produce
//[{"name":"cheese","amount":5,"slot":1},{"name":"Bread","amount":2,"slot":4}]
string jsonString2 = JsonSerializer.Serialize(invList);
//How to deserialize
List<Inventory> inventoryList2 = (List<Inventory>)JsonSerializer.Deserialize<List<Inventory>>(jsonString2);
Let's suppose that I want to create the following document
{
"Id": "6a23a5f3-0f77-40a9-b9f9-26e88537a962",
"CarHistory": [
{ "model":"ford", "price": 100, "kilometers": 100 "current": true },
{ "model":"ford", "price": 200, "kilometers": 200, "current": false },
]
}
In Poco I guess that the model could look something among these lines:
public class Document
{
public Guid Id { get; set; }
}
public class Car : Document
{
public string Model {get; set;}
public decimal Price {get; set;}
public int Kilometers {get; set;}
public bool Current {get; set;}
}
So later I create..
public class MasterCar : Document
{
public ICollection<Car> CarHistory { get; set; } = new List<Car>();
}
All seems to work fine while debugging:
I create the Guid programmatically somewhere in a service like:
var masterCar = new MasterCar(){ Id = Guid.NewGuid() }
but when I go to the cosmos db emulator and a SELECT * FROM , and I checkout the Id property its value is:
"id": "00000000-0000-0000-0000-000000000000",
Can someone point me what Im doing wrong? or how this should be accomplished, I read that
you should not provide an Id yourself, BUT how can I access the Id property programmatically then?
For example:
CarService.GetById(Car.Id); //Id property doesnt exist if there is no property in poco
Below is my test code, you can have a try:
Document.cs
public class Document
{
[JsonProperty("id")]
public Guid Id { get; set; }
}
Car.cs
public class Car
{
[JsonProperty("model")]
public string Model { get; set; }
[JsonProperty("price")]
public decimal Price { get; set; }
[JsonProperty("kilometers")]
public int Kilometers { get; set; }
[JsonProperty("current")]
public bool Current { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
MasterCar.cs
public class MasterCar : Document
{
public ICollection<Car> CarHistory { get; set; } = new List<Car>();
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
create and search:
var guid = Guid.NewGuid();
var masterCar = new MasterCar() { Id = guid };
var car = new Car() { Model = "ford", Price = 100, Kilometers = 100, Current = true };
var car2 = new Car() { Model = "ford", Price = 200, Kilometers = 200, Current = false };
var carHistory = masterCar.CarHistory;
carHistory.Add(car);
carHistory.Add(car2);
CosmosClient client = new CosmosClient(connection_string);
Container container = client.GetContainer(databaseId, containerName);
await container.CreateItemAsync<MasterCar>(masterCar);
ItemResponse<MasterCar> itemResponse = await container.ReadItemAsync<MasterCar>(guid.ToString("D"), new PartitionKey(guid.ToString("D")));
Console.WriteLine(itemResponse.Resource.ToString());
Result:
I have 3 tables Drivers, Races and DriverRaces.
public partial class Driver
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Driver()
{
this.DriverRaces = new HashSet<DriverRace>();
}
public int DriverID { get; set; }
[DisplayName("Name")]
public string DriverName { get; set; }
[DisplayName("Number")]
public string DriverNumber { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<DriverRace> DriverRaces { get; set; }
}
public partial class DriverRace
{
public int DriverRaceID { get; set; }
public int Points { get; set; }
[DisplayName("Driver")]
public Nullable<int> Driver_DriverID { get; set; }
[DisplayName("Race")]
public Nullable<int> Race_RaceID { get; set; }
public virtual Driver Driver { get; set; }
public virtual Race Race { get; set; }
}
public partial class Race
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Race()
{
this.DriverRaces = new HashSet<DriverRace>();
}
public int RaceID { get; set; }
public System.DateTime RaceDate { get; set; }
[DisplayName("Name")]
public string RaceName { get; set; }
[DisplayName("Class")]
public string RaceClass { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<DriverRace> DriverRaces { get; set; }
}
There are 5 classes of races, a driver can be in more than one class, and can compete in multiple races. I am trying to write a linq statement to get the top 5 drivers of each class, and the sum of their total points from each race in that class.
I know how to select all rookie drivers and get their names and points
var drivers = DriverRaces.Where(d=>d.Points > 0 && d.Race.RaceClass == "Rookie");
foreach (var driver in drivers){
Console.WriteLine("Driver Name is {0} points is {1}", driver.Driver.DriverName, driver.Points);
}
Which could return something like
Driver Name is Alexander points is 100
Driver Name is Mady points is 99
Driver Name is Blake points is 98
Driver Name is Alexander points is 100
Driver Name is Mady points is 99
Driver Name is Tom points is 98
But I want it to show
Driver Name is Alexander points is 200
Driver Name is Mady points is 198
Driver Name is Blake points is 98
Driver Name is Tom points is 98
I need help adding up each drivers totals and then sorting them.
To achieve the goal you will need to aggregate these results. There are two approaches one uses Aggregate other Select. Aggregate is more performant while Select is cleaner.
I've added a small example to indicate behavior:
class Program
{
static void Main(string[] args)
{
List<Driver> driversFirstTable = new List<Driver>()
{
new Driver
{
DriverName = "John", DriverRaces = new Collection<DriverRace>
{
new DriverRace { Points = 99, Category = "Rookie" },
new DriverRace { Points = 100, Category = "Rookie" },
new DriverRace { Points = 10, Category = "Mid" },
new DriverRace { Points = 99, Category = "Pro" },
}
},
new Driver
{
DriverName = "Jack", DriverRaces = new Collection<DriverRace>
{
new DriverRace { Points = 100, Category = "Rookie" },
new DriverRace { Points = 98, Category = "Rookie" },
new DriverRace { Points = 66, Category = "Mid" },
new DriverRace { Points = 100, Category = "Pro" },
}
},
new Driver
{
DriverName = "Richard", DriverRaces = new Collection<DriverRace>
{
new DriverRace { Points = 98, Category = "Rookie" },
new DriverRace { Points = 99, Category = "Rookie" },
new DriverRace { Points = 62, Category = "Mid" },
new DriverRace { Points = 98, Category = "Pro" },
}
},
new Driver
{
DriverName = "Will", DriverRaces = new Collection<DriverRace>
{
new DriverRace { Points = 97, Category = "Rookie" },
new DriverRace { Points = 97, Category = "Rookie" },
new DriverRace { Points = 61, Category = "Mid" },
new DriverRace { Points = 97, Category = "Pro" },
}
}
};
var rookieTop = driversFirstTable
.Select(x => new DriverAggregated { Category = "Rookie", DriverName = x.DriverName, TotalPoints = x.DriverRaces.Where(y => y.Category == "Rookie").Sum(y => y.Points) })
.OrderByDescending(x => x.TotalPoints)
.Take(3);
// Will is not in the list
foreach (var driver in rookieTop)
{
Console.WriteLine($"Driver - {driver.DriverName} gathered {driver.TotalPoints} points.");
}
Console.Read();
}
}
class DriverAggregated
{
public string DriverName { get; set; }
public int TotalPoints { get; set; }
public string Category { get; set; }
}
public class Driver
{
public string DriverName { get; set; }
public virtual ICollection<DriverRace> DriverRaces { get; set; }
}
public class DriverRace
{
public int Points { get; set; }
public string Category { get; set; }
}
EDIT:
Another approach could be to use Aggregate function not as pretty but more performant:
var topRookie = driversFirstTable.Select(x => x.DriverRaces.Aggregate(new DriverAggregated() { Category = "Rookie", DriverName = x.DriverName }, (seed, race) =>
{
if (race.Category == seed.Category)
seed.TotalPoints += race.Points;
return seed;
}))
.OrderByDescending(x => x.TotalPoints)
.Take(3);
I need a final json format as follows and that should be dynamic.
{
"product_items" :
[
{
"_at" : 1,
"product_id" : "999"
},
{
"_at" : 2,
"quantity" : 2.00
},
{
"_delete_at" : 3
}
]
}
How to create a json format as above in the code._at field is dynamic.sometimes it might be 2 and sometimes it might be 10.I dont have idea on to generate the json dynamically in c#.
class Test
{
public ProductItem[] product_items { get; set; }
class ProductItem
{
public int[] _at { get; set; }
public int[] _delete { get; set; }
public int[] quantity { get; set; }
public string[] product_id{get;set;}
}
}
i have create the the properties for json as above.
I'm using Newtonsoft library
Your class should look more like this:
public class ProductItem
{
public int _at { get; set; }
public string product_id { get; set; }
public double? quantity { get; set; }
public int? _delete_at { get; set; }
}
public class ProductItemObject
{
public List<ProductItem> product_items { get; set; }
}
A example on serializing :
List<ProductItem> list = new List<ProductItem>();
ProductItemObject o = new ProductItemObject { product_items = list };
var item1 = new ProductItem { _at = 1, product_id = "001" };
var item2 = new ProductItem { _at = 2, quantity = 2.00 };
var item3 = new ProductItem { _delete_at = 3 };
list.Add(item1);
list.Add(item2);
list.Add(item3);
string json = JsonConvert.SerializeObject(o, Formatting.Indented);
// json string :
// {
// "product_items": [
// {
// "_at": 1,
// "product_id": "001",
// "quantity": null,
// "_delete_at": null
// },
// {
// "_at": 2,
// "product_id": null,
// "quantity": 2.0,
// "_delete_at": null
// },
// {
// "_at": 0,
// "product_id": null,
// "quantity": null,
// "_delete_at": 3
// }
// ]
//}
An alternative full dynamic that gets u the same Json string without any model :
var jsonObject = new JObject();
dynamic objectList = jsonObject;
objectList.product_items = new JArray() as dynamic;
dynamic item = new JObject();
item._at = 1;
item.product_id = "999";
objectList.product_items.Add(item);
item = new JObject();
item._at = 2;
item.quantity = 2.00;
objectList.product_items.Add(item);
item = new JObject();
item._delete_at = 3;
objectList.product_items.Add(item);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObject, Formatting.Indented);
Well, if I understand you properly and you just need to be able to generate that json, the product list should be dynamic with maybe anonymous classes then:
public class Products
{
public Products()
{
product_items = new List<dynamic>();
}
public List<dynamic> product_items { get; set; }
}
products.product_items.Add(new { _at = 1, product_id = "999" });