Подтвердить что ты не робот

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

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

Я пробовал...

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.

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

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

ИЗМЕНИТЬ

Здесь пример о том, как сделать хакерский анонимный тип

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

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

Этот подход имеет похожие недостатки, такие как "хакеры анонимного типа", описанные ранее: вам нужна волшебная строка для идентификации столбца плюс тип, отлитый от объекта к int.

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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

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

Ответ 10

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

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

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

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

Ответ 11

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

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

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

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

Ответ 12

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