2011-10-26 21 views
5

私はXMLファイルを読み書きするクラスを用意しています。 は今それの簡易版は、次のようになりますXElementがグローバルにnullの場合はチェックしてください

public class EstEIDPersoConfig 
{ 
    public bool LaunchDebugger { get ; set; } 
    public string Password { get; set; } 
    public int Slot { get; set; } 
    public string Reader { get; set; } 
    public string TestInput { get; set; } 
    public bool Logging { get; set; } 

    public EstEIDPersoConfig() 
    { 
     XElement xml = XElement.Load(myxml.xml); 
     XElement Configuration = xml.Element("Configuration"); 

     LaunchDebugger = Convert.ToBoolean(Configuration.Element("LaunchDebugger").Value); 
     Password = Configuration.Element("Password").Value; 
     Slot = Convert.ToInt32(Configuration.Element("Slot").Value); 
     Reader = Configuration.Element("Reader").Value; 
     TestInput = Configuration.Element("TestInput").Value; 
     Logging = Convert.ToBoolean(Configuration.Element("Logging").Value); 
    } 
} 

そしてより後であるでしょう。その問題は、xmlにいくつかの要素が存在しない場合、私はSystem.NullReferenceExceptionとなるということです。だから私は、要素がnullかどうかを確認する必要があります。これを行うには1つの方法があります。

var value = Configuration.Element("LaunchDebugger").Value; 
if (value != null) 
    LaunchDebugger = Convert.ToBoolean(value); 
else 
    throw new Exception("LaunchDebugger element missing from xml!"); 

しかし、すべての要素でこれを行うのは、あまりにも多くなります。ですから、私はこのシステムを簡素化するための良いアイデアが必要なので、1000行のコードで終わることはありません。

EDIT:最後のコードスニペットを編集しました。アイデアはデフォルト値を設定していませんでした。アイデアはこの要素がxmlから欠落していることをユーザーに通知することでした。

+0

xmlの値がnullの場合、適切なコンストラクターに、xmlの遅延初期化を実行します。 – mozillanerd

+1

@ hs2d - 私はabatishchevの答えはあなたが探しているものだと思います。 – Tim

答えて

4

は、MSDNを参照してください。

Microsoft hereに記載されているとおり、XElementを希望のタイプにキャストできます。

LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger"); 

あなたがnullケースを処理したい場合、私はあなたがあなたのビジネスロジックに依存

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true); 

または多分

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false); 

を行うことができると思います。あなたが特定のタイプのための同じcoalesceneを行う場合は、この1つのライナーをメソッド、拡張子などで囲むことが適切な場合がありますが、それが多く追加されるかどうかは不明です。

+1

'bool? 'を使う必要があるようです。 – abatishchev

+0

が更新されました。他のプリミティブでも同じです。 – Jodrell

+1

+1は?? (ヌル集合演算子、私は信じていますか?)ヌル要素の場合にはデフォルト値を設定します。私は今夜​​このスレッドから2つの有用なことを学びました:) – Tim

2

ロジックをメソッドに抽出し、Int32、booleanおよびその他のデータ型変換用のオーバーロードされたメソッドを持っています。

public static void GetElementValue(XElement xElement, string parameter, out bool value) 
    { 
     var stringValue = xElement.Element(parameter).Value; 
     value = false; 
     if (value != null) 
      value = Convert.ToBoolean(stringValue); 
    } 
+0

私は 'out'パラメータを使わず、戻り値を使います。また、 "LaunchDebugger"という文字列がパラメータであった場合は、より便利です。 –

+0

入力ミスを修正しました。コードを書くためにIDEを使用していませんでした。 – luqi

+0

しかし、このように私はまだすべてのXML要素のための外部メソッドを作成する必要がありますか?または、私がここに何かを見逃しています。 – hs2d

1

外部方法についてどのように:私はSnippetCompilerでこれをテストしてみた

public static class XElementExtensions 
{ 
    public static bool AsBoolean(this XElement self, bool defaultValue) 
    { 
     if (self == null) 
     { 
      return defaultValue; 
     } 
     if (!string.IsNullOrEmpty(self.Value)) 
     {   
      try 
      { 
       return XmlConvert.ToBoolean(self.Value); 
      } 
      catch 
      { 
       return defaultValue; 
      } 
     } 
     return defaultValue; 
    } 
} 

