I create the person object like this.
Person person=new Person(\"Sam\",\"Lewis\")
It has properties like this.
person.Dob
If you have a class with an object property, or if your property actually casts to an object, you can reshape the object by reassigning its properties, as in:
MyClass varClass = new MyClass();
varClass.propObjectProperty = new { Id = 1, Description = "test" };
//if you need to treat the class as an object
var varObjectProperty = ((dynamic)varClass).propObjectProperty;
((dynamic)varClass).propObjectProperty = new { Id = varObjectProperty.Id, Description = varObjectProperty.Description, NewDynamicProperty = "new dynamic property description" };
//if your property is an object, instead
var varObjectProperty = varClass.propObjectProperty;
varClass.propObjectProperty = new { Id = ((dynamic)varObjectProperty).Id, Description = ((dynamic)varObjectProperty).Description, NewDynamicProperty = "new dynamic property description" };
With this approach, you basically rewrite the object property adding or removing properties as if you were first creating the object with the
new { ... }
syntax.
In your particular case, you're probably better off creating an actual object to which you assign properties like "dob" and "address" as if it were a person, and at the end of the process, transfer the properties to the actual "Person" object.
If you can't use the dynamic type with ExpandoObject, then you could use a 'Property Bag' mechanism, where, using a dictionary (or some other key / value collection type) you store string key
's that name the properties and value
s of the required type.
See here for an example implementation.
It's not possible with a "normal" object, but you can do it with an ExpandoObject
and the dynamic
keyword:
dynamic person = new ExpandoObject();
person.FirstName = "Sam";
person.LastName = "Lewis";
person.Age = 42;
person.Foo = "Bar";
...
If you try to assign a property that doesn't exist, it is added to the object. If you try to read a property that doesn't exist, it will raise an exception. So it's roughly the same behavior as a dictionary (and ExpandoObject actually implements IDictionary<string, object>
)
If you only need the dynamic properties for JSON serialization/deserialization, eg if your API accepts a JSON object with different fields depending on context, then you can use the JsonExtensionData
attribute available in Newtonsoft.Json or System.Text.Json.
Example:
public class Pet
{
public string Name { get; set; }
public string Type { get; set; }
[JsonExtensionData]
public IDictionary<string, object> AdditionalData { get; set; }
}
Then you can deserialize JSON:
public class Program
{
public static void Main()
{
var bingo = JsonConvert.DeserializeObject<Pet>("{\"Name\": \"Bingo\", \"Type\": \"Dog\", \"Legs\": 4 }");
Console.WriteLine(bingo.AdditionalData["Legs"]); // 4
var tweety = JsonConvert.DeserializeObject<Pet>("{\"Name\": \"Tweety Pie\", \"Type\": \"Bird\", \"CanFly\": true }");
Console.WriteLine(tweety.AdditionalData["CanFly"]); // True
tweety.AdditionalData["Color"] = "#ffff00";
Console.WriteLine(JsonConvert.SerializeObject(tweety)); // {"Name":"Tweety Pie","Type":"Bird","CanFly":true,"Color":"#ffff00"}
}
}
Consider using the decorator pattern http://en.wikipedia.org/wiki/Decorator_pattern
You can change the decorator at runtime with one that has different properties when an event occurs.
Take a look at the Clay library:
http://clay.codeplex.com/
It provides something similar to the ExpandoObject but with a bunch of extra features. Here is blog post explaining how to use it:
http://weblogs.asp.net/bleroy/archive/2010/08/18/clay-malleable-c-dynamic-objects-part-2.aspx
(be sure to read the IPerson interface example)