2012-04-03 9 views
0

コンテンツパイプライン拡張で工場と同様のパターンを使用する必要があります。私は、辞書の種類で始まる:XNAコンテンツパイプライン内からサービスにアクセスする

public partial class TestContent 
{ 
    // Test type 
    public string title; 

    // Once test if true 
    public bool once; 

    // Parameters 
    public Dictionary<string, object> args; 

    public TestContent() 
    { 
     title = string.Empty; 
     args = new Dictionary<string, object>(); 
    } 

    public TestContent(XElement xe) 
    { 
     title = xe.Name.ToString(); 
     args = new Dictionary<string, object>(); 
     xe.ParseAttribute("once", once); 
    } 
} 

XElement.ParseAttributeは1想像のとおりに機能拡張メソッドです:

public delegate T Mapper<T>(MapFactory<T> mf, XElement d); 

public class MapFactory<T> 
{ 
    Dictionary<string, Mapper<T>> map = new Dictionary<string, Mapper<T>>(); 

    public void Add(string s, Mapper<T> m) 
    { 
     map.Add(s, m); 
    } 

    public T Get(XElement xe) 
    { 
     if (xe == null) throw new ArgumentNullException(
      "Invalid document"); 
     var key = xe.Name.ToString(); 
     if (!map.ContainsKey(key)) throw new ArgumentException(
      key + " is not a valid key."); 
     return map[key](this, xe); 
    } 

    public IEnumerable<T> GetAll(XElement xe) 
    { 
     if (xe == null) throw new ArgumentNullException(
      "Invalid document"); 
     foreach (var e in xe.Elements()) 
     { 
      var val = e.Name.ToString(); 
      if (map.ContainsKey(val)) 
       yield return map[val](this, e); 
     } 
    } 
} 

は、ここで私は保存するオブジェクトの一種です。成功すれば真であるブール値を返します。

問題には、さまざまな種類のテストがあり、それぞれが特定のテストに固有の方法でオブジェクトに値を設定します。要素名は、MapFactoryの辞書のキーです。このタイプのテストは、非定型ですが、私の問題を示しています。

public class LogicTest : TestBase 
{ 
    string opkey; 
    List<TestBase> items; 

    public override bool Test(BehaviorArgs args) 
    { 
     if (items == null) return false; 
     if (items.Count == 0) return false; 
     bool result = items[0].Test(args); 
     for (int i = 1; i < items.Count; i++) 
     { 
      bool other = items[i].Test(args); 
      switch (opkey) 
      { 
       case "And": 
        result &= other; 
        if (!result) return false; 
        break; 
       case "Or": 
        result |= other; 
        if (result) return true; 
        break; 
       case "Xor": 
        result ^= other; 
        break; 
       case "Nand": 
        result = !(result & other); 
        break; 
       case "Nor": 
        result = !(result | other); 
        break; 
       default: 
        result = false; 
        break; 
      } 
     } 
     return result; 
    } 

    public static TestContent Build(MapFactory<TestContent> mf, XElement xe) 
    { 
     var result = new TestContent(xe); 
     string key = "Or"; 
     xe.GetAttribute("op", key); 
     result.args.Add("key", key); 
     var names = mf.GetAll(xe).ToList(); 
     if (names.Count() < 2) throw new ArgumentException(
       "LogicTest requires at least two entries."); 
     result.args.Add("items", names); 
     return result; 
    } 
} 

私の実際のコードは、工場は、2つの辞書、書き込み、実際のゲームオブジェクトを作成するために、リーダによって使用される別のコンテンツタイプにXElementオブジェクトを回すつを有する、より複雑です。

文字列を代理人にマップするため、これらのファクトリをコードで構築する必要があります。私はこれらの工場のいくつかを含むサービスを持っています。ミッションは、これらのファクトリクラスをコンテンツプロセッサで使用できるようにすることです。プロセッサ自体やパラメータとして使用するコンテキストは、IServiceProviderまたは同等のものを接続するための既知のフックを持っていません。

アイデア?

答えて

0

基本的な要求に応じてデータ構造を作成する必要がありました。第三者(この場合はXNA Game Studio)からの基本クラスにアクセスする必要はありません。私は静的に知っているこれを行うための唯一の方法があります。

/// <summary> 
/// Turns an imported XElement into a TestContent used for a LogicTest 
/// </summary> 
[ContentProcessor(DisplayName = "LogicProcessor")] 
public class LogicProcessor : ContentProcessor<XElement, TestContent> 
{ 
    public override TestContent Process(XElement input, ContentProcessorContext context) 
    { 
     var result = new TestContent(input); 
     string key = "Or"; 
     input.GetAttribute("op", key); 
     result.args.Add("key", key); 
     var items = TestMap.Map.Collect(input, context); 
     if (items.Count() < 2) throw new ArgumentNullException(
       "LogicProcessor requires at least two items."); 
     result.args.Add("items", items); 
     return result; 
    } 
} 

参照したり、そのような基本的な静的クラスを生成しますTestMap.Collectを呼び出してクラスにアクセスしようとすると:

public class TestMap : Dictionary<string, string> 
{ 
    private static readonly TestMap map = new TestMap(); 

    private TestMap() 
    { 
     Add("Logic", "LogicProcessor"); 
     Add("Sequence", "SequenceProcessor"); 
     Add("Key", "KeyProcessor"); 
     Add("KeyVector", "KeyVectorProcessor"); 
     Add("Mouse", "MouseProcessor"); 
     Add("Pad", "PadProcessor"); 
     Add("PadVector", "PadVectorProcessor"); 
    } 

    public static TestMap Map 
    { 
     get { return map; } 
    } 

    public IEnumerable<TestContent> Collect(XElement xe, ContentProcessorContext cpc) 
    { 
     foreach(var e in xe.Elements().Where(e => ContainsKey(e.Name.ToString()))) 
     { 
      yield return cpc.Convert<XElement, TestContent>(
       e, this[e.Name.ToString()]); 
     } 
    } 
} 

私はTestBaseの種類ごとにコンテンツプロセッサを、このさらなるステップ取り、作成しました必要に応じて。私は基本的にコードをLogicTest.Buildからプロセッサに移動しました。私はまた、プロセッサに必要な検証を実行します。

これらのクラスを読んだとき、私はContentServiceを手伝ってくれます。

関連する問題