dynamic object - runtime reports field not present but can see it in debugger?

.net, c#, dynamic

Solution

`ToSport` returns an anonymous type rather than an `ExpandoObject`. You have to be careful when you cast an anonymous type to dynamic, because those types have an access modifier of `internal`. Thus, if you cross assembly boundaries the runtime won't see any accessable properties. Try:

 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;
        }

    }

Problem

EDIT : restarting visual studio fixed this issue with no code changes. I have a ConfigSection handler that uses dynamic types and an expando object. The test fails reporting 'object' does not contain a definition for 'SportName'. I have tried to replicate in a console taking the ConfigSection handler out of the equation but what looks like the equivalent code works fine. I'm stumped. See below for test, ConfigurationSectionHandler and config 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 ```

Original source