Как привести объект к анонимному типу в другой сборке? - PullRequest
2 голосов
/ 25 февраля 2011

У меня есть GridView, где мой DataSource:

items.Select(i => new { ID = i.ID, Foo = i }).ToList();

В RowDataBound я хочу получить доступ к объекту, но не знаю, как его привести ...

grid.RowDataBound += (s, e) =>
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        dynamic item = e.Row.DataItem as 'what?';
    }
};

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


Шаги для воспроизведения

  1. Создать сайт
  2. Создать страницу(default.aspx) и поместите <asp:GridView ID="grid" runat="server" />
  3. в коде:

add

protected void Page_Load(object sender, EventArgs ev)
{
    var provider = new FooProvider();

    grid.DataSource = provider.Elements;
    grid.RowDataBound += (s, e) =>
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            dynamic item = e.Row.DataItem;

            var test = item.ID;
        }
    };
    grid.DataBind();
}
  1. Создание проекта библиотеки классов
  2. Добавить файл FooProvider.cs

Код:

public class FooProvider
{
    public IEnumerable<dynamic> Elements
    {
        get
        {
            return new int[] { 1, 2, 3 }
                .Select(i => new { ID = i, Foo = i * 3 }).ToList();
        }
    }
}

Затем добавить ссылку на сайт.


Ожидаемый результат: Получить идентификатор анонимного объекта.

Текущий результат:

RuntimeBinderException не обработан кодом пользователя

'object' не содержит определения для 'ID'


Является ли отражение единственным способом?

Ответы [ 6 ]

8 голосов
/ 25 февраля 2011

Не используйте анонимные типы.Сделай класс.

public class MyCustomRow
{
  int ID {get;set;}
  Foo Foo {get;set;}
}

(wtf? Dynamic?)

4 голосов
/ 25 февраля 2011

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

dynamic item = e.Row.DataItem;
DoSomething((int)item.Foo)

(хотя я согласен с Дэвидом Б, что я бы предпочел иметь безопасный тип, объявленный класс.)Кстати, есть один прием, который вы можете использовать с генериками, который позволит вам сделать что-то вроде этого:

var item = e.Row.DataItem.CastAnonymous(new {ID = 1, Foo = 1});
DoSomething(item.Foo);

... но я думаю, что это худший из трех вариантов. Редактировать

При работе между сборками отражение - единственный способ выполнить то, что вы просите.Анонимные типы всегда предназначались для того, чтобы оставаться в пределах одного метода, поэтому вы не можете объявить их как параметр или тип возврата.Они делают такие вещи, как операторы LINQ, гораздо менее утомительными, но их цель - не превращать C # в язык сценариев.Есть ли причина, по которой вы не можете объявить сильный тип?

0 голосов
/ 27 июня 2014

Почему бы не использовать DataBinder.Eval ()?

    grid.RowDataBound += (s, e) =>
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            var test = DataBinder.Eval(e.Row.DataItem, "Id");
        }
    }
0 голосов
/ 28 февраля 2011

Вы можете использовать оболочку с открытым исходным кодом Impromptu-Interface , чтобы подключить анонимный тип к статическому интерфейсу, позволяющему ему работать в другой сборке.

Интерфейс Impromptu фактически использует тот жеapi в качестве динамического ключевого слова, за исключением того, что оно устанавливает контекст для структуры, в которой вы объявили свой анонимный тип. Таким образом, динамический вызов будет разрешен правильно (поскольку анонимные типы компилируются как internal).

return new int[] { 1, 2, 3 }
            .Select(i => new { ID = i, Foo = i * 3 }
                            .ActLike<IMyMadeUpInterface>()).ToList();
0 голосов
/ 25 февраля 2011

Не думаю, что ты можешь. Некоторое время назад у меня было нечто подобное, и, насколько я помню, мне пришлось использовать нотацию <%%> для ссылки на анонимные свойства (ID и Foo, в вашем случае). Если у вас есть более сложная обработка в RowDataBound, вам нужно определить класс.

0 голосов
/ 25 февраля 2011

var item = e.Row.DataItem; не работает?

не можете ли вы создать собственный класс модели для хранения информации, чтобы вы могли ее привести?

...