How to Create New Property Dynamically

Is it possible to add dynamically named properties to JavaScript object?

Yes.

var data = {    'PropertyA': 1,    'PropertyB': 2,    'PropertyC': 3};
data["PropertyD"] = 4;
// dialog box with 4 in italert(data.PropertyD);alert(data["PropertyD"]);

Dynamically Add C# Properties at Runtime

Have you taken a look at ExpandoObject?

see: https://learn.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject

From MSDN:

The ExpandoObject class enables you to add and delete members of its instances at run time and also to set and get values of these members. This class supports dynamic binding, which enables you to use standard syntax like sampleObject.sampleMember instead of more complex syntax like sampleObject.GetAttribute("sampleMember").

Allowing you to do cool things like:

dynamic dynObject = new ExpandoObject();
dynObject.SomeDynamicProperty = "Hello!";
dynObject.SomeDynamicAction = (msg) =>
{
Console.WriteLine(msg);
};

dynObject.SomeDynamicAction(dynObject.SomeDynamicProperty);

Based on your actual code you may be more interested in:

public static dynamic GetDynamicObject(Dictionary<string, object> properties)
{
return new MyDynObject(properties);
}

public sealed class MyDynObject : DynamicObject
{
private readonly Dictionary<string, object> _properties;

public MyDynObject(Dictionary<string, object> properties)
{
_properties = properties;
}

public override IEnumerable<string> GetDynamicMemberNames()
{
return _properties.Keys;
}

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_properties.ContainsKey(binder.Name))
{
result = _properties[binder.Name];
return true;
}
else
{
result = null;
return false;
}
}

public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (_properties.ContainsKey(binder.Name))
{
_properties[binder.Name] = value;
return true;
}
else
{
return false;
}
}
}

That way you just need:

var dyn = GetDynamicObject(new Dictionary<string, object>()
{
{"prop1", 12},
});

Console.WriteLine(dyn.prop1);
dyn.prop1 = 150;

Deriving from DynamicObject allows you to come up with your own strategy for handling these dynamic member requests, beware there be monsters here: the compiler will not be able to verify a lot of your dynamic calls and you won't get intellisense, so just keep that in mind.

How to create new property dynamically

There are two methods to doing it.

One, you can directly create property dynamically from outside the class:

class Foo{

}

$foo = new Foo();
$foo->hello = 'Something';

Or if you wish to create property through your createProperty method:

class Foo{
public function createProperty($name, $value){
$this->{$name} = $value;
}
}

$foo = new Foo();
$foo->createProperty('hello', 'something');

C# dynamically set property

objName.GetType().GetProperty("nameOfProperty").SetValue(objName, objValue, null)

How to create an object with dynamic property names

In your code fruits.props[i] = 'Juice'; would try to set the 0th index value of props property where the property is undefined and causing the error.

Use bracket notation for assigning object property using a string.

var fruits = {};
var props = ['orange', 'apple', 'banana'];
for (var i = 0; i < props.length; i++) { fruits[props[i]] = 'Juice'; //----^^^^^^^^^^-----}
console.log(fruits);

How do I dynamically assign properties to an object in TypeScript?

Index types

It is possible to denote obj as any, but that defeats the whole purpose of using typescript. obj = {} implies obj is an Object. Marking it as any makes no sense. To accomplish the desired consistency an interface could be defined as follows.

interface LooseObject {
[key: string]: any
}

var obj: LooseObject = {};

OR to make it compact:

var obj: {[k: string]: any} = {};

LooseObject can accept fields with any string as key and any type as value.

obj.prop = "value";
obj.prop2 = 88;

The real elegance of this solution is that you can include typesafe fields in the interface.

interface MyType {
typesafeProp1?: number,
requiredProp1: string,
[key: string]: any
}

var obj: MyType ;
obj = { requiredProp1: "foo"}; // valid
obj = {} // error. 'requiredProp1' is missing
obj.typesafeProp1 = "bar" // error. typesafeProp1 should be a number

obj.prop = "value";
obj.prop2 = 88;

Record<Keys,Type> utility type

Update (August 2020): @transang brought this up in comments

Record<Keys,Type> is a Utility type in typescript. It is a much cleaner alternative for key-value pairs where property-names are not known.
It's worth noting that Record<Keys,Type> is a named alias to {[k: Keys]: Type} where Keys and Type are generics.
IMO, this makes it worth mentioning here

For comparison,

var obj: {[k: string]: any} = {};

becomes

var obj: Record<string,any> = {}

MyType can now be defined by extending Record type

interface MyType extends Record<string,any> {
typesafeProp1?: number,
requiredProp1: string,
}

While this answers the Original question, the answer here by @GreeneCreations might give another perspective on how to approach the problem.

Create and assign a object property dynamically typescript

This happens because on your second last line: this.myHistory is undefined. You are trying to access the property ourHistory of undefined, which the compiler does not like.

You need to instantiate the property, like mentioned in the comments to your question.

One way to do it, could do it like so:

export class HistoryComponent implements OnInit, OnDestroy {
myHistory: OurHistory;

let ourHistory = [];
ourHistory = this.allHistory.fields['ourHistory'];
this.myHistory = {ourHistory: ourHistory[0]};
}

This way, we instantiate the property myHistory with a new object:

{
ourHistory: someValue
}

C# - Adding objects dynamically (adding dynamic property names)

Rather than creating an ExpandoObject or some other dynamic type, you could create a List<Dictionary<string, object>> where each Dictionary<string, object> contains the name/value pairs you want to serialize. Then serialize to JSON using Json.NET (or JavaScriptSerializer, though that is less flexible):

        var list = new List<Dictionary<string, object>>();

// Build a dictionary entry using a dictionary initializer: https://msdn.microsoft.com/en-us/library/bb531208.aspx
list.Add(new Dictionary<string, object> { { "ID", 1 }, {"Product", "Pie"}, {"Days", 1}, {"QTY", 65} });

// Build a dictionary entry incrementally
// See https://msdn.microsoft.com/en-us/library/xfhwa508%28v=vs.110%29.aspx
var dict = new Dictionary<string, object>();
dict["ID"] = 2;
dict["Product"] = "Melons";
dict["Days"] = 5;
dict["QTY"] = 12;
list.Add(dict);

Console.WriteLine(JsonConvert.SerializeObject(list, Formatting.Indented));
Console.WriteLine(new JavaScriptSerializer().Serialize(list));

The first outputs:

[
{
"ID": 1,
"Product": "Pie",
"Days": 1,
"QTY": 65
},
{
"ID": 2,
"Product": "Melons",
"Days": 5,
"QTY": 12
}
]

The second outputs the same without the indentation:

[{"ID":1,"Product":"Pie","Days":1,"QTY":65},{"ID":2,"Product":"Melons","Days":5,"QTY":12}]


Related Topics



Leave a reply



Submit