I'm using RestSharp to deserialize some data. This works fine and all the data loads correctly, however one of my fields is in csv format (I can't change this unfortunately) and I need to parse out that data and load it into my object.
What is a good way to structure my class so that the code inside loadData() is run when the "data" object receives a value? I basically want to avoid running loadData on its own before I can use every object, as my SkaterData object is created 20+ times.
This is what my class structure looks like:
public class SkaterData
{
public int id { get; set; }
public string data { get; set; }
public PlayerData PlayerData { get; set; }
public void loadData()
{
var dataRows = data.Split(',');
PlayerData = new PlayerData(Int32.Parse(dataRows[0]), dataRows[1], dataRows[2]);
}
}
public class PlayerData
{
public int Number { get; set; }
public string Position { get; set; }
public string Name { get; set; }
public PlayerData(int number, string position, string name)
{
this.Name = name;
this.Position = position;
this.Number = number;
}
}
Both getters and setters are functions which means that you can write something like this:
private string _data;
public int id { get; set; }
public string data
{
get { return _data; }
set
{
_data = value;
loadData();
}
}
public PlayerData PlayerData { get; set; }
public void loadData()
{
var dataRows = data.Split(',');
PlayerData = new PlayerData(Int32.Parse(dataRows[0]), dataRows[1], dataRows[2]);
}
In the above code sample, I explicitly defined the data property (which the syntax you were using is just sytantic sugar for). I then added calling loadData to the setter of this property.
Since that setter will get called on deserialization (probably) you may need a slightly different variant of what I have, but its hard to say what it would be based on your problem statement.
I am pretty sure this is what OnDeserializedAttribute is for, but I have not been able to get it to work using an XmlSerializer (edit: that's because it doesn't implement it I guess).
[OnDeserialized()]
internal void OnDeserializedMethod(StreamingContext context)
{
}
Related
I have the following structure:
public class LogicStatement : ILogicStatement
{
public string TestLogic { get; set; }
public string CompareLogic { get; set; }
public string Operator { get; set; }
public string Expression();
public bool Value();
}
public class Test : ITest
{
public int TestId { get; set; }
public int LiteralId { get; set; }
public string TestName { get; set; }
public string TestText { get; set; }
public string TestDisplayName { get; }
**public ILogicStatement LogicStatement { get; set; }**
public string Expression { get; set; }
public bool Value { get; set; }
}
public class Literal : ILiteral
{
some property members...
**public List<ITest> Tests {get; set;}**
some method members...
}
Note that the class Test has a member of type LogicStatement, and the class Literal has a member of type List.
Note also that all classes have properties and methods that share the same name: Expression, Value, Expression(), Value().
The value of Expression and Value (properties and methods) depend on values in the LogicStatement class.
Throughout the whole project, I use the Interface Type for to instantiate each object to adhere with Dependency Inversion. To support this, I use a factory-like design to create new instances of Test and LogicStatement.
Example:
public static class Factory
{
public static ILogicStatement CreateLogicStatement()
{
return new LogicStatement();
}
public static ITest CreateTest()
{
return new Test(CreateLogicStatement());
}
public static List<ITest> CreateTests()
{
return new List<ITest>();
}
//repeat the same for evey other class.
}
My goal is to have Expression() and Value() be calculated only once in the bottom level class (LogicStatement), and somehow get transfered to their counterpart properties in the higher level classes.
I'm getting the data from Dapper and it looks like all the nested objects are returned from the Dapper module correctly with the same nested structure I intended, and with the right values for all of their members. All of them but Expression, Expression(), Value, Value() are null.
my constructors look like this:
public LogicStatement()
{
Expression();
Value();
}
public Test(ILogicStatement logicStatement)
{
_logicStatement = logicStatement;
Expression = _logicStatement.Expression();
Value = _logicStatement.Value();
}
public Literal(ITest test)
{
_test = test;
Expression = _test.Expression;
Value = _test.Value;
}
and my main:
List<ILiteral> literals = Factory.CreateLiterals();
List<ITest> tests = Facotry.CreateTests();
List<ILogicStatement> logicStatements = Factory.CreateLogicStatements();
literals = GetDataFromDapper();
This last line seems to assign correct values to all other members on all hierarchies. But I cannot get Expression and Value to be anything other than null.
If I test LogicStatement.Expression() and LogicStatement.Value() standalone, they do return the expexted values. but starting at the first parent class Test, these properties are all null.
I think I'm doing something wrong in the way i'm instantiating my objects. Primarily because I'm not sure i understand basic best practices to write constructors.
Maybe I the desired behavior should be implemented through events, where the Test and Literal classes subscribe to changes in the Expression() and Value() methods (or rather to what calculates them). But I never used events and I'd like to know if this fundamentally can be acheived without them first.
My question: How do I make the Expression() Value() at the bottom level class "Fire up" whenever LogicStatement is instantiated, and then have the Expression and Value properties be assigned accordingly as a result.
In other words, I want the following to always be true:
test[i].Expression == literal[i].Expression == LogicStatement[i].Expression()
I'm a beginner in OOP. So any fundamental explanation is welcome.
As you are new to object oriented programming I would start with the basics and leave factories and adhering with Dependency Inversion and the interfaces away for later.
You could tell Dapper to split joined tables into multiple entities (see https://www.learndapper.com/relationships), but for learning OOP I would start doing everything manually.
Your class design does not look proper to me yet. Not sure what Expression and Value of the LogicStatement are, but if they are calculations based on the other properties, I would implement them as (just to show off with complicated words) lazy initialized cached getter properties that are invalidated in the setters of the relevant properties. That ensures you only calculate them once for as many reads you like but recalculate them on first read after one or multiple properties have been updated.
public class LogicStatement {
private string _testLogic;
private string _compareLogic;
private string _operator;
private string? _expression;
private bool? _value;
public LogicStatement(string testLogic, string compareLogic, string #operator) {
_testLogic = testLogic;
_compareLogic = compareLogic;
_operator = #operator;
}
public string TestLogic {
get {
return _testLogic;
}
set {
_testLogic = value;
InvalidateCachedValues();
}
}
public string CompareLogic {
get {
return _compareLogic;
}
set {
_compareLogic = value;
InvalidateCachedValues();
}
}
public string Operator {
get {
return _operator;
}
set {
_operator = value;
InvalidateCachedValues();
}
}
public string Expression {
get {
string? result = _expression;
if (result is null) {
_expression = result = BuildExpression();
}
return result;
}
}
public bool Value {
get {
bool? result = _value;
if (result is null) {
_value = result = EvaluateValue();
}
return result.Value;
}
}
private void InvalidateCachedValues() {
_expression = null;
_value = null;
}
private string BuildExpression() {
//Your logic goes here
throw new NotImplementedException();
}
private bool EvaluateValue() {
//Your logic goes here
throw new NotImplementedException();
}
}
Sorry, it got a bit bigger with the full properties.
In the other classes I would not copy the Value and the Expression but simply remove these properties as anybody can easily access them through the LogicStatement property:
public class Test {
public Test(int testId, int literalId, string testName, string testText, string testDisplayName, LogicStatement logicStatement) {
TestId = testId;
LiteralId = literalId;
TestText = testText;
TestDisplayName = testDisplayName;
LogicStatement = logicStatement;
}
public int TestId { get; }
public int LiteralId { get; }
public string TestName { get; }
public string TestText { get; }
public string TestDisplayName { get; }
public LogicStatement LogicStatement { get; }
}
and the Literal could look like this (I got a bit confused whether this class has one Test or a list of them, I stick to your constructor + properties that hint in the direction of a single one):
public class Literal {
private Test _test;
public Literal(string property1, int property2, Test test) {
Property1 = property1;
Property2 = property2;
_test = test;
}
public string Property1 { get; }
public int Property2 { get; }
public string Expression => _test.LogicStatement.Expression;
public bool Value => _test.LogicStatement.Value;
}
As you decided not to expose the Test in the Literal it makes sense to provide Expression and Value, otherwise they could also be removed (or kept for convenience).
I want to get the price of any crypto coin from BitZ api.
I have the code like this:
string coinName;
string jsonURL = "https://apiv2.bitz.com/Market/coinRate?coins=" + coinName;
I will give the variable coinName the value I want for example coinName = "btc" and I want the price in USDT
The problem here is the Json structure it contains the coin name I will end up with tons of code lines if do this for every coin,
public class Btc
{
public string usdt { get; set; }
}
public class Data
{
public Btc btc { get; set; }
}
public class Root
{
public int status { get; set; }
public string msg { get; set; }
public Data data { get; set; }
public int time { get; set; }
public string microtime { get; set; }
public string source { get; set; }
}
Unlike Bittrex api for example which is easier to read using JsonDotNet asset from unity store and :
BittrexJsonUrl = "https://api.bittrex.com/api/v1.1/public/getticker?market=USDT-" + coinName;
and then I use this code to get the data:
private IEnumerator GetData()
{
/////bittrex
UnityWebRequest request = UnityWebRequest.Get(BittrexJsonUrl);
yield return request.SendWebRequest();
if (request.error == null)
{
Bittrex_proccessJsonData(request.downloadHandler.text);
}
else
{
Debug.Log("Something went wrong!!");
}
}
private void Bittrex_proccessJsonData (string _url) {
var _bittrexJsonData = JsonConvert.DeserializeObject<BittrexJsonData>(_url);
bittrexPrice = _bittrexJsonData.result.Last;
}
this works perfectly with with bittrex's Json structure, since it doesnt contain the coin name all I do is change the Json URL.
Now I want to do like the same thing for BitZ's if you have any idea how to please help :) thank you in advance.
For such thing you could use good old SimpleJson.
Here you don't need to implement the entire c# structure but rather access the data field by field via it's ID. You can imagine it like a nested Dictionary like thing.
Simply create that file with given content from the link somewhere in your project and do e.g.
var json = JSON.Parse(the_JSON_string);
var usdt = json["Data"]["bst"]["usdt"].AsFloat;
I have a similar structure to the one below
Base class
public class BaseClass
{
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Guid Guid { get; set; }
public string Hometown { get; set; }
}
Derived Class
public class DerivedClass : BaseClass
{
public List<DerivedClassDataItem> Data { get; set; }
}
Data class
public class DerivedClassDataItem
{
public string Datum1 { get; set; }
public string Datum2 { get; set; }
public string Datum3 { get; set; }
public string Datum4 { get; set; }
public int Datum5 { get; set; }
public DateTime Datum6 { get; set; }
}
What is the best practice to return specific set of info from the DerivedClass?
a potential set could be:
Name, Address, Guid and then a Data list that only contains Datum1 and Datum4
I could see anonymousTypes, Tuples or another set of class(es), all to be valid approaches.
My concern about creating new set of classs for the set returned is that the class(s) structure will be similar to the structure of the three mentioned above except it will have fewer selected members, which to me, does not sound ideal. (duplicate code and structure)
Using anonymousTypes was my initial solution to tackle this, something like
List<DerivedClass> list = new List<DerivedClass>();
var mySet = list.Select(d => new
{
Name = d.Name,
Address = d.Address,
.
.
.
.
.
Data = d.Data.Select(item => new
{
Datum1 = item.Datum1,
Datum4 = item.Datum4
})
});
but again, that was a headache for us to track through httpResponse and through out API calls.
Should I go with Tuple?
Any insights as to what is the best practice for doing this?
Edit
I am using this set of data to be a response returned by a API/GET call. I will send the set back using HttpRespose and then the framework will transform that into json
this is an actual method we have now
private void populateReturnFile()
{
var returnFileAnonymous = new
{
Vendor = this.Vendor,
OrganizationName = this.OrganizationName,
User = this.User,
Platform = this.Platform,
DictionaryType = this.DictionaryType,
UseCaseId = this.UseCaseId,
Data = this.Data.Select(d => new
{
MigrationTermId = d.MigrationTermId,
ImoLexicalCode = d.ImoLexicalCode
})
};
this.returnFile = returnFileAnonymous;
}
Then my GET will return the retunFile (this is a very simple method, i have remove irrelevant code)
[HttpGet]
public HttpResponseMessage Get(Guid migrationFileId)
{
ProblemList problemList = ProblemList.GetProblemList(migrationFileId);
return Request.CreateResponse(HttpStatusCode.OK, problemList.ReturnFile, new JsonMediaTypeFormatter());
}
If API calls is where you are using these classes, then I personally like to keep it simple and avoid complex inheritance hierarchy. Remember, simple code is good code.
I would make a separate class for each api request/response call. For very simple api calls (ajax requests for example) I like to use anonymous types, but for controllers that only handle API calls I like to create separate classes, organized in a nice folder structure.
Everyone has their "style" but as long as you strive for simplicity your code will be maintainable.
I have a series of classes used to represent identifiers in my project that are supposed to have a specific string storage format. I don't have control on this format.
The classes are pure containers, they don't do anything. The storage format is of the form "CLASSSTYPE|key1|key2|key3|...|keyN". Each "key" can be mapped to one property of the class.
Right now the FromStorageString and ToStorageString functions look like this:
public class SomeTypeId : IObjectId
{
public static string ToStorageString(SomeTypeId id)
{
return string.Format("{0}|{1}|{2}", typeof(SomeTypeId).Name, MyIntKey, MyStringKey);
}
public static SomeTypeId FromStorageString(IdReader source)
{
int intKey = source.Retrieve<int>();
string stringKey = source.Retrieve<string>();
return new SomeTypeId(intKey, stringKey);
}
public int MyIntKey { get; private set; }
public string MyStringKey { get; private set; }
public SomeTypeId(int intKey, string stringKey)
{
MyIntKey = intKey;
MyStringKey = stringKey;
}
}
We are checking the From/To consistency in unit tests, but I feel there should be a way to simplify the set up and perform the check a compile-time.
What I had in mind is something like this:
[Storage("MyIntKey", "MyStringKey")]
public class SomeTypeId : IObjectId
{
private SomeTypeId() {}
public int MyIntKey { get; private set; }
public string MyStringKey { get; private set; }
public SomeTypeId(int intKey, string stringKey)
{
MyIntKey = intKey;
MyStringKey = stringKey;
}
}
But first I don't know how to do this with the no parameters constructor and the property setters staying private. I am reluctant to have them public.
Second this approach is not robust to property name change and typos because the property names in the attribute are strings.
Should I expose the setters and private constructor ?
Is there a better way of doing this ?
I was randomly typing 'fastest serializing c#' into Google and got protobuf.net as a result. I tried it and I think I can serialize properly yet since I can't deserilize, there is no way to tell now is there?!
When trying to deserilaize I get :
A first chance exception of type 'ProtoBuf.ProtoException' occurred in protobuf-net.dll
Cool.
The Data To Serialize:
[ProtoContract]
public struct Cow
{
[ProtoMember(1)]
public float Weight{ get; private set; }
[ProtoMember(2)]
public bool[] HadCowlings{ get; private set; }
public Cow(float weight, bool[] babies)
: this()
{
this.Weight = weight;
this.HadCowlings= (bool[])babies.Clone();
}
...
}
[ProtoContract]
public class Pasture
{
[ProtoMember(1)]
public Point Position { get; private set; }
[ProtoMember(2)]
public Cow[] Cows { get; private set; }
public static int HerdSize { get; private set; }
public static float BoundWidth { get; private set;}
public static float BoundHeight { get; private set; }
public Pasture(Cow[] Cows, Point farmPosition)
{
this.Cows = (Cow[])Cows.Clone();
Position = farmPosition;
}
...
}
[ProtoContract]
public class Farm
{
[ProtoMember(1)]
public Point FarmIDCoordinates{ get; private set; }
[ProtoMember(2)]
public List<Pasture> Pastures{ get; private set; }
public static float BoundWidth { get; private set; }
public static float BoundHeight { get; private set; }
public static int FarmSize { get; private set; }
public Farm(int x, int y, FarmType fType)
{
if (fType == RegionType.STANDARD)
Pastures = new List<Pasture>(//make a farm!);
else
Pastures = new List<Pasture>(//What he said);
FarmIDCoordinates = new Point(x, y);
}
...
}
The How:
Set:
using (ObjectSerializer serializer = new ObjectSerializer())
{
serializer.ProtoSerialize<Farm>(farm.ToString() + ".bin", aFarm)
}
Get:
using (ObjectSerializer serializer = new ObjectSerializer())
{
try
{
farmsIOwn.Add(serializer.ProtoDeserialize<Farm>(
farmLat.X.ToString() + "_" + farmLong.Y.ToString() + ".bin"));
}
catch
{
// make me a dummy farm, crashing is for dummies
}
}
ObjectSerializer:
public void ProtoSerialize<T>(string fileName, T objectGraph)
{
using (var stream = File.Open(fileName, FileMode.Create))
{
Serializer.Serialize<T>(stream, objectGraph);
}
}
public T ProtoDeserialize<T>(string fileName)
{
T objectGraph;
using (var stream = File.Open(fileName, FileMode.Open))
{
objectGraph = Serializer.Deserialize<T>(stream);
}
return objectGraph;
}
protobuf-net can be configured in many different ways. By default, it creates objects via a parameterless constructor, because that option that works on all frameworks. In this usage, it is a bit like XmlSerializer. Because your types don't have a constructor, that usage can't work. The simplest option is to add a parameterless constructor. For use on the full framework this does not need to be public - so a private / protected etc constructor is fine - but note that this (private / protected) won't work on Silverlight etc.
The next option is to skip the constructor completely - a lot like DataContractSerializer. This can be done via attributes or via runtime configuration of the type-model. To illustrate the first:
[ProtoContract(SkipConstructor = true)]
public class Foo {...}
Again - this works great on most frameworks, but there are a few where it doesn't work (the framework utility method to do it simply doesn't exist).
Finally, you can provide your own factory methods; either per-type of globally. This factory method is a static method that returns a vanilla instance (optionally accepting things like the serialization-context, requested-type, etc). In addition to providing complete control over construction, this is also useful if you want to provide object-pooling etc. This option works on all frameworks, but requires you to write extra code and configuration.
One of the requirements of protobuf-net is that a default constructor be provided.
Because both Farm and Pasture objects' constructors contain parameters. There is no longer a default constructor. You must provide one.
Add one to get your data back.
Farm() {}
Pastures() {}