How to design different structures with common parts using inheritance - c#

I've searched a lot about this problem without finding any appreciable result (maybe because i don't have a clear idea of what to ask), then here we are...
I have to design two structures derived from two different JSON which they have common parts:
{
"data":
{
"success": true,
"updated_ids": [0],
"not_updated_ids": [0]
}
}
{
"data":
{
"success": true,
"branch_ids":["0"]
}
}
My idea is to create something like this:
class Response
{
Data data { get; set; }
}
class Data
{
bool success { get; set; }
}
class UserResponse : Data
{
List<int> updatedIds { get; set; }
List<int> notUpdatedIds { get; set; }
}
class BranchResponse : Data
{
List<string> branchIds { get; set; }
}
Now my question is: How can i instantiate my two different classes?
If I do new Response() i don't get the UserReponse or BranchResponse part and if i do new UserResponse() i don't get the Response part.
Basically i would like to instantiate a variable for each structure, populate it with all the values and then Serialize to create the Json.
Thanks in advance!

Alright so what you need is an interface and a factory to accomplish what you are trying to create here.
public interface IData
{
bool Success { get; set; }
}
public class Response
{
public IData Data { get; set; }
}
public class UserData : IData
{
public bool Success { get; set; }
public List<int> UpdatedIds { get; set; }
public List<int> NotUpdatedIds { get; set; }
}
public class BranchData : IData
{
public bool Success { get; set; }
public List<string> BranchIds { get; set; }
}
public class HowToUseIt
{
public Response CreateResponse()
{
Response myReponse = new Response
{
Data = new UserData
{
Success = true,
UpdatedIds = new List<int>(),
NotUpdatedIds = new List<int>()
}
};
return myReponse;
}
public void WhatKindOfDataDoIHave(Response response)
{
if (typeof(UserData) == response.Data.GetType())
{
//You have user data
}
else if (typeof(BranchData) == response.Data.GetType())
{
//You have branch data
}
else
{
//You have a problem!
}
}
}

Using a part of the suggestion from Andrew i've finally found a solution whihc works for me. Posting it to anyone who maybe is going crazy with it:
class Response
{
Data data { get; set; }
}
public abstract class Data
{
bool Success { get; set; }
public abstract Response CreateDeserializationModelSchema();
}
public class UserData : Data
{
public bool Success { get; set; }
public List<int> UpdatedIds { get; set; }
public List<int> NotUpdatedIds { get; set; }
public override Response CreateDeserializationModelSchema()
{
return new Response
{
Data = new UserData()
};
}
public static UsersData GetContent(Response response)
{
if (response.Data.GetType() == typeof(UsersData))
return (UsersData)response.Data;
else
throw new FormatException("Response not in the correct format to parse into UpdateUsersStatusResponse");
}
}
class UsersDataConverter : CustomCreationConverter<Response>
{
public override Response Create(Type objectType)
{
return new UsersData().CreateDeserializationModelSchema();
}
}
public class HowToUseIt
{
public void Use()
{
Response resp = JsonConvert.DeserializeObject<Response>(jsonResponse.ToString(), new UserDataConverter());
UserData u = UserData.GetContent(resp)
}
}

Related

How to do json data list<T> show dataGridView

