Как я могу получить значение свойства от анонимного типа? - PullRequest
20 голосов
/ 17 мая 2009

У меня есть сетка данных, заполненная запросом Linq. Когда сфокусированная строка в сетке данных изменяется, мне нужно установить переменную, равную одному из свойств этого объекта.

Я пытался ...

var selectedObject = view.GetRow(rowHandle);
_selectedId = selectedObject.Id;

... но компилятору это совершенно не нужно («встроенное выражение не может быть объявлением или помеченным утверждением»).

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

Как получить доступ к свойству анонимного объекта?

Редактировать для уточнения:

Я использую элемент управления DevExpress XtraGrid. Я загрузил этот элемент управления запросом Linq, состоящим из нескольких различных объектов, поэтому данные фактически не соответствуют ни одному из моих классов (т. Е. Я не могу привести их ни к чему).

Я использую .NET 3.5.

Когда я просматриваю результаты метода view.GetRow (rowHandle), я получаю анонимный тип, который выглядит следующим образом:

{ ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }

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

Я попробовал пару предложений в ранних ответах, но не смог добраться до точки, где я мог получить этот ClientId.

Ответы [ 12 ]

47 голосов
/ 29 июля 2010

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

// use reflection to retrieve the values of the following anonymous type
var obj = new { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }; 
System.Type type = obj.GetType(); 
int clientid = (int)type.GetProperty("ClientId").GetValue(obj, null);
string clientname = (string)type.GetProperty("ClientName").GetValue(obj, null);

// use the retrieved values for whatever you want...
18 голосов
/ 04 декабря 2010

Общее решение для получения значения элемента данных для данного ключа

public static T GetValueFromAnonymousType<T>( object dataitem, string itemkey ) {
    System.Type type = dataitem.GetType();
    T itemvalue = (T)type.GetProperty(itemkey).GetValue(dataitem, null);
    return itemvalue;
}

Пример:

var dataitem = /* Some value here */;
bool ismember = TypeUtils.GetValueFromAnonymousType<bool>(dataitem, "IsMember");
17 голосов
/ 17 мая 2009

Одна из проблем с анонимными типами заключается в том, что их трудно использовать между функциями. Нет никакого способа «назвать» анонимный тип, и, следовательно, его очень трудно разыграть между ними. Это предотвращает их использование в качестве выражения типа для всего, что появляется в метаданных и определяется пользователем.

Я не могу точно сказать, какой API вы используете выше. Однако API не может возвращать строго типизированный анонимный тип, поэтому мое предположение в этом selectedObject типизировано как object. C # 3.0 и ниже не поддерживает динамический доступ, поэтому вы не сможете получить доступ к идентификатору свойства, даже если он доступен во время выполнения.

Вам понадобится одно из следующих, чтобы обойти это

  • Используйте отражение, чтобы захватить свойство
  • Создайте полный тип и используйте его для заполнения сетки данных
  • Используйте одно из множества хакерских приведений анонимного типа

EDIT

Вот пример того, как взломать анонимный тип.

public T AnonymousTypeCast<T>(object anonymous, T typeExpression) { 
  return (T)anonymous;
}

...
object obj = GetSomeAnonymousType();
var at = AnonymousTypeCast(obj, new { Name = String.Empty, Id = 0 });

Причина, по которой он взломан, заключается в том, что это очень легко сломать. Например, в методе, где изначально создается анонимный тип. Если я добавлю еще одно свойство к типу, приведенный выше код скомпилируется, но потерпит неудачу во время выполнения.

14 голосов
/ 30 марта 2012

Вы можете использовать динамический тип для доступа к свойствам анонимных типов во время выполнения без использования отражения.

var aType = new { id = 1, name = "Hello World!" };
//...
//...
dynamic x = aType;
Console.WriteLine(x.name); // Produces: Hello World!

Подробнее о динамическом типе читайте здесь: http://msdn.microsoft.com/en-us/library/dd264736.aspx

3 голосов
/ 29 мая 2009

Когда я работал с передачей анонимных типов и пытался их переписать, я в конечном итоге обнаружил, что проще написать оболочку, которая обрабатывает работу с объектом. Вот ссылка на сообщение в блоге об этом.

http://somewebguy.wordpress.com/2009/05/29/anonymous-types-round-two/

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

//create an anonymous type
var something = new {  
  name = "Mark",  
  age = 50  
};  
AnonymousType type = new AnonymousType(something);

//then access values by their property name and type
type.With((string name, int age) => {  
  Console.Write("{0} :: {1}", name, age);  
}); 

//or just single values
int value = type.Get<int>("age");   
1 голос
/ 28 декабря 2011

В DevExpress в xtraGridView есть такой метод GetRowCellDisplayText (int rowHandle, столбец GridColumn). При использовании этого метода следующий код возвращает идентификатор анонимного типа.

var _selectedId = view.GetRowCellDisplayText(rowHandle, "Id");

Хотя это не дает ответа на вопрос «Как я могу получить доступ к свойству анонимного объекта?», Оно все же пытается решить основную причину проблемы.

Я попробовал это с devXpress версии 11.1, и я вижу, что вопрос был задан почти 2,5 года назад. Возможно, автор вопроса мог найти обходной путь или найти решение сам. Тем не менее, я все еще отвечаю, чтобы это могло кому-то помочь.

1 голос
/ 17 мая 2009

Как правильно угадал JaredPar, тип возврата GetRow() равен object. При работе с сеткой DevExpress вы можете извлечь желаемое значение следующим образом:

int clientId = (int)gridView.GetRowCellValue(rowHandle, "ClientId");

У этого подхода есть аналогичные недостатки, такие как описанные выше «хакерские приведения анонимного типа»: вам нужна волшебная строка для идентификации столбца плюс тип, приведенный от объекта к int.

0 голосов
/ 31 декабря 2015
var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value;
0 голосов
/ 23 июля 2013

Если вы знаете, что делаете, и не боитесь получить ошибки времени выполнения при изменении кода, вы можете преобразовать данные строки в dynamic:

var data = view.GetRow(rowHandle) as dynamic;  

int clientId      = data.ClientID;
string clientName = data.ClientName;
int jobs          = data.Jobs

Нет проверки во время компиляции. Но это должно работать хорошо.

0 голосов
/ 24 марта 2011

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

var obj = new {someValue = "hello", otherValue = "world"};
foreach (var propertyInfo in obj.GetType().GetProperties() {
    var name = propertyInfo.Name;
    var value = propertyInfo.GetValue(obj, index: null);
    ...
}
...