C# 动态对象-运行时报告字段不存在,但可以在调试器中看到它?

C# 动态对象-运行时报告字段不存在,但可以在调试器中看到它?,c#,.net,dynamic,C#,.net,Dynamic,编辑:重新启动visual studio修复了此问题,没有代码更改。 我有一个使用动态类型和expando对象的ConfigSection处理程序。测试失败报告“对象”不包含“SportName”的定义。我曾尝试在控制台中进行复制,将ConfigSection处理程序从等式中去掉,但看起来等效的代码可以正常工作。我被难住了 有关测试、ConfigurationSectionHandler和配置xml,请参见下文 public class SportSection : IConfiguratio

编辑:重新启动visual studio修复了此问题,没有代码更改。


我有一个使用动态类型和expando对象的ConfigSection处理程序。测试失败报告“对象”不包含“SportName”的定义。我曾尝试在控制台中进行复制,将ConfigSection处理程序从等式中去掉,但看起来等效的代码可以正常工作。我被难住了

有关测试、ConfigurationSectionHandler和配置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>
公共类SportSection:IConfigurationSectionHandler
{
公共对象创建(对象父对象、对象配置上下文、XmlNode部分)
{
var doc=XDocument.Parse(section.OuterXml);
var root=(XElement)doc.FirstNode;
尝试
{
var sportList=root.Element(“sportList”).Elements(“sport”).Select(ToSport);
动态配置=新的ExpandooObject();
config.SportList=SportList;
返回配置;
}
捕获(例外情况除外)
{
抛出新的ConfigurationErrorsException(“无效的SportSection配置”,ex);
}
}
专用静态动态ToSport(XElement sportElement)
{
尝试
{
var getAttrib=newfunc((x,atr)=>x.Attribute(atr.Value);
var getDictionary=
新的Func(elems=>elems.ToDictionary(x=>x.Attribute(“name”).Value,y=>y.Attribute(“Value”).Value));
还新
{
SportName=sportElement.Attribute(“name”).Value,
EventProperties=getDictionary(sportElement.Element(“EventProperties”).Elements(“property”),
CompetitionProperties=getDictionary(sportElement.Element(“CompetitionProperties”).Elements(“property”),
MappedMarkets=sportElement.Element(“映射”).Elements(“市场”).Select(x=>new MappedMarket(){Type=getAttrib(x,“类型”),MappedType=getAttrib(x,“MappedType”)})
};
}
捕获(例外情况除外)
{
掷骰子;
}
}
}
[测试]
public void GoodConfig()
{
var document=新的XmlDocument();
document.LoadXml(Resources.ValidSportSectionConfig);
var config=new SportSection().Create(null,null,document)为动态;
IEnumerable sportList=config.sportList;
arenequal(1,sportList.Count());
//Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:“对象”不包含“SportName”的定义
Assert.AreEqual(“棒球”,sportList.Select(x=>(字符串)x.SportName.First());
var eventProperties=sportList.First(x=>x.SportName==“棒球”).eventProperties作为IDictionary;
arenequal(2,eventProperties.Count);
Assert.AreEqual(“BSB”,eventProperties[“SportId]”);
Assert.AreEqual(“THA”,eventProperties[“Competitor或ReferenceId]”);
var compProps=sportList.First(x=>x.SportName==“棒球”)。CompetitionProperties作为IDictionary;
Assert.AreEqual(2,compProps.Count);
Assert.AreEqual(“BSB”,compProps[“SportId]”);
Assert.AreEqual(“杯”,compProps[“CompetitionOrgMethodId”);
var mappedMarkets=(sportList.First(x=>x.SportName==“棒球”).mappedMarkets as IEnumerable.ToList();
AreEqual(2,mappedMarkets.Count());
Assert.AreEqual(“match_winner”,mappedMarkets[0]。类型);
Assert.AreEqual(“BSBAO”,mappedMarkets[0].MappedType);
Assert.AreEqual(“障碍”,mappedMarkets[0]。类型);
Assert.AreEqual(“BSBAQ”,mappedMarkets[0].MappedType);
}
更新-堆栈跟踪:

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
CallSite.Target上的
(闭包、调用站点、对象)
在System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](调用站点,T0 arg0)
在C:\\u Git\SS.Integration.EVenue\SS.Integration.EVenue.WindowsService.UnitTests.Configuration.SportSectionTests.b_u11(对象x)中的SS.Integration.EVenue\SS.Integration.EVenue.WindowsService.UnitTests\Configuration\SportSectionTests.cs:第35行

ToSport
返回匿名类型,而不是
ExpandoObject
。将匿名类型强制转换为动态类型时必须小心,因为这些类型的访问修饰符为
internal
。因此,如果您跨越程序集边界,运行时将看不到任何可访问的属性。尝试:

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

    }
专用静态动态ToSport(XElement sportElement)
{
尝试
{
var getAttrib=newfunc((x,atr)=>x.Attribute(atr.Value);
var getDictionary=
新的Func(elems=>elems.ToDictionary(x=>x.Attribute(“name”).Value,y=>y.Attribute(“Value”).Value));
动态n=新的ExpandooObject();
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(“映射”).Elements(“市场”)。选择(x=>new MappedMarket(){Type=getAttrib(x,“Type”),MappedType=getAttrib(x,“MappedType”)});
返回n;
}
捕获(例外情况除外)
{
掷骰子;
}
}

代码看起来正确,您确认它在控制台中运行正常。尝试调试测试,“勾选”处理异常。然后通过检查局部变量开始挖掘调用堆栈的顶部(显示外部代码)。如果您的意思是在调试>异常对话框中勾选“抛出”,然后在同一点中断..使用调用堆栈更新,thxYes,我的意思是。现在,当它在那里破裂时,检查顶部2帧中的局部区域。您也可以从程序集中检查IL,看看是否有问题。重新启动