I'm using the Newtonsoft library for parsing JSON:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
I have my json string and "MyClass" class.
JSON string:
{
"Result":
{
"MyClassList": [
{"Id":1,"Amount":"5,00"},
{"Id":2,"Amount":"10,00"},
{"Id":3,"Amount":"20,00"},
{"Id":4,"Amount":"25,00"}
]
"ReturnValues":
{
"ErrorCode":1,
"ErrorDescription":"Successful"
}
}
}
My Class:
public class MyClass
{
[JsonProperty("Id")]
Int64 Id { get; set; }
[JsonProperty("Amount ")]
string Amount { get; set; }
}
I am getting json data using these classes "GetMyClassList", "RootObject" and "ReturnValues".
List<MyClass> GetMyClassList()
{
JObject jo = new JObject();
List<MyClass> myClassList = new List<MyClass>();
jo.Add("Name", "Name");
jo.Add("Surname", "Surname");
url = "MyUrl";
string responseText = ExecuteHttpRequest(url , "POST",
"application/json", Encoding.UTF8.GetBytes(jo.ToString()), 3000);
myClassList = JsonConvert.DeserializeObject<RootObject>(responseText)
.GetMyClassListResult.MyClassList;
return myClassList;
}
public class ReturnValues
{
public int ErrorCode { get; set; }
public string ErrorDescription { get; set; }
}
public class GetMyClassListResult
{
[JsonProperty("MyClassList")]
public List<MyClass> MyClassList { get; set; }
public ReturnValues ReturnValues { get; set; }
}
public class RootObject
{
public GetMyClassListResult GetMyClassListResult { get; set; }
}
I cannot get this data array (Id and amount).
and I want to take this data and show it in a dataGridView.
The best way to t-shoot this is set breakpoint at the line, where u getting the results from method -> is it filled? This Line:
return myClassList;
I have run Your code with single adjustment -> I have just used the direct JSON (not from web) - code below. This run without issues and I can see all the results parsed out of the JSON.
You have to find if the issue is parsin the JSON, or setting the data to the DataGridTable (which code You have not included at all).
class Program
{
static void Main(string[] args)
{
var result = new Program().GetMyClassList();
foreach (var item in result)
Console.WriteLine($"ID: {item.Id}\tAmount:{item.Amount}");
Console.ReadKey();
}
public List<MyClass> GetMyClassList()
{
List<MyClass> myClassList = new List<MyClass>();
string responseText = "{\"GetMyClassListResult\":{\"MyClassList\":[{\"Id\":1,\"Amount\":\"5,00\"},{\"Id\":2,\"Amount\":\"10,00\"},{\"Id\":3,\"Amount\":\"20,00\"},{\"Id\":4,\"Amount\":\"25,00\"}],\"ReturnValues\":{\"ErrorCode\":1,\"ErrorDescription\":\"Successful\"}}}";
myClassList = JsonConvert.DeserializeObject<RootObject>(responseText)
.GetMyClassListResult.MyClassList;
return myClassList;
}
}
public class MyClass
{
[JsonProperty("Id")]
public Int64 Id { get; set; }
[JsonProperty("Amount")]
public string Amount { get; set; }
}
public class ReturnValues
{
public int ErrorCode { get; set; }
public string ErrorDescription { get; set; }
}
public class GetMyClassListResult
{
[JsonProperty("MyClassList")]
public List<MyClass> MyClassList { get; set; }
public ReturnValues ReturnValues { get; set; }
}
public class RootObject
{
public GetMyClassListResult GetMyClassListResult { get; set; }
}

How to combine the common code to create a generic method?

