2012-01-17 1 views
0
[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, как вар xEvent СЬК жалуется, что XPathEvaluate не определено на XElement. Это не так; его метод расширения.
  • способ, которым теперь является фрагмент (т. Е. XEvent, объявленный как XElement), он отлично работает.
  • Если я заменил раздел, начинающийся с «dynamic» и заканчивающийся в конце вызова моего метода ExpandoToMessageEvent с разделом, который в настоящее время прокомментирован, CLR счастлив.

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

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

+0

Как выглядит подпись для метода ExpandoToMessageEvent? – Groo

+0

... ExpandoToMessageEvent (ExpandoObject), который возвращает XElement ... Его в столбце ... – AlexeiOst

ответ

9

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

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

+0

xEvent НЕ является объектом ExpandoObject. Пожалуйста, прочтите более внимательно. – AlexeiOst

+1

@AlexeiOst, но если вы используете 'var', он рассматривается как' dynamic'. Фактический тип не имеет значения. Вызов 'ExpandoToMessageEven()' является динамическим, поэтому он возвращает 'dynamic'. – svick

+0

Я понимаю сейчас. Спасибо, Эрик, благодарю тебя. – AlexeiOst

2

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

+0

Но методы расширения обычно должны выводить их возвращаемый тип, если указаны параметры? – Groo

+0

Параметры не имеют к этому никакого отношения. – AlexeiOst

+0

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