False 
True 
False 
False 
False 

は、複数のこのような追加:

XElement test = new XElement("test", 
    new XElement("child1"), 
    new XElement("child2", new XText("true")), 
    new XElement("child3", new XText("false")), 
    new XElement("child4", new XText("rubbish"))); 

WL(test.Element("child1").AsBoolean(false)); // note, "child1" has no value (or is `""`) 
WL(test.Element("child2").AsBoolean(false)); 
WL(test.Element("child3").AsBoolean(false)); 
WL(test.Element("child4").AsBoolean(false)); 
WL(test.Element("child5").AsBoolean(false)); // note, "child5" doesn't exist   

は、この結果を生成するために、他のタイプのメソッドと012を追加するは、デフォルトでtrueにしたい場合に便利です。

他の人が述べたように、演算子を使用してnullの値を指定できます。これは、巣は、しかし、そうしない:XMLファイルには、このような要素が存在しない場合

LaunchDebugger = XmlConvert.ToBoolean(Configuration.Element("LaunchDebugger").Value) ?? false; 

NullReferenceExceptionを介します。

+2

abatischevの回答で、「?」合体演算子を使用してMicrosoftの記述手法を使用するのは簡単ではないでしょうか? – Jodrell

1

値を抽出してそこでnullをチェックする方法を定義できます。だから、そのようなあなた自身の方法で値検索をラップ:あなたは私はちょうどこのように使用する拡張メソッドを持っているなど

+3

なぜフレームワークの開発者はこれを追加しませんでしたか?それは必要ないので、答えます。アバティシェフの答えを見てください。 – Jodrell

+1

@ジョドレル:私は今それを見る...私は実際にこのポストから何かを学んだと思う;)ありがとう男! –

2

をブールするパースで正しく動作するために、これを拡張することができ

もちろん
public string GetXMLValue(XElement config, string elementName){ 
    var element = Configuration.Element(elementName); 

    if(element == null) 
     return String.Empty; 

    return element.Value; 
} 

物:

public static T GetValue<T>(
      this XElement @this, 
      XName name, 
      Func<XElement, T> cast, 
      Func<T> @default) 
    { 
     var e = @this.Element(name); 
     return (e != null) ? cast(e) : @default(); 
    } 

これはあなたに必要なキャストとデフォルト値の工場を与えます。ここで

は、あなたがそれを使用したい方法は次のとおりです。

LaunchDebugger = Configuration.GetValue("LaunchDebugger", 
    x => Convert.ToBoolean(x),() => false); 
Password = Configuration.GetValue("CMKPassword", x => (string)x,() => ""); 
Slot = Configuration.GetValue("CMKSlot", x => (int)x,() => -1); 
Reader = Configuration.GetValue("Reader", x => (string)x,() => ""); 
TestInput = Configuration.GetValue("TestInput", x => (string)x,() => ""); 
Logging = Configuration.GetValue("Logging", 
    x => Convert.ToBoolean(x),() => false); 
+1

2つのラムダをジェネリックに渡す方が、 ''ヌルコアレンス演算子をキャストして使用するほうがよろしいですか? – Jodrell

+0

タイプ "T"のプレーンな値の代わりに2番目のラムダを使うのはなぜですか? –

+0

@ Jodrell - 「キャスト」ラムダは、コンバージョンとして本当によく考えられます。コードを一貫させるために私はそれをやります。 – Enigmativity

4
(bool)Configuration.Element("LaunchDebugger") 

または

(bool?)Configuration.Element("LaunchDebugger") 

例外をスローしてはいけません。彼は信用に値するので、ここでの考え方はabatischevの答えから直接来て

+0

なぜdownvoteは、私に最高の答えのように見えるhttp://msdn.microsoft.com/en-us/library/bb387049.aspx – Jodrell

+0

@ Jodrell:あなたは正しいようです...私の悪い。それは少し奇妙に見えます! –

+0

これは '(bool?)Configuration.Element(" LaunchDebugger ")'ではありませんか?つまり、boolをnull可能な型にします。 – Tim

関連する問題