I have a master object where it contains list of properties and these properties have their attributes. I like to copy these object's properties to a new one but omitting some of its properties.
How do you do this? could this be done using ExpandoObj? Removing the properties should be hundle during runtime because in the UI part there are checkbox on which properties to include. If the property is not checked then it should not be including in the creation of the object.
Update: properties have their attributes, [Workbook(Order = 1)], I want this to be copied also as it contains information determining how its value can be translated.
As others have stated, it might be better if you can change your approach. But of course this is not always possible, sometimes the other object class is in a library that you can't change or don't want to change for example.
A simple (but maybe not very efficient so take care) approach is to serialise and deserialise with JSON.
(I know this is technically abuse, and not necessarily efficient in terms of performance, but it is simple).
//Your master class
public class Master
{
public Boolean Enabled { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string Address3 { get; set; }
public string City { get; set; }
public string Postcode { get; set; }
public string Country { get; set; }
public Master ()
{
}
}
//Your simplified class
public class Simple
{
public Boolean Enabled { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public Simple()
{
}
}
//Code to transform
Master mstr = new Master() { Address1 = "Castle rose", Address2 = "The street", Address3 = "Done the lane", City = "Ebson on the Hill",
Country = "UK", Postcode = "NR1 1YT", Enabled = true, Name = "John Jones", Status = "Activated" };
string json = JsonConvert.SerializeObject(mstr);
Simple simp = JsonConvert.DeserializeObject<Simple>(json);
This is handy, especially if you are doing a PoC or testing etc. and you want something quick but simple. But a better permanent solution is to have a new Constructor of your Simple Class which would accept a Master as input and only copy the attributes it requires.
Or you could use reflection, which might offer more flexibility but also has a performance overhead, so you have to be careful where and how you use it.
Related
I have a couple of classes that look something like this:
public class Address
{
public string Country { get; set; }
public string Zip { get; set; }
public string State { get; set; }
public string City { get; set; }
public string Street { get; set; }
}
public class Order
{
public Address FromAddress { get; set; }
public Address ToAddress { get; set; }
public decimal Amount { get; set; }
...
}
I'm using Newtonsoft.JSON to serialize/deserialize those objects to JSON, but I have some rather specific requirements for how serializing should work.
For one, properties should all be snake case. This was easy enough using a SnakeCaseNamingStrategy with a contract resolver. However, I also want to bring the properties from the addresses up to the top level and have them renamed to append from or to to them. Basically:
{
"from_country": "US",
...
"to_country": "US",
...
"amount": "10.00"
}
I want to do all this without littering my classes with attributes and ideally without creating wrapper classes. I've been looking into the creation of custom ContractResolvers as well as custom JsonWriters, but I'm unable to figure out which or which combination of the two I need to achieve my desired format.
How can I remove a property from an list/array of a object?
My model contains:
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public string Size { get; set; }
And i'm converting this to JSON with
string json = JsonConvert.SerializeObject(client);
And all works fine... I got all propertys of the object in JSON.
But I need to create two levels of acess, and show all info in one level, and the other level, fewer propertys...
My question is: Can I remove a property of an object?
Someting like this:
List<Customer> customers = new List<Customer>();
//(and this have 100 clients inner)
customer.removeProperty(Age, Size); // Can I have someting like this?
Try using the json ignore tag above the property. E.g.:
[JsonIgnore]
public string Age { get; set; }
If you want to be able to serialise both with and without certain properties, without altering the structure of your actual classes, you could try using the example here.
Create a new model with your fewer properties. Make two lists, one with all the properties and the other with the properties you want removed.
For example
public YourModelNow
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Age { get; set; }
public string Size { get; set; }
}
public YourModelNowFiltered
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This is assuming you need two file.json with the different properties. If you just need to ignore the properties use Ross Gurburts approach.
i would suggest using AutoMapper
you will need to create a DTO [Data Transfer Object] class
which would have the properties that you would like to expose
the usage is pretty simple:
in the config:
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<YourModel, YourModelDTO>();
});
in the actual usage:
IMapper iMapper = config.CreateMapper();
var source = new YourModel();
var destination = iMapper.Map<YourModel, YourModelDTO>(source);
for more information and example of what AutoMapper could do read here
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!
I'm using the official MongoDB C# Driver to communicate with my MongoDB Servers.
This is my complete entity scheme:
public class Person
{
public ObjectId _id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
public DateTime DateOfBirth { get; set; }
public List<Address> Addresses { get; set; }
}
public class Address
{
public String Street { get; set; }
public String City { get; set; }
}
Now, in several cases i just want to get the following return:
public class Person_LocationOview
{
public String LastName { get; set; }
public List<Address_CityOnly> Addresses { get; set; }
}
public class Address_CityOnly
{
public String City { get; set; }
}
The default behavior to load all fields and do the mapping by myself
MongoCursor<Person>
is senseless, because I just want to load the specific fields.
With the help of reflection I generate the fields to load and send:
var fields = new { "LastName", "Addresses.City" };
MongoCollection< BsonDocument >.FindAllAs< Person_LocationOview >( )
.SetFields( fields ).ToList( );
I thought the serializer of MongoDB would be intelligent; but the call returns following error:
System.IO.FileFormatException: Required element 'City' for property 'City' of class Models.Address_CityOnly is missing
Any ideas to this requirement?
I've updated the complete MongoDB infrastructure. Now the code works with all viewModels such as Person_LocationOview. With the full scheme classes, the code still crashes and I do not know why.
Now, all my view classes are implementing an own interface (IPartialEntityView).
In my reflection method to get the field names I'll check this inheritance and only then I will load "Addresses.FieldName(s)". If the property type is no default .NET type or does not inherit IPartialEntityView I will use the complete field "Adresses".
That works great.
Thanks for all.
We currently have several underlying database tables such as Events, Shop Products, Content Pages etc. each with have shared properties such as having a Name, a details page on the front end of the site, a thumbnail url, an active flag etc.
I'm trying to figure out the most efficient way of creating a class of shared properties that can be used to pass around these objects generically. An example might be the search results page. The search can be done against the name of the collection of data which is actually across multiple tables originally.
I am struggling using inheritance due to all these classes originating from LINQ classes and I don't want to start editing the datacontext designer to suit my needs.
Currently each partial class on my LINQ classes contains a SharedObject method:
public partial class Event
{
public SharedObject SharedObject
{
get
{
return new SharedObject(this);
}
}
...
This is repeated for Events, Shop Products etc. The Shared Object class contains the following:
public class SharedObject
{
public string Reference { get; set; }
public string Name { get; set; }
public string ImageURL { get; set; }
public bool IsVisible { get; set; }
public bool IsAdminVisible { get; set; }
public string FrontEndDetailsURL { get; set; }
public string AdminDetailsURL { get; set; }
public object OriginalObject { get; set; }
public string ObjectDescription { get; set; }
public SharedObject(object originalObject)
{
if (originalObject.GetType() == typeof(Event))
{
Event eventx = (Event)originalObject;
Reference = eventx.Reference;
Name = eventx.Name;
ImageURL = eventx.ImageURL;
IsVisible = eventx.IsActive && !Event.IsArchived;
IsAdminVisible = !eventx.IsArchived;
FrontEndDetailsURL = eventx.DetailsURL;
AdminDetailsURL = eventx.AdminDetailsURL;
OriginalObject = originalObject;
ObjectDescription = "Event";
}
....
Does this sound like a suitable solution?
Consider using an interface. This is much more flexible.
public interface ISharedObject
{
string Reference { get; set; }
string Name { get; set; }
string ImageURL { get; set; }
bool IsVisible { get; set; }
bool IsAdminVisible { get; set; }
string FrontEndDetailsURL { get; set; }
string AdminDetailsURL { get; set; }
object OriginalObject { get; set; }
string ObjectDescription { get; set; }
}
public partial class Event : ISharedObject
{}
I think the most efficient way to pass around your shared objects is to use the "Chain of responsibility pattern" Chain of responsibility
For the inheritance LINQ you think of the use of IQueryable <T>. I hope that it can help you