2012-04-25 2 views
6

編集:Visual Studioを再起動するとコードが変更されずにこの問題が修正されました。動的オブジェクト - ランタイムレポートフィールドは存在しませんが、デバッガで表示できますか?


私は、ダイナミック型を使用しConfigSectionハンドラとはExpandoオブジェクトを持っています。テストに失敗しました'object'に '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> 

UPDATEについては下記を参照してください - スタックトレース:

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

コードが正しく表示され、コンソールで正常に動作していることを確認してください。テストのデバッグを試み、例外を処理した 'tick'。地元の人々を調べて、コールスタックの上部(外部コードを表示)で掘り出しを開始します。 – leppie

+0

デバッグ>例外ダイアログでティック「スロー」を意味する場合、同じポイントでブレークします。コールスタックで更新されました。 –

+1

はい、それは意味します。今すぐそこで壊れたら、上の2つのフレームの地元の人々を調べてください。また、アセンブリからILを検査して、何かが間違っているかどうかを確認することもできます。 – leppie

答えて

3

ToSportExpandoObjectではなく、匿名型を返します。匿名型を動的にキャストするときは、アクセス修飾子が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; 
     } 

    } 
+0

これは私が経験した問題を説明するものですが、VSを再起動した理由を説明していません。奇妙な。 –

+1

異なる種類のビルドでは、アセンブリ境界がどこにあるのかが不明瞭になることがあります。たとえば、ASP.NETには、異なるアセンブリにグループ化されてランダムに編集できるページがあります。私はどちらがVSを修正したのか分かりませんが、ExpandoObjectsでダイナミックキャストを返す匿名型を置き換えることは本当に良い習慣であることは分かっています。 – jbtule

+0

良いアドバイス、ありがとう! –

関連する問題