Adding new property to .Net object - c#

I have a WCF web service that is consumed in an MVC4 application that returns an object. I want to add another property to the object after it is loaded. Essentially I want a clone of the object plus my new property.
How would I do that?
Would it be best to deserialize to JSON, then add the new property and then serialize it into my new object with the extra property or is there another way to do it?

If you want to keep things simple, you can simply create your new Type including all properties of given object and your desired new property, then fill your new class and do what do you want with it.
Also consider reading Note part.
For complicated cases and large applications, you can consider solutions like what abatishchev mentioned in his answer.
class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
class FooViewModel
{
public FooViewModel()
{
}
public FooViewModel(Foo foo)
{
this.Id= foo.Id;
this.Name= foo.Name;
}
public int Id { get; set; }
public string Name { get; set; }
public string NewProperty{ get; set; }
}
And use it this way:
var foo = Service.GetFoo();
var fooViewModel= new FooViewModel(foo);
fooViewModel.NewProperty = "new value";
Note:
You can use a Foo instance in FooViewModel and all getters and setters act on that instance to keep thing synchronized.
Sometimes you can enhance the solution using inheritance from Foo, this way you don't need too create each properties again.
For complicated cases and large applications, you can consider solutions like what abatishchev mentioned in his answer.

I think what you're looking for is AutoMapper. You can map one object into another. Say, you have a DTO entity with X properties. Then you have a business logic entity with the same X properties + Y additional. AutoMapper will handle it easily.
class OrderDto
{
public int OrderId { get; set; }
}
class OrderViewModel
{
public int OrderId { get; set; }
public int DisplayOrder { get; set; }
}
Mapping:
var dto = new OrderDto { OrderId = 2 };
var vm = mapper.Map<OrderViewModel>(dto);
vm.DisplayOrder = 3;

Would it be best to deserialize to JSON, then add the new property and
then serialize it into my new object with the extra property or is
there another way to do it?
It's definitely would be easier and cost less efforts to use JSON.
But if you want more control over the generation process see that answer how to generate classes on the fly.

Related

Storing query result into a variable

