2011-01-28 2 views
3

Использование JavaScript позволяет получить доступ к объекту с использованием нотации обозначений точек или массива.Свойства C# как нотация массива

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

Можно ли это сделать с помощью C#?

Это то, что я пытался:

[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; 
    } 
} 
+0

Почему вы хотите использовать эти обозначения? –

+1

Не делайте этого. Возможно, есть и другие законные сценарии, но это (действие контроллера ASP.NET MVC), безусловно, не является одним из них. Вы действительно действительно хотите проверить входные данные, поступающие от пользователей через Интернет. Не просто произвольные значения в произвольно именованные свойства. Это просто требует проблем с безопасностью. –

+0

Благодарим вас за полезную информацию. Поскольку я новичок, я думал о том, чтобы вводить входные значения в строго типизированный объект, который генерирует исключение, если значения не могут быть отлиты. После заполнения значений и отсутствия исключения, я бы подтвердил, что значения свойств находятся в правильном формате. После того, как все это будет проверено, я могу передать этот объект в элемент управления, который он сохранил в БД. – deDogs

ответ

5

Хотя это невозможно сделать с помощью C#. Вы можете изменить свой код несколькими способами, которые могут достичь вашей цели. Во-первых, вы можете использовать словарь как это:

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

Другой вариант должен был бы сделать это динамически:

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; 
} 

Если вам нужно перебрать свойства на строго типизированного объекта, который вы могли бы использовать отражение:

var owner = new Metis.Domain.User(); 
var properties = owner.GetType().GetProperties(); 
foreach (var prop in properties) { 
    object value = prop.GetValue(owner, null); 
} 
+0

Подход словаря не имитирует эту функцию, так как она не обеспечивает доступ к свойствам. –

+1

Я согласен, но я думаю, что важно понять доступные варианты, чтобы он мог оценить лучший способ выполнить свою задачу. Подход словаря может быть лучше, чем использование строго типизированного объекта. –

+0

Я согласен, я просто считаю, что вы заметили, что это не совпадение с описанной функцией JavaScript. –

1

Javascript нотация массив не то, что вы можете использовать в C#.

Для доступа к объектам объекта необходимо использовать точечную нотацию.

Вам нужно будет получить доступ к каждому значению непосредственно и назначить его:

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

Есть обходные пути - использование словарей, динамические объекты или даже отражение, но сценарий не поддерживается непосредственно C#.

+0

@Downvoter - Поучительно объяснять? – Oded

1

В C# нет синтаксического эквивалента, но есть некоторые способы приблизиться к одной и той же функции.

Вы можете имитировать доступ к типу индексатора с помощью Dictionary, но тогда вы потеряете доступ в стиле собственности. Для доступа свойства стиля, вы могли бы сделать что-то подобное в C# с помощью анонимного типа, например:

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

Однако это не создает массив или разрешить доступ типа массива и не позволяет модификации типа после создания.

Чтобы получить более близкое приближение к функции JavaScript, вы можете использовать ExpandoObject, чтобы немного подражать этому, или вы могли бы что-то реализовать самостоятельно.

Для этого вам понадобится класс, который имеет конструктор для автоматического генерации свойств из переданного массива и предоставляет индекс, который, в свою очередь, использует отражение для поиска именованного свойства.

Initialization этого типа будет что-то вроде:

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

Это предполагает, что есть подтип для каждого определения элемента (возможно с использованием Tuple или KeyValuePair Конструктор будет затем принимает IEnumerable<T> этого типа. .

+0

Комментарий удален, потому что вы ответили ниндзя. –

+0

@Ben: Я ценю обратную связь. –

0

Да, это возможно.

Есть две возможности:

1) Список ключей и значений является динамическим.

  • Обозначение массива представлено, например, System.Collections.Generic.Dictionary<string, blah>
  • Обозначение доступа к членству может быть обеспечено с помощью магии DLR и ключевого слова dynamic.

2) Список ключей и значений является статическим.

  • Объявление доступа к члену уже предоставлено компилятором C#.
  • Обозначение массива может быть выполнено с использованием Reflection (надеюсь, с кешем для повышения производительности).

В статическом случае нотация доступа членов намного быстрее. В динамическом случае нотация массива будет немного быстрее.

3

Я бы не рекомендовал это, но вы можете поместить указатель в свой класс, принять строку, а затем использовать отражение, чтобы прочитать это свойство. Что-то вроде:

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); 
    } 
    } 
}