Почему динамическое разрешение перегрузки не учитывает кандидатов метода расширения? - PullRequest
0 голосов
/ 17 января 2012
[TestFixture]
public class ExpandoToMessageConverterTests
{
/// <summary>
/// CanConvertEvent
/// </summary>
[Test]
public void CanConvertEvent()
{
    dynamic expandoEvent = new ExpandoObject();
    expandoEvent.PropertyOne = "pROPERTYoNE";
    expandoEvent.PropertyTow = "pROPERTYtWO";

    XElement xEvent=ExpandoToMessageConverter.ExpandoToMessageEvent(expandoEvent);

    /*var xEvent = new XElement("event",
                                new XElement("properties",
                                            new XElement("property",
                                                        new XAttribute("name", "pROPERTYoNE"),
                                                        new XAttribute("value", "someVal")),
                                            new XElement("property",
                                                        new XAttribute("name", "pROPERTYtWO"),
                                                        new XAttribute("value", "BLAH"))));*/
    Assert.IsNotNull(xEvent);
    var properties = new List<XElement>(xEvent.Descendants("properties"));
    Assert.AreEqual(1,properties.Count);


    var value = ((IEnumerable)xEvent.XPathEvaluate("properties/property")).Cast<XElement>();
    Assert.AreEqual(2, value.Count());
}

В приведенном выше коде я создаю один и тот же xml по-разному (один, явно, закомментирован). Другой использует ExpandoToMessageEvent (ExpandoObject), который возвращает XElement. Вот загадка для меня:

  • если я объявляю xEvent как var xEvent, CLR жалуется, что XPathEvaluate не определен в XElement. На самом деле это не так; это метод расширения.
  • то, как теперь сниппет (т. Е. XEvent объявлен как XElement), работает нормально.
  • если я заменю раздел, начинающийся с 'dynamic' и заканчивающийся в конце вызова моего метода ExpandoToMessageEvent, разделом, который в данный момент закомментирован, CLR рад.

Очевидно, я могу заставить это работать. Но вопрос в том, почему «динамическое» слово отбрасывает CLR?

Я решил проверить еще пару вещей, и вот что я нашел: если я передаю новый ExpandoObject () в функцию, тогда тип xEvent в «var xEvent = ExpandoToMessageConverter.ExpandoToMessageEvent (new ExpandoObject ())» определяется правильно, и CLR счастлив. Однако, если я скажу «dynamic blah = new ExpandoObject ()», а затем «var xEvent = ExpandoToMessageEvent (blah)», тип xEvent определен неправильно (я полагаю), и CLR, похоже, не учитывает методы расширения для XElement.

Ответы [ 2 ]

9 голосов
/ 17 января 2012

Разрешение перегрузки динамических вызовов не учитывает методы расширения.

Чтобы определить, какие методы расширения доступны для данного вызова, необходимо знать, какие директивы «using» действовали на сайте вызова. У нас не было ранее существующего механизма для сохранения этой информации на сайте вызовов; у нас не было бюджета, чтобы спроектировать, внедрить, протестировать и документировать новый механизм и все еще вовремя выпустить C # 4. Поэтому мы вырезали эту часть функции.

2 голосов
/ 17 января 2012

Похоже, компилятор как-то не смог определить метод расширения при использовании var, поэтому выдает ошибку. Однако dynamic работает нормально, поскольку динамические переменные не проходят проверку типа во время компиляции ( ссылка ).

...