Список анонимного типа и динамики ... Запутано - PullRequest
3 голосов
/ 04 февраля 2011

Я нашел в .NET что-то, что работает немного иначе, чем я ожидал.Код, который я вставляю, не имеет смысла, но это сжатая версия гораздо более сложной функции, которую я имею.По сути, я получаю информацию об анонимном типе в качестве параметра (еще не создано ни одного экземпляра анонимного типа), и мне нужно создать список этого типа, заполнить его, а затем вернуть список.Теперь я нашел решение, но хотел знать, почему метод B работает, а не метод A.

Метод A:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

Метод B:

static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    System.Collections.IList list;

    list = (System.Collections.IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add(Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));
}

Опять же, я не ищу решения, просто любопытно, почему метод B работает, но не метод A.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 04 февраля 2011

Поскольку в вашем методе B вы используете явный IList.Add(object), который берет объект и пытается привести его к анонимному типу.В методе A у вас есть List<anonymous type>, и вы используете общий метод Add и пытаетесь добавить объект, но вы получаете RuntimeBinderException, потому что он ожидает правильно приведенный тип.Если вы не используете dynamic, вы увидите ошибку компилятора.Чтобы использовать явный IList.Add, измените ваш метод A на

((IList)list).Add(
    Activator.CreateInstance(newItem.GetType(), 
        new object[] { Guid.NewGuid(), "Test 2" }));
0 голосов
/ 08 марта 2011

Все, что вам нужно сделать, чтобы метод А работал, - это dynamic приведение результата активатора, который вы добавляете. Многие люди не понимают, что динамический вызов C # на самом деле использует статические типы по умолчанию для определения сигнатуры метода. Поэтому, приведя аргумент к динамическому, вы также указываете ему использовать тип времени выполнения.

   static void Main(string[] args)
{
    var newItem = new {  ID = Guid.NewGuid(), Name = "Test" };
    dynamic list;

    list = Activator.CreateInstance(typeof(List<>).MakeGenericType(newItem.GetType()));

    list.Add(newItem);
    list.Add((dynamic)Activator.CreateInstance(newItem.GetType(), new object[] { Guid.NewGuid(), "Test 2" }));

}
...