Deep copy - choosing the properties to copy - c#

I would like to do a deep copy of an object. This object has some normal string, int, properties but it would also have custom objects (e.g. a list of custom objects).
Is there a way to do a deep copy where I pick and choose which properties to copy?
e.g. I want to copy
public class BankAccount
{
[Required]
[DeepCopy]
public string Number { get; }
[Required]
[DeepCopy]
public string Owner { get; set; }
[Required]
[DeepCopy]
public decimal Balance { get; }
[Required]
[DeepCopy]
public List<CustomAddress> {get; set;}
[Required]
public List<CustomLinkedAccounts> {get; set;}
}
Where perhaps I would want to copy everything except the List of CustomLinkedAccounts.

This is a solution I have used in the past for deep cloning.
It requires Newtonsoft JSON library.
It can be adapted to use System.Text.Json if you can't use third party libraries.
using Newtonsoft.Json;
public class BankAccount
{
[Required]
public string Number { get; }
[Required]
public string Owner { get; set; }
[Required]
public decimal Balance { get; }
[Required]
public List<CustomAddress> {get; set;}
[Required]
[JsonIgnore]//this is not in the json
public List<CustomLinkedAccounts> {get; set;}
public BankAccount Clone()
{
var json = JsonConvert.SerializeObject(this);
var result = JsonConvert.DeserializeObject<BankAccount>(json);
//this is a deep copy... no reference issues
return result;
}
}

Related

Only return some fields in JSON

I have an API that returns some data of a class in JSON. Is there any way to return only some specific fields of a C# class in JSON?
For example:
class Person {
public int Id{ get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Gender { get; set; }
}
Person myPerson = new Person();
var Json = (new
{
Person = myPerson
});
return Request.CreateResponse(HttpStatusCode.OK, Json);
It returns ID, Name, Family, Gender. I need to return only the Name and Family. I thought I can create an object and add my specific fields in the class in that object and return object?
Use anonymous types?
return Request.CreateResponse(HttpStatusCode.OK, new {Name = person.Name; Family = person.Family});
You should consider applying the DRY principle.
The DRY principle is not "never write code twice", but rather that "every piece of knowledge must have a single, unambiguous, authoritative representation in the system".
What this means is that you have to build a model that has a meaningful name, contains properties that it actually has, and can be changed as needed later without having to figure out where else in the application it's used. I'm certain you could also find a name that would better represent this area of the application.
Should I create a different model with just the properties I need or
use the same model and have NULL values for the field I don't use? Or just create anonymous type and make this way harder in future?
I don't recommend using the same model for your case, from my understanding of it. It's going to make your life easier down the road if you build a model that has a meaningful name as I said before.
So what should we do? I have seen many people trying to use JsonIgnore in domain model but you should not get down that path. You should avoid using JsonIgnore in domain model. I will give an example for it.
For example:
class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Gender { get; set; }
}
So you have this model and you want other models to inherit from it but like in your case you don't want to return Id and Gender, only Name and Family. So you go like this.
class Person {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Family { get; set; }
public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
[JsonIgnore]
public override int Id { get; set; }
[JsonIgnore]
public override string Gender{ get; set; }
}
If a class has many properties and you only want to serialize a small
subset of them then adding JsonIgnore to all the others will be
tedious and error prone. The way to tackle this scenario is to add the
DataContractAttribute to the class and DataMemberAttributes to the
properties to serialize. This is opt-in serialization, only the
properties you mark up with be serialized, compared to opt-out
serialization using JsonIgnoreAttribute.
But, you can do it with the help of JsonIgnore but this way does not support XML format. So, in case your application has to support XML format more (or only support XML), instead of using Json.Net, you should use [DataContract] which supports both JSON and XML.
Datacontract is a great solution. It gives me a clean REST API. At the same time when I save the data in a no-sql, the ignored properties are persisted despite the objects being stored as json.
[DataContract]
public class Person {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Family { get; set; }
public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
// included in JSON
[DataMember]
public override string Name { get; set; }
[DataMember]
public override string Family { get; set; }
// other inherited properties will be ignored
}
I will also mention another way of doing it as there are more (custom contact resolver, Web API convention ("ShouldSerialize")...)
Another way you can do it is to decorate your auto property with JsonProperty attribute in order to skip the serialization of that field if it is null.
Example:
class Person {
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int? Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Gender { get; set; }
}
Happy coding!