I'm a very beginner of C# and have some troubles with correct understading of generic types. In this example I would like to somehow store a query result into a variable.
The code I showed below is incorrect, because generic type T should specified.
public class Data
{
public IQueryable<T> Results { get; set; }
public Data()
{
var db = new Database();
}
public void Store()
{
Results = db.Products.Select(x => new { x.ProductName, x.Cost });
}
}
Is it possible to do it without declaring a special class for only one use, like this one?
public class ProductView
{
public string ProductName { get; set; }
public int Country { get; set; }
}
...
public IQueryable<ProductView > Results { get; set; }
Also, why dynamic type doesn't suit in this example?
public dynamic Results { get; set; }
There are 3 ways to solve this problem:
1) Create class like ProductView that you mentioned - classical C#6 or older way
2) Use dynamic instead of T like: public IQueryable<dynamic> Results { get; set; } - not recommended, because it increases risk of runtime errors and reduces readability
3) Use tuples (C#7 feature):
public IQueryable<(string, int)> Results { get; set; } // I suppose ProductName is string and Cost is int
public void Store()
{
Results = db.Products.Select(x => (x.ProductName, x.Cost));
}
The problem here is that your Data class appears to know some specific things about T. In the Store method it reads the Products and obtains two specific properties from each item. So it is not actually a generic class that can store any type. It's very specific.
To make it generic you would need to remove the Store method. And then there is not much left. You need to decide what the purpose of Data is. What problem does it exist to solve?

Cannot implicitly convert type 'System.Collections.Generic.List<MODEL#1>' to 'System.Collections.Generic.List<Model#2>

I'm using MVC5 with EF6 .I'm getting the below conversion Error
Cannot implicitly convert type
System.Collections.Generic.List<TreaceabilitySystem.GLB_M_PROFITCENTER>
to
System.Collections.Generic.List<TreaceabilitySystem.Models.Profitcenter>
private TSEntities db = new TSEntities();
// GET: Profitcenter
public ActionResult Index()
{
List<Profitcenter> profitcenter = new List<Profitcenter>();
profitcenter = db.GLB_M_PROFITCENTER.ToList(); //Error coming up here
return View(profitcenter.ToList());
}
My models are here:
This Model created through EF when i add table in .edmx
public partial class GLB_M_PROFITCENTER
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public GLB_M_PROFITCENTER()
{
this.GLB_M_USERMASTER = new HashSet<GLB_M_USERMASTER>();
}
public string PROFITCENTER_CODE { get; set; }
public string PROFITCENTER_NAME { get; set; }
public string DESCRIPTION { get; set; }
public bool ISACTIVE { get; set; }
public int CREATEDBY { get; set; }
public System.DateTime CREATED_DATE { get; set; }
public Nullable<int> UPDATEDBY { get; set; }
public Nullable<System.DateTime> UPDATED_DATETIME { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<GLB_M_USERMASTER> GLB_M_USERMASTER { get; set; }
}
And I have created the below model for change the display name and validation purposes
[MetadataType(typeof(Profitcenter))]
public partial class GLB_M_PROFITCENTER { }
public class Profitcenter
{
[Required(ErrorMessage = "*")]
[DisplayName("Profitcenter Code")]
public string PROFITCENTER_CODE { get; set; }
[Required(ErrorMessage = "*")]
[DisplayName("Profitcenter Name")]
public string PROFITCENTER_NAME { get; set; }
[DisplayName("Description")]
public string DESCRIPTION { get; set; }
[DisplayName("Is Active")]
public bool ISACTIVE { get; set; }
[DisplayName("Created By")]
public int CREATEDBY { get; set; }
[DisplayName("Created Timestamp")]
public System.DateTime CREATED_DATE { get; set; }
[DisplayName("Upated by")]
public Nullable<int> UPDATEDBY { get; set; }
[DisplayName("Updated Timestamp")]
public DateTime UPDATED_DATETIME
{
get; set;
}
}
both models are exactly same , Am I missing anything ?
How do I fix this?
both models are exactly same
That doesn't mean you can just assign the one to the other. For this code to work:
Foo foo = new Foo();
Bar bar = foo;
Bar must be a base type of Foo. This isn't the case here, both your Bar and Foo just happen to have the same property names.
You need to map from one to the other:
public Profitcenter Map(GLB_M_PROFITCENTER input)
{
return new Profitcenter
{
PROFITCENTER_CODE = input.PROFITCENTER_CODE,
...
};
}
You can do the mapping of the entire list with Select():
List<Profitcenter> profitcenter = new List<Profitcenter>();
profitcenter = db.GLB_M_PROFITCENTER.Select(Map).ToList();
An automated way of doing this could be using AutoMapper, which works especially well if all properties on both sides are named identically.
That only answers your question partially though. You have two types: GLB_M_PROFITCENTER, an Entity Framework-generated class that represents a database table, and Profitcenter, where you have added attributes that can be used for input validation using the MetadataType attribute.
I'm not a fan of the latter, because you're then using Entity Framework models as viewmodels for your UI layer. You shouldn't, and you can just remove the MetadataType attribute from the partial class definition.
So you can either use the MetadataType, but then never really instantiate that type (after all, it is a metadata type):
List<GLB_M_PROFITCENTER> profitcenter = db.GLB_M_PROFITCENTER.ToList();
return View(profitcenter);
And make your view #model IEnumerable<GLB_M_PROFITCENTER>. Then MVC will read the MetadataType attribute for GLB_M_PROFITCENTER, and apply the metadata (DisplayName, ...) as applied to Profitcenter (but you shouldn't).
Or you can simply apply mapping, thereby decoupling your view model from your entity model (and thus your database), with all additional benefits.
Some programming languages, unlike C# and other C-like languages, allow for what is called "duck typing", which would let you assign from different types if they both "quack the same way".
In C#, however, you can only assign an instance of a class to a variable of the same type, or of a base type (a class which your class extends, or an interface which it implements). Even if you had two classes which looked exactly the same, you wouldn't be able to assign from one of them to the other. .NET prior to version 4.0 didn't even support proper generic covariance and contravariance, meaning you couldn't even assign a IEnumerable<Tderived> to IEnumerable<Tbase> even if Tderived is derived from Tbase.
The solution could be to:
use a tool which will map from one class to the other (i.e. copy between equally named properties), like AutoMapper, or
redesign your app to have a separate assembly which contains common entities to be shared between other assemblies type (not a bad idea either), or
extract an interface so that you can assign to this base interface.
It is not uncommon to use mapping to resolve this issue, since you often want to have plain data transfer objects for moving data between tiers, so using an automated tool for this is ok, but if you can keep all entities in a separate assembly which is referenced by both DAL and business layer, but doesn't know anything about them, then it's an even better approach because it avoids any runtime mapping issues.
GLB_M_PROFITCENTER and Profitcenter are not same types, you just share metadata for sharing of attributes from viewmodel to entity model. You should use linq projection for conversion of one type to other
db.GLB_M_PROFITCENTER.select(e => new Profitcenter() {
/* props mapping*/
}).ToList()
you can also use mapping engine for example AutoMapper
If the member names are the same - use auto mapper - it will automatically convert each type.
Mapper.CreateMap<SourceType, DestinationType>()
Then you can call
Mapper.Map<DestinationType>(instanceofSourceType);

Mapping object with properties names and values

I have class
public class Foo
{
public string Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
I want to convert the object to a generic object
{
"properties": {
"id" : "1234",
"name": "John Doe",
"email" : "john.doe#mail.com"
}
}
I want to convert the class instance to the structure where the properties would be dynamic depending on the class. Is this possible with Automapper?
Seems you want to serialize/deserialize to/from JSON. In this case you can reference to Newtonsoft.Json and use the JsonConvert.SerializeObject/JsonConvert.DeserializeObject generic method which does not depend on any specific class:
Deserializing (From String to Class Instance):
var foo = JsonConvert.DeserializeObject<Foo>(jsonString);
Serializing (From Class Instance to String):
var stringValue = JsonConvert.SerializeObject(foo)
One More Point (Mapping)
Also you may want to decorate your class with some attributes to specify the mapping:
[DataContract]
public class Foo
{
[DataMember(Name = "id")]
public string Id {get;set;}
[DataMember(Name = "name")]
public string Name {get;set;}
[DataMember(Name = "email")]
public string Email {get;set;}
}
Partially AutoMapper cannot map to dictionary or ExpandoObject, so no.
The following solution was posted before I was aware that by mapping to an ExpandoObject Automapper will simply leave you with an empty object.
The simplest solution would be this I think (assuming you want an ExpandoObject as a result):
public ExpandoObject Map<TInput>(TInput inputObject)
{
dynamic result = new ExpandoObject();
result.properties = Mapper.DynamicMap<TInput, ExpandoObject>(inputObject);
return (ExpandoObject)result;
}
As far as I know you can't delegate all members as child properties to another field using automapper, but it's simple to do this yourself. AutoMapper is completely useless here.
edit: seems that automapper struggles with ExpandoObject... Actually it seems like AutoMapper cannot do this at all, so you're left with reflection.
You would then write a reflection object that can create or populate a dictionary with the objects properties.

Deserialize object using JSON.NET, but put some properties into a member of the class

I am writing a set of data structures to ingest third-party JSON into (no writing out) using JSON.NET.
I have a case for reading some of the top-level JSON elements into a member object of the object being deserialized into.
My JSON:
{
"Id":1
"Checksum":42
"Name":"adam",
"Hair":true
}
My ideal object structure:
public class EntityHeader
{
int Id { get; set; }
int Checksum { get; set; }
}
public class Entity
{
[HeroicJsonAttribute( "Id", "Checksum" )]
public EntityHeader Header { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
Is there a simple way to achieve this? I will have a number of types which will need this, and I'd hate to have to write a JsonConverter for each.
This question has been asked before, here, but the accepted answer doesn't address the question.
Thanks!
An alternative approach would be to use an EntityHeader field in the Entity class as a backing store for private properties which can be deserialized into:
public class EntityHeader
{
int Id { get; set; }
int Checksum { get; set; }
}
public class Entity
{
private EntityHeader m_Header = new EntityHeader();
public EntityHeader Header { get { return m_Header; } }
[JsonProperty]
private int Id { set { m_Header.Id = value; } }
[JsonProperty]
private int Checksum { set { m_Header.Checksum = value; } }
public string Name { get; set; }
public bool Hair { get; set; }
}
Thus, all the properties in the JSON can be read straight into the Entity object, but consumers of Entity objects have access to a "nicely encapsulated" EntityHeader property.
I haven't tested this, and it may even be kludgey, but it would technically work for me (OP). I am still interested in other answers!
Base on your example you could either; use the adapter pattern:
public class EntityJson
{
int Id { get; set; }
int Checksum { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
// quick/poor example
public class EntityAdapter : IEntity
{
public EntityAdapter(EntityJson model)
{
Header = new Header(); // and populate this objects fields
Name = model.Name; // populate other properties
}
public EntityHeader Header { get; set; }
public string Name { get; set; }
public bool Hair { get; set; }
}
Or abuse the fact that json.net ignores properties not available:
var entity = JsonConvert.Deserialze<Entity>();
var header = JsonConvert.Deserialize<EntityHeader>();
entity.Header = header;
I'm going to go ahead and post this answer which is a little bit too long for a comment, so please take this more as an extended comment than an actual attempt to answer your specific question. And of course, you know your requirements best so this is just my considered opinion :)
With that in mind, my advice is:
Don't do this.
I would instead create a simple DTO class that has a 1-1 relationship to the JSON being received; and I'd put all my validation attributes on the properties of that class.
Once I had deserialised the JSON into this simple DTO, I would then use a mapping layer of some kind (roll your own or use Automapper, etc) to map this DTO into a more meaningful structure such as your Entity class.
My reasoning behind this is because unless your Entity class is itself only a simple DTO (in which case it should be as simple as possible and ideally not be a composite) you are mixing OOP and concerns with data mapping concerns; whilst this in and of itself is not such a bad thing, it only serves to increase the complexity of your code.
Consider for example if your incoming JSON ends up with 30 or 40 properties, and you manage to figure out a way (maybe adapting some of the nice techniques from the other answers) to map it to the Entity class. But what about when something goes wrong - it's going to be much easier to reason about, and therefore debug, a process which you have much more control over; it's also going to be much easier to make special adaptations for odd edge cases where the serialiser behaviour just can't help you out
Granted it's a bit of work to write and maintain these DTOs but not that much - Webtools already does this for you
Reference: At the boundaries, Applications are not Object-Oriented

What is the best way to merge two objects during runtime using C#?

I have two objects and I want to merge them:
public class Foo
{
public string Name { get; set; }
}
public class Bar
{
public Guid Id { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
}
To create:
public class FooBar
{
public string Name { get; set; }
public Guid Id { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
}
I will only know the structure of Foo at runtime. Bar can be any type at runtime. I would like to have a method that will be given a type and it combine that type with Foo. For instance, the scenario above, the method was given a Bar type at runtime and I combined it with Foo.
What would be the best way to do this? Can it be done using LINQ Expressions or do I have to generate it Dynamically or is there another way? I am still learning the new LINQ namespace in C# 3.0, so excuse the ignorance if it can't be done using LINQ Expressions. This is also the first time I have ever had to do something dynamic like this with C#, so I am not quite sure of all the options I have available to me.
Thanks for any options given.
EDIT
This is strictly for adding meta information to the type given to me for serialization. This scenario keeps the user's objects ignorant of the meta information that needs to be added, before it is serialized. I have come up with two options before asking this question and I just wanted to see if there was anymore, before deciding on which one to use.
The two options I have come up with are:
Manipulating the serialized string of the type given to me after serializing it, by adding the meta information.
Wrapping the type given to me, which is similar to what #Zxpro mentioned, but mine differed slightly, which is fine. It will just make the user of my API have to follow the convention, which isn't a bad thing, since everybody is about convention over configuration:
public class Foo<T>
{
public string Name { get; set; }
public T Content { get; set; }
}
EDIT
Thanks everybody for their answers. I decided on wrapping the object like above and I gave the answer to #Zxpro, since a majority liked that approach also.
If anybody else comes across this question, feel free to post, if you think there might be a better way.
If you don't mind them being grouped rather than merged:
public class FooEx<T>
{
public Foo Foo { get; set; }
public T Ex { get; set; }
}
UNTESTED, but using the Reflection.Emit API, something like this should work:
public Type MergeTypes(params Type[] types)
{
AppDomain domain = AppDomain.CurrentDomain;
AssemblyBuilder builder =
domain.DefineDynamicAssembly(new AssemblyName("CombinedAssembly"),
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = builder.DefineDynamicModule("DynamicModule");
TypeBuilder typeBuilder = moduleBuilder.DefineType("CombinedType");
foreach (var type in types)
{
var props = GetProperties(type);
foreach (var prop in props)
{
typeBuilder.DefineField(prop.Key, prop.Value, FieldAttributes.Public);
}
}
return typeBuilder.CreateType();
}
private Dictionary<string, Type> GetProperties(Type type)
{
return type.GetProperties().ToDictionary(p => p.Name, p => p.PropertyType);
}
USAGE:
Type combinedType = MergeTypes(typeof(Foo), typeof(Bar));
Unfortunately, this is not something you can do easily. The best you can do is to create an anonymous type as part of a LINQ query, but that will have local scope only, and so will only be good for you in the method wherein you make it.
When .NET 4 comes out, there's a new Dynamic Runtime Library that might help you out.
Aside from the question "Why", the only way I can think to take two objects, one known and one unknown, and combine them into a new type would be to use Reflection.Emit to generate a new type at runtime.
There are examples on MSDN. You would have to determine weather you wanted to merge fields that had the same name or have the known type supersede the unknown type.
As far as I can tell, there is no way to do this in LINQ.
Since all you're interested in is Properties it should be pretty easy to use this article as an example. Leave out the il for creating methods and you're good to go.
As others have pointed out, there is no way to "merge" them (if you're thinking of a select * with multiple tables in SQL, for example). Your closest analog would be taking the route that Zxpro has provided and "group" them in a generic class.
What, exactly, would you want to accomplish with "merging" them, though? Declaring the properties explicitly would have the biggest convenience effect on writing code and compile-time safety, but if you can't specify a type then there's no opportunity for that. If you're just looking for a generic "property bag" container, then an existing data structure, such as a Dictionary<T,T> or Hashtable should be able to handle that.
If you can add a method to the metadata class you could do something like the following
public class Foo
{
public string Name { get; set; }
public void SerializeWithMetadata(Bar bar)
{
var obj = new {
Name = this.Name,
Guid = bar.Guid,
Property1 = Bar.Property1
}
//Serialization code goes here
}
}
public class Bar
{
public Guid Id { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
}
I'm not sure I would recommend this exact approach I mainly left it here to display anonymous types as a possible option that might be worth exploring
Another Option:
Modify the first class like so
public class Foo
{
public string Name { get; set; }
[System.Xml.Serialization.XmlAnyElementAttribute()]
public XmlElement Any {get;set;}
}
Take the second class and serialize it into an XmlElement like so:
XmlElement SerializeToElement(Type t, object obj)
{
XmlSerializer ser = new XmlSerializer(t);
StringWriter sw = new StringWriter();
using (XmlWriter writer = XmlWriter.Create(sw, settings))
ser.Serialize(writer, obj);
string val = sw.ToString();
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
return (XmlElement)doc.DocumentElement;
}
Set property Any to the XmlElement, and serialize it
You'll see the XML for the other class embedded in the document, complete with all the namespaces
You can even get away with this if the class was generated using Xsd.exe if you use the following as an element:
<xs:any namespace="##any" processContents="lax" />
I believe you can also get away with an array of XmlElements for more than one sub-class.
Deserializaing should be a matter of inspecting the XmlElements and then looking for a matching class, or perhaps using the namespace to find the class.
This is a lot tidier than messing about with string manipulation.

Categories

Resources