I have below classes with which I generate a request object and serialize the response to get a JSON string. The definition of classes are as follows
PortfolioResponse & StocksInfo classes are for mentioning purpose as they contain a lot many fields which I would not be able to write here.
[DataContract]
public class BaseInfoRequest
{
[DataMember]
public string Token { get; set; }
}
[DataContract]
public class StocksInfoRequest : BaseInfoRequest
{
[DataMember]
public string SomeKey { get; set; }
}
[DataContract]
public class PortfolioInfoRequest : BaseInfoRequest
{
[DataMember]
public string PortfolioId { get; set; }
[DataMember]
public string SomeKey { get; set; }
}
[DataContract]
public class StocksInfoResponse
{
[DataMember(Name = "success")]
public bool Success { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
[DataMember(Name = "stocks")]
public StocksInfo StocksInfo { get; set; }
[DataMember(Name = "pfolio")]
public PortfolioResponse PortfolioInfo { get; set; }
}
public class PortfolioResponse
{
}
public class StocksInfo
{
}
Now, to get the data from different other classes and services in project I use below two methods in let's say class Sample
private string GetsStocksInformation(StocksInfoRequest request)
{
var response = new StocksInfoResponse();
if (ValidateRequestToken(request) || string.IsNullOrWhiteSpace(request.SomeKey))
{
response.Message =
GetsResponse().ErrorMessage;
return JsonConvert.SerializeObject(response);
}
response.StocksInfo = GetsStocksInfo(request);
response.Success = true;
return JsonConvert.SerializeObject(response);
}
private string GetsPortfolioInformation(PortfolioInfoRequest request)
{
var response = new StocksInfoResponse();
if (!ValidateRequestToken(request) || string.IsNullOrWhiteSpace(request.SomeKey) ||
string.IsNullOrWhiteSpace(request.PortfolioId))
{
response.Message =
GetsResponse().ErrorMessage;
return JsonConvert.SerializeObject(response);
}
response.PortfolioInfo = GetsPortfolioInfo(request.SomeKey, request.PortfolioId);
response.Success = true;
return JsonConvert.SerializeObject(response);
}
Now, if you look closely enough both the methods are almost same except condition
if (ValidateRequestToken(request) || string.IsNullOrWhiteSpace(request.SomeKey)) &&
response.StocksInfo = GetsStocksInfo(request);
Apart from above two, both the methods do more or less same things. The definition of ValidateRequestToken is below
private bool ValidateRequestToken(BaseInfoRequest request)
{
return true;
}
How do I combine both methods to create a generic method ?

Retrieving generic data without knowing the List<Type> to be returned, is that possible?

I dont know if the question is correct but what I need to do is to received the correct entity from the messagetoprocess repository method with the corresponding data, how can I do that in this scenario? (code below)
Im using AutoMapper.
I know that I can create a MessageEntity and eliminate the Interface and put all properties together in it but that is exactly what Im trying not to do.
Here is what I've got:
Interface:
public interface IMessage
{
string MessageFrom { get; set; }
string MessageTo { get; set; }
{
Implementer Entities
public class EmailMessageEntity : IMessage
{
public bool IsMessageBodyHtml { get; set; }
}
public class SmsMessageEntity : IMessage
{
public bool IsMmsMessage { get; set; }
}
Models:
public class EmailMessage
{
public string MessageFrom { get; set; }
public string MessageTo { get; set; }
public bool IsMessageBodyHtml { get; set; }
}
public class SMSMessage
{
public string MessageFrom { get; set; }
public string MessageTo { get; set; }
public bool IsMmsMessage { get; set; }
}
Repositry:
public static List<*****Entity problem*****> RetrieveMessageToProcess()
{
var commandSettings = new CommandSettings
{
CommandText = #"[Schema].[RetrieveMessageToProcess]",
CommandType = CommandType.StoredProcedure
};
return new MsSqlProviderBase(DbConnectionString, commandSettings).ExecuteQuery<*****Entity problem*****>();
}
Using it:
//code excerpt
var messagesToProcess = Db.RetrieveMessageToProcess(); //repository
if (messagesToProcess == null) return;
// Process Message(s)
foreach (var messageEntity in messagesToProcess)
{
if (Email) // this is just the verification example not the actual statement and not a variable
{
Mapper.CreateMap<EmailMessageEntity, EmailMessage>();
var emailMessage = Mapper.Map<EmailMessage>(messageEntity);
}
else if (SMS)
{
Mapper.CreateMap<SMSMessageEntity, SMSMessage>();
var smsMessage = Mapper.Map<SmsMessage>(messageEntity);
}
}
Could you consider having a MessageType member on your IMessage interface instead of the two IsXXX properties ?
You could return an enum, or whatever other value you deem appropriate, and use that in your if(EMAIL) statement.

Trying to work out these interfaces

I'm trying to create some interfaces. The IReportSection object will have one string and a collection of items, which could be different depending on what we're working with. Do I need to make it generic?
The IReport will have one string and a collection of IReportSection.
Here's how I'm trying to define it now.
public interface IReport
{
string ReportName { get; set; }
ICollection<IReportSection> ReportSections { get; }
}
public interface IReportSection
{
string ReportSectionName { get; set; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase : IReportSection
{
public string ReportSectionName { get; set; }
public ICollection ReportItems { get; set; }
}
And my models:
pulic class ProjectSubmissionViewModel
{
public int ProjectSubmissionId { get; set; }
public string SubmissionTitle { get; set; }
}
pulic class AffiliateViewModel
{
public int AffiliateId { get; set; }
public string AffiliateName { get; set; }
}
This is how I'm trying to use it in code:
public class ChapterAffiliates : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Affiliates"; } }
public ICollection<AffiliateViewModel> ReportItems { get; set; }
}
public class ChapterTitles : ReportSectionBase
{
public string ReportSectionName { get { return "Chapter Titles"; } }
public ICollection<ProjectSubmissionViewModel> ReportItems { get; set; }
}
public class SubmissionListViewModel : IReport
{
public ICollection<ProjectSubmissionViewModel> Submissions { get; set; }
public ICollection<AffiliateViewModel> Affiliates{ get; set; }
public string ReportName { get; set; }
public ICollection<IReportSection> ReportSections
{
get
{
var affiliateSection = new ChapterAffiliates
{
ReportItems = Affiliates
};
var titleSection = new ChapterTitles
{
ReportItems = Submissions.Where(s => s.SubmissionTitle.Contains("SomePhrase")).ToList()
};
var sections = new List<IReportSection> { {subSection}, {titleSection} };
return sections;
}
}
}
I'm not sure how to best define this. I'm pretty sure I've done it before, but it's not coming to me.
Are the type parameters for TRType all the same within a certain report? E.g. will you have report sections with different report types in them?
If all types within a report are the same, the solution is relatively simple:
public interface IReport<T> { ... }
If this is not the case - you'll have to do something different, e.g:
public interface IReportSection
{
string ReportSectionName { get; }
ICollection ReportItems { get; }
}
public abstract class ReportSectionBase<TRType> : IReportSection {
...
}
This allows you to put different underlying types in the ReportSections collection related to the report. You'll have to do some more work to get the exact information that you need out of each report section.

using JSON response from REST api with nonstandard names

{"balances-and-info":{"on_hold":[],"available": {"USD":0.93033384},"usd_volume":"243.18","fee_bracket": {"maker":"0.00","taker":"0.60"},"global_usd_volume":"0.09942900"}}
I have this JSON response, and I'm trying to store it in an object, however as you can see "balances-and-info" cannot be used as a variable name. The method I have been using is:
RestClient client = new RestClient("http://currency-api.appspot.com/api/");
RestRequest request = new RestRequest(url);
var response = client.Execute<Currency>(request);
Currency obj = response.Data;
Where obviously the class is a lot easier
public class Currency
{
public string rate { get; set; }
}
So how can I handle this?
String.replace() balances-and-info with balances_and_info
in your code
YourObject deserialized = parseResponse(obj.replace("balances-and-info", "balances_and_info"));
YourObject parseResponse(string response) {
try
{
// https://www.nuget.org/packages/Newtonsoft.Json/
// Json.NET
YourObject ret = JsonConvert.DeserializeObject<YourObject>(response);
return ret;
}
catch (JsonSerializationException)
{
// do something
}
return null;
}
YourObject
Use http://json2csharp.com/ and generate your object (copy response string, replace balances-and-info with balances_and_info and generate)
public class Available
{
public double USD { get; set; }
}
public class FeeBracket
{
public string maker { get; set; }
public string taker { get; set; }
}
public class BalancesAndInfo
{
public List<object> on_hold { get; set; }
public Available available { get; set; }
public string usd_volume { get; set; }
public FeeBracket fee_bracket { get; set; }
public string global_usd_volume { get; set; }
}
public class YourObject
{
public BalancesAndInfo balances_and_info { get; set; }
}

Categories

Resources