Making a class that will contain a subclass that can be different classes depending on the need

I'm unsure how to go about implementing this particular idea of I have a class lets call it EnhancedUserInput that will have some variables that all of the input types will have and a particular subclass depending on the need during operation so some extra variables and a list so for example sub classes of it would be MultipleChoice which would have MinSelection, MaxSelection and a list of a type called option with their own variables ect and then another possible sub class called ExplicitAgreement which would have the variables inputLabel1, inputLabel2 and a list of type BinaryInput which would have their own variables.
So far from what I understand the best way going about this would be to have some type of generic variable? I'll show some code to try and help get what it is I need across but was just wondering is there an easy way of doing this that I am unaware of?
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set}
// this is where I am unsure of how to go about it
public object inputType
{
MultipleChoice
ExplicitAgreement
}
}
public class MultipleChoice
{
public List<MultipleChoiceOption> Options { get; set; }
public int MinSelected { get; set; }
public int MaxSelected { get; set; }
}
public class ExplicitAgreement
{
public List<BinaryInputOption> Buttons { get; set; }
public string InputLabel1 { get; set; }
public string InputLabel2 { get; set; }
}
what would be the best path for this solution I can think of some possible ways but they would be a bit figity and was wondering if there are any simple ways?
Seems to me that you may have this the wrong way around. Maybe what you want is to just use class inheritance?
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set}
}
public class MultipleChoice : EnhancedCustomerInput
{
public List<MultipleChoiceOption> Options { get; set; }
public int MinSelected { get; set; }
public int MaxSelected { get; set; }
}
public class ExplicitAgreement : EnhancedCustomerInput
{
public List<BinaryInputOption> Buttons { get; set; }
public string InputLabel1 { get; set; }
public string InputLabel2 { get; set; }
}
Steve Harris's inheritance suggestion is good. Your original option to use Composition can work just fine, too:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public object InputData { get; set; }
}
The only problem is that consumers of your code need to know that InputData can be one of several different types, and you presumably need logic to switch on their type. You can add comments to the property to give people a hint, or you can use a library like LanguageExt, which provides an Either type:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public Either<MultipleChoice, ExplicitAgreement> InputData { get; set; }
}
This makes it much more obvious which types InputData can be, but would get very unwieldy if you have more than two possibilities.
You could also declare an interface that InputData must implement, which would make it easier for developers to find all the types that are intended to be used there. But an empty interface is considered to be a code smell because it indicates you're using interfaces for something they weren't really intended for.
Another option I've found to work well is to define an enum type to help identify which different types of input data you can have:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public InputType InputType { get; set; }
public object InputData { get; set; }
}
public enum InputType { MultipleChoice, ExplicitAgreement }
This gives your business logic a specific set of possible types that you can switch your logic on, and works particularly well when the class is going to be serialized and deserialized, because then you can tell the deserializer which specific type of object to deserialize InputData to.
There are lots of options, each with their advantages and disadvantages.

Is there a way to control the order of properties in JSON objects?

I'm using Entity Framework Core, and the generated class has its own properties, i.e.
DataModel.Agent.cs
public partial class Agent {
public virtual decimal Id
{
get;
set;
}
public virtual string Name
{
get;
set;
}
}
But I need other properties, so I declare them in another file:
Agent.cs
public partial class Agent
{
[NotMapped]
public dynamic Custom { get; set; }
}
The problem is that Agent.cs is compiled before DataModel.Agent.cs, so the compiler generates properties in this order: Custom, Id, Name, and the resulting JSON is weird.
I want it to be: Id, Name, Custom. In other words, I always want the DataModel class to come first.
EDIT: Just to clarify, the only objective is to make the JSON prettier by always putting the Id first, which is a very common pattern. This has absolutely no impact on how the application works.
Is there a way to force the compiler to always compile one of the files first?
Well you really shouldn't count on JSON property order BUT if using json.net
public class Account
{
public string EmailAddress { get; set; }
// appear last
[JsonProperty(Order = 1)]
public bool Deleted { get; set; }
[JsonProperty(Order = 2)]
public DateTime DeletedDate { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
// appear first
[JsonProperty(Order = -2)]
public string FullName { get; set; }
}
http://www.newtonsoft.com/json/help/html/JsonPropertyOrder.htm

C# - Storing data in classes

I'm trying to understand how to query a web service that provides information about the weather. The service outputs XML.
I am not sure how to store the retrieved information in a class. Looking on the internet there seems to be two ways of doing it.
Either this way:
class CurrentWeather
{
public string CityName { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF { get; set; }
public int WindSpeedMph { get; set; }
//Lots and lots of more weather related properties
}
Or this way:
class CurrentWeather
{
public string CityName { get; set; }
public double TemperatureC { get; set; }
public double TemperatureF { get; set; }
public double WindSpeedMph { get; set; }
public CurrentObservation(string cityName, double temperatureC, double temperatureF, double windSpeedMph)
{
CityName = cityName;
TemperatureC = temperatureC;
TemperatureF = temperatureF;
WindSpeedMph = windSpeedMph;
}
}
My question: I don't know which way to do it. Which approach is the "correct" one, and why is that the case? Why would I use one way other the other?
They are exactly the same way to store data, the only difference is you added a constructor to ensure all the parameters are filled when you instance the class.
But it has a drawback, a class without an empty constructor cannot be instantiated by a serializer.
Why I say that? Because if you are receiving an XML well formed and you code your class structure as the data in that XML, you can use an XmlSerializer to deserialize the XML into an instance of that class without parsing the XML or filling the class properties.
The second is probably heading more the right way to support deserialization, but I'd probably consider breaking the data up a bit. Keep the data encapsulated so related data stays together. Your exact structure is up to you, but I'd probably break down something like:
public class CurrentConditions {
public City CurrentCity { get; set;}
public Temperature[] TemperatureReadings {get; set;}
public Wind[] WindCondtions {get; set;}
}
public class City {
public string Name {get; set;}
}
public enum TemperatureScale { Celsius, Fahrenheit }
public enum SpeedScale { MPH, KPH }
public class Temperature {
public int Degrees {get; set;}
public TemperatureScale Scale {get; set;}
}
etc.
It keeps the data organized. Allows you to only pass around and/or update the particular details you need to if you're making changes, etc.
If you posted the XML I'd have a better feel for how you could map the elements of the XML to objects.

How to deserialize json string to a domain object?

I am trying to convert the following json into a domain object .
JSON:
[{"name":"McDonalds","deals":[{"desc":"Onion Rings free with Double Cheese burgers"}],"geometry":{"lat":13.073412,"lng":80.221393}},{"name":"JusSportz","deals":[{"desc":"20% off on Wilson Rackets"}],"geometry":{"lat":13.073231,"lng":80.221181}}]
Model:
[DataContract]
public class Deal
{
[DataMember(Name="name")]
public string Store { get; set; }
[DataMember(Name="deals")]
public Offer[] Offers {get; set;}
[DataMember(Name="geometry")]
public GeoCoordinate Location { get; set; }
}
[DataContract]
public class Offer
{
[DataMember]
public string deal;
}
I tried the DataContractJsonSerializer that is in the System.Runtime.Serialization.Json namespace and there is apparently no way to convert a string into an object. Are there any other libraries which allow me to get this done? Or is there a way to get this done using this library (by converting the Json string to some intermediate format.)?
Here's how I deserialize JSON back to my domain objects.
using (var reader = new MemoryStream(Encoding.Unicode.GetBytes("YourStringValue")))
{
var ser = new DataContractJsonSerializer(typeof(Deal));
return (Deal)ser.ReadObject(reader);
}
Is this what you were looking for?
Try to change a bit Model:
[DataContract]
public class Deal
{
[DataMember(Name="name")]
public string Store { get; set; }
[DataMember(Name="deals")]
public Offer[] Offers {get; set;}
[DataMember(Name="geometry")]
public GeoCoordinate Location { get; set; }
}
[DataContract]
public class Offer
{
[DataMember(Name="desc")]
public string deal { get; set; }
}

Categories

Resources