2012-04-25 7 views
6

EDYCJA: ponowne uruchomienie Visual Studio rozwiązało ten problem bez żadnych zmian kodu.obiekt dynamiczny - pole raportów runtime nie występuje, ale może być widoczne w debugerze?


Mam obsługi ConfigSection który wykorzystuje dynamiczne rodzaje i przedmiot expando. Test nie powiódł się. Zgłoszenie "Obiekt" nie zawiera definicji "SportName". Próbowałem replikować w konsoli odbierającej program obsługi ConfigSection poza równanie, ale to, co wygląda na równoważny kod, działa dobrze. Jestem zdumiony.

Poniżej testu, ConfigurationSectionHandler i konfiguracyjnym XML

public class SportSection : IConfigurationSectionHandler 
{ 
    public object Create(object parent, object configContext, XmlNode section) 
    { 
     var doc = XDocument.Parse(section.OuterXml); 
     var root = (XElement)doc.FirstNode; 

     try 
     { 
      var sportList = root.Element("sportList").Elements("sport").Select(ToSport); 

      dynamic config = new ExpandoObject(); 
      config.SportList = sportList; 

      return config; 
     } 
     catch (Exception ex) 
     { 
      throw new ConfigurationErrorsException("Invalid SportSection configuration", ex); 
     } 
    } 

    private static dynamic ToSport(XElement sportElement) 
    { 
     try 
     { 
      var getAttrib = new Func<XElement, string, string>((x, atr) => x.Attribute(atr).Value); 
      var getDictionary = 
       new Func<IEnumerable<XElement>, IDictionary<string, string>>(elems => elems.ToDictionary(x => x.Attribute("name").Value, y => y.Attribute("value").Value)); 

      return new 
      { 
       SportName = sportElement.Attribute("name").Value, 
       EventProperties = getDictionary(sportElement.Element("eventProperties").Elements("property")), 
       CompetitionProperties = getDictionary(sportElement.Element("competitionProperties").Elements("property")), 
       MappedMarkets = sportElement.Element("mapping").Elements("market").Select(x => new MappedMarket() { Type = getAttrib(x, "type"), MappedType = getAttrib(x, "mappedType") }) 
      }; 
     } 
     catch (Exception ex) 
     { 

      throw ex; 
     } 

    } 
} 


[Test] 
    public void GoodConfig() 
    { 
     var document = new XmlDocument(); 
     document.LoadXml(Resources.ValidSportSectionConfig); 

     var config = new SportSection().Create(null, null, document) as dynamic; 

     IEnumerable<dynamic> sportList = config.SportList; 

     Assert.AreEqual(1, sportList.Count()); 
     //Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : 'object' does not contain a definition for 'SportName' 
     Assert.AreEqual("Baseball", sportList.Select(x => (string) x.SportName).First()); 

     var eventProperties = sportList.First(x => x.SportName == "Baseball").EventProperties as IDictionary<string, string>; 

     Assert.AreEqual(2, eventProperties.Count); 
     Assert.AreEqual("BSB", eventProperties["SportId"]); 
     Assert.AreEqual("THA", eventProperties["CompetitorReferenceId"]); 

     var compProps = sportList.First(x => x.SportName == "Baseball").CompetitionProperties as IDictionary<string, string>; 
     Assert.AreEqual(2, compProps.Count); 
     Assert.AreEqual("BSB", compProps["SportId"]); 
     Assert.AreEqual("CUP", compProps["CompetitionOrgMethodId"]); 

     var mappedMarkets = (sportList.First(x => x.SportName == "Baseball").MappedMarkets as IEnumerable<MappedMarket>).ToList(); 
     Assert.AreEqual(2, mappedMarkets.Count()); 
     Assert.AreEqual("match_winner" , mappedMarkets[0].Type); 
     Assert.AreEqual("BSBAO", mappedMarkets[0].MappedType); 
     Assert.AreEqual("handicap", mappedMarkets[0].Type); 
     Assert.AreEqual("BSBAQ", mappedMarkets[0].MappedType); 
    } 

<sportSettings> 
    <sportList> 
    <sport name="Baseball"> 
    <eventProperties> 
     <property name="SportId" value="BSB"></property> 
     <property name="CompetitorReferenceId" value="THA"></property> 
    </eventProperties> 
    <competitionProperties> 
     <property name="SportId" value="BSB" /> 
     <property name="CompetitionOrgMethodId" value="CUP" /> 
    </competitionProperties> 
    <mapping> 
     <market type="match_winner" mappedType="BSBAO" /> 
     <market type="handicap" mappedType="BSBAQ" /> 
    </mapping> 
    </sport> 
    </sportList> 
</sportSettings> 

UPDATE - Stack Trace:

at CallSite.Target(Closure , CallSite , Object) 
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0) 
at SS.Integration.EVenue.WindowsService.UnitTests.Configuration.SportSectionTests.<GoodConfig>b__11(Object x) in C:\_Git\SS.Integration.EVenue\SS.Integration.EVenue.WindowsService.UnitTests\Configuration\SportSectionTests.cs:line 35 
+1

Kod wygląda poprawnie i potwierdzasz, że działa poprawnie w konsoli. Spróbuj debugowania testu i "zaznacz" obsługiwane wyjątki. Następnie zacznij kopać w górnej części okna wywoławczego (pokaż kod zewnętrzny), sprawdzając mieszkańców. – leppie

+0

Jeśli masz na myśli zaznaczenie 'Wyrzucony' w oknie dialogowym Debuguj> Wyjątek, to pęknie w tym samym punkcie .. zaktualizowano stos wywoławczy, thx –

+1

Tak, mam na myśli to. Teraz, kiedy się tam włamie, sprawdź mieszkańców w dwóch górnych klatkach. Możesz również sprawdzić IL od złożeń, aby zobaczyć, czy coś jest nie w porządku. – leppie

Odpowiedz

3

ToSport zwraca typ anonimowy raczej niż ExpandoObject. Musisz zachować ostrożność, gdy rzucasz typ anonimowy dynamiczny, ponieważ typy te mają modyfikator dostępu o wartości internal. Tak więc, jeśli przekroczysz granice zespołu, środowisko wykonawcze nie zobaczy żadnych dostępnych właściwości. Wypróbuj:

private static dynamic ToSport(XElement sportElement) 
    { 
     try 
     { 
      var getAttrib = new Func<XElement, string, string>((x, atr) => x.Attribute(atr).Value); 
      var getDictionary = 
       new Func<IEnumerable<XElement>, IDictionary<string, string>>(elems => elems.ToDictionary(x => x.Attribute("name").Value, y => y.Attribute("value").Value)); 


      dynamic n = new ExpandoObject(); 
      n.SportName = sportElement.Attribute("name").Value; 
      n.EventProperties = getDictionary(sportElement.Element("eventProperties").Elements("property")); 
      n.CompetitionProperties = getDictionary(sportElement.Element("competitionProperties").Elements("property")); 
      n.MappedMarkets = sportElement.Element("mapping").Elements("market").Select(x => new MappedMarket() { Type = getAttrib(x, "type"), MappedType = getAttrib(x, "mappedType") }); 

      return n; 
     } 
     catch (Exception ex) 
     { 

      throw ex; 
     } 

    } 
+0

To by wyjaśniało problem, którego doświadczyłem, chociaż nie wyjaśnia, dlaczego restartowanie VS je naprawiło. Dziwne. –

+1

Różne typy kompilacji mogą czasami zaciemniać obszar, w którym znajduje się granica zespołu. Na przykład strona ASP.NET zawiera strony, które są kompilowane w locie, a następnie mogą być losowo grupowane w różne złożenia. Nie wiem też, dlaczego VS to naprawił, ale wiem, że to naprawdę dobra praktyka, aby zastąpić powracające anonimowe dynamiczne rzuty z ExpandoObjects. – jbtule

+0

Dobra rada, dziękuję! –

Powiązane problemy