6

Using JavaScript it's possible to access an object using the dot notation or array notation.

var myArray = {e1:"elem1",e2:"elem2",e3:"elem3",e4:"elem4"};
var val1 = myArray["e1"];
var val2 = myArray.e1;

Is it possible to accomplish this using C#?

This is what I have attempted:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection frmVals)
{
  string value;
  Owner owner = new Owner();

  foreach (var key in frmVals.AllKeys)
  {
    value = frmVals[key];
    owner[key] = value;  
  }
}
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
deDogs
  • 739
  • 1
  • 8
  • 24
  • Why do you want to use this notation? – Eric Giguere Jan 28 '11 at 17:40
  • 1
    Don't do this. Maybe there are other legit scenarios, but this (an ASP.NET MVC controller action) is definitely not one of them. You really really really want to validate input coming from users over the web. Don't just stuff arbitrary values into arbitrarily named properties. That's just asking for security problems. – Robert Levy Jan 28 '11 at 17:49
  • Thank you for the helpful information. Since I'm new, my thinking was to stuff the input values into a strongly typed object, which would throw an exception if values couldn't be cast. After stuffing the values and if no exception, then I would validate the property values are in correct format. After all this is verified then I can pass this object to a Control, which it saved to DB. – deDogs Jan 28 '11 at 18:46
  • Yeah, you can do it in C# 4.0 with ExpandoObject, but you won't get intellisense on the members. It's basically a dynamic object that implements IDictionary. http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject(v=vs.100).aspx – BrainSlugs83 Nov 04 '12 at 00:47

5 Answers5

6

While there is no way to do this exactly with C#. You could change your code in several ways that may accomplish your goal. First, you could use a Dictionary like this:

var something = new Dictionary<string, object>() {
    { "property", "value"},
    { "property1", 1}
};
foreach (var keyVal in something) {
    var property = keyVal.Key;
    var propertyValue = keyVal.Value;
}

Another option would be to do it dynamically:

dynamic somethingDyn = new System.Dynamic.ExpandoObject();
somethingDyn.property = "value";
somethingDyn.property1 = 1;

var somethingDynDict = (IDictionary<string, object>)somethingDyn;
var propValue = somethingDyn["property"];

foreach (var keyVal in somethingDynDict) {
    var property = keyVal.Key;
    var propertyValue = keyVal.Value;
}

If you need to iterate through properties on a strongly typed object you could use reflection:

var owner = new Metis.Domain.User();
var properties = owner.GetType().GetProperties();
foreach (var prop in properties) {
    object value = prop.GetValue(owner, null);
}
Nate Totten
  • 8,904
  • 1
  • 35
  • 41
  • The Dictionary approach doesn't mimic the feature as it doesn't provide the property-style access. – Jeff Yates Jan 28 '11 at 17:41
  • 1
    I agree, but I think it is important that he understand the options that are available so he can evaluate the best way accomplish his task. The dictionary approach might be better than using a strongly typed object. – Nate Totten Jan 28 '11 at 17:43
  • I agree, I just think it pertinent that you note it is not a one-for-one match to the JavaScript feature described. – Jeff Yates Jan 28 '11 at 19:19
3

I wouldn't recommend this, but you could put an indexer in your class, accepting a string, then use reflection to read that property. Something like:

public object this[string key]
{
  get
  {
    var prop = typeof(ThisClassName).GetProperty(key);
    if (prop != null)
    {
      return prop.GetValue(this, null);
    }
    return null;
  }
  set
  {
    var prop = typeof(ThisClassName).GetProperty(key);
    if (prop != null)
    {
      prop.SetValue(this, value, null);
    }
  }
}
Joe Enos
  • 39,478
  • 11
  • 80
  • 136
1

Javascript array notation is not something you can use in C#.

You need to use dot notation to access members of an object.

You will need to access each value directly and assign it:

owner.key = frmVals[key];
owner.key2 = frmVals[key2];

There are workarounds - using dictionaries, dynamic objects or even reflection, but the scenario is not a directly supported by C#.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
1

There is no syntactic equivalent possible in C# but there are some ways to approximate the same feature.

You could mimic the indexer type access using a Dictionary but then you'd lose the property-style access. For property-style access, you could do something similar in C# by using an anonymous type, as in:

var myType = new { e1="elem1",e2="elem2",e3="elem3",e4="elem4"};
var val1 = myType.e1;

However, that doesn't create an array or allow array type access and it doesn't allow for modifications to the type after creation.

To get a closer approximation to the JavaScript feature, you may be able to use ExpandoObject to mimic this a little more closely, or you could implement something yourself.

For that, you'd need a class that has a constructor to auto-generate properties from the passed in array and exposes an indexer, which in turn uses reflection to find the named property.

Initialization of this type would be something like:

var myType = new MyType(new[]{
    {"e1", "elem1"},
    {"e2", "elem2"},
    {"e3", "elem3"},
    {"e4", "elem4"}});

This assumes there is a sub-type for each element definition (possibly using Tuple or KeyValuePair. The constructor would then be taking an IEnumerable<T> of that type.

Jeff Yates
  • 61,417
  • 20
  • 137
  • 189
0

Yes, it's possible.

There are two possibilities:

1) The list of keys and values is dynamic.

  • The array notation is provided by e.g. System.Collections.Generic.Dictionary<string, blah>
  • The member access notation can be provided through DLR magic and the dynamic keyword.

2) The list of keys and values is static.

  • Member access notation is already provided by the C# compiler.
  • Array notation can be had using Reflection (hopefully with a cache to improve performance).

In the static case, member access notation is MUCH faster. In the dynamic case, array notation will be a little faster.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720