2009-05-17 3 views
20

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

Я пытался ...

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

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

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

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

РЕДАКТИР Разъяснение:

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

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

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

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

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

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

+0

Каков точный тип идентификатора "view"? – AnthonyWJones

+0

«Вид» - это элемент управления GridView от DevExpress. –

ответ

43

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

// 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... 
+0

Спасибо abdoul, ваш код довольно легко понять. У меня недавно возникла проблема с получением анонимного типа и здесь: http: //stackoverflow.com/questions/3534969/only-parameterless-constructors-and-initializers-are-supported-in-linq-to-entitie Я оставил вопрос. После некоторых поисков и работы в выходные я пришел на эту страницу, и это действительно сделало мой день. – Developer

+0

Именно поэтому я люблю SO – Bergkamp

+0

Действительно, слишком классный ответ! Это то, что я искал с 2 недель! Спасибо большое! – KomalJariwala

17

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

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

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

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

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

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

+0

«хакеры анонимного типа бросают», что это такое? – AnthonyWJones

+0

@ AnthonyWJones, я добавил пример хакерского анонимного типа. – JaredPar

+0

Спасибо за этот ответ. Очень приятное и элегантное решение. У этого есть только один недостаток: он не работает, если анонимный объект поступает из другой сборки. Это одна из причин, почему вы никогда не должны возвращать анонимный объект из метода, но не все это знают, и поэтому мне приходится иметь дело с библиотекой, которая, к сожалению, делает именно это. –

0

Возможно, это неверно (у вас может не быть достаточно кода), но вам не нужно индексировать строку, чтобы вы выбрали нужный вам столбец? Или если «Id» это столбец вы хотите, вы должны делать что-то вроде этого:

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

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

1

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

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

Этот подход имеет аналогичные недостатки, как «Hacky анонимного типа приведений», описанный раньше: Вам нужна волшебная строка для идентификации столбца плюс type cast from object to int.

2

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

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"); 
0

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

private List<StockSymbolResult> GetDistinctSymbolList(List<ICommonFields> l) 
      { 
       var DistinctList = (
         from a 
         in l 
         orderby a.Symbol 
         select new 
         { 
          a.Symbol, 
          a.StockID 
         }).Distinct(); 

       StockSymbolResult ssr; 
       List<StockSymbolResult> rl = new List<StockSymbolResult>(); 
       foreach (var i in DistinctList) 
       { 
           // Symbol is a string and StockID is an int. 
        ssr = new StockSymbolResult(i.Symbol, i.StockID); 
        rl.Add(ssr); 
       } 

       return rl; 
      } 
17

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

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"); 
+0

Я нашел это решение лучшим после объявления анонимных типов. Благодарю. – DoomerDGR8

0

Вы можете цикл через свойства анонимного типа, как это :

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

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

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

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

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

11

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

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

+0

Так просто и элегантно мне стыдно не думать об этом :) – percebus

0

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

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

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

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

0
var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value; 
+0

Это простейшая fomra, чтобы получить значение атрибутов списка (DataGridView) –

Смежные вопросы