何となく Blog by Jitta
Microsoft .NET 考

目次

Blog 利用状況
  • 投稿数 - 761
  • 記事 - 18
  • コメント - 36167
  • トラックバック - 222
ニュース
  • IE7以前では、表示がおかしい。div の解釈に問題があるようだ。
    IE8の場合は、「互換」表示を OFF にしてください。
  • 検索エンジンで来られた方へ:
    お望みの情報は見つかりましたか? よろしければ、コメント欄にどのような情報を探していたのか、ご記入ください。
It's ME!
  • はなおか じった
  • 世界遺産の近くに住んでます。
  • Microsoft MVP for Visual Developer ASP/ASP.NET 10, 2004 - 9, 2011
広告

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

その他

わんくま同盟

同郷

 

とりあえず、RSS を読み込んで、それぞれの中身を取り出せるようになりました。


まず、基本方針。XML を読み込んで、それが対応しているフォーマットであることを確認します。確認が出来たら、管理したい項目のみ取り出して、管理するのに都合の良いフォーマットに変換します。

フォーマットの確認に、リフレクションを使います。一度使ってみたかったので、使うことにしました(ぉぃ)。


using System.Xml.Linq;
using System.Reflection;
/// <summary>
/// インスタンスを生成します。
/// </summary>
/// <param name="document">解析対象の XML ドキュメント</param>
/// <returns>RSS フィードを解析する SyndicationAnalyzer のインスタンスを返します。</returns>
/// <exception cref="System.NotSupportedException">サポートしていないフォーマットの場合、発生します。</exception>
public static SyndicationAnalyzer CreateInstance(XDocument document) {
    // サポートしている型を列挙
    Type[] supports = new Type[] { typeof(AnalyzerRss10), typeof(AnalyzerRss20), typeof(AnalyzerAtom) };
    foreach (var t in supports) {
        // それぞれの "CanParse" メソッドを検索
        var canParse = t.GetMethod("CanParse", BindingFlags.Static | BindingFlags.Public);
        // メソッドを実行
        bool result = (bool)canParse.Invoke(null, new object[] { document });
        if (result == true) {
            // サポートしているなら、
            // 規定のコンストラクターを取り出す
            var stcConstructor = t.GetConstructor(new Type[] { });
            // 規定のコンストラクターを呼び出して、インスタンスを生成する
            var instance = stcConstructor.Invoke(new object[] { });
            // XDocument 1つを引数に取るコンストラクターを取り出す
            var constructor = t.GetConstructor(new Type[] { typeof(XDocument) });
            // 規定のコンストラクターで生成したインスタンスを元に、引数ありコンストラクターを実行
            constructor.Invoke(instance, new object[] { document });
            // できたインスタンスを返す
            return (SyndicationAnalyzer)instance;
        }
    }
    throw new NotSupportedException();
}

あまり、うれしくないです。AnalyzerRss10AnalyzerRss20AnalyzerAtom は、それぞれ static public bool CanParse(XDocument document) メソッドと、規定のコンストラクタ、XDocument 型を引数にとるコンストラクタが定義されているものとします。この、「定義されているものとする」という縛りがかけられないのが、不便。インターフェイスを定義して・・・そのインターフェイスを実装したクラスを一覧、って出来ないかなぁ?ここに上げたコードだと、新しい型が増えたとき、型情報の一覧に追加するだけで対応できます。if 文または switch - case 文で、分岐を増やすってのが、したくなかった。それだけの理由でリフレクションを使ってみたのだけど、あまりうれしくなかったです。

とにかく、それらがあるもとして、supports に、その型を列挙します。列挙されているものを順に、CanParse メソッドを呼び出して、解析できるかどうかを判断します。このコードは CanParse メソッドがあることを前提にしていますが、当然 canParse の null チェックをしておくべきでしょう。

引数のない規定のコンストラクタは「静的な」コンストラクタなのですが、引数のあるコンストラクタは「動的な」コンストラクタなのだそうです。知らなかった。動的なコンストラクタは、インスタンスがなければ呼び出せません。その為、一度規定のコンストラクタを検索して、呼び出してインスタンスを生成し、そのインスタンスを利用して、引数を持ったコンストラクタを呼び出しています。

AnalyzerRss10AnalyzerRss20AnalyzerAtom の親は、次のように定義します。CanParse メソッドは、静的メソッドなので、ここには定義しません。


abstract class SyndicationAnalyzer
{
    protected XDocument document;
    #region プロパティ
    /// <summary>
    /// ドキュメントが設定され、解析ができる場合は true を返します。
    /// </summary>
    public virtual bool CanUse {
        get { return (this.document != null); }
    }
    /// <summary>
    /// 配信サイトのタイトルを取得します。
    /// </summary>
    public abstract string FeedTitle {
        get;
    }
    /// <summary>
    /// 配信サイトへの URL を取得します。
    /// </summary>
    public abstract Uri FeedLink {
        get;
    }
    /// <summary>
    /// 配信サイトの説明を取得します。
    /// </summary>
    public abstract string FeedDescription {
        get;
    }
    /// <summary>
    /// 配信中のアイテムの個数を取得します。
    /// </summary>
    public abstract int ItemCount {
        get;
    }
    public abstract string ItemTitle(int index);
    public abstract Uri ItemLink(int index);
    public abstract string ItemDescription(int index);
    #endregion
    public static SyndicationAnalyzer CreateInstance(XDocument document) {
        // 省略
    }
}
投稿日時 : 2009年6月29日 21:32
コメント
  • # re: とりあえず、半分(カナ?)
    なちゃ
    Posted @ 2009/06/29 22:39
    うーん普通はインターフェイスを定義してChain of Responsibilityあたりを使うのが一般的な気がします…

    Chain リストは既定プラス構成ファイルで追加可みたいな。
    もしくは設定が面倒なら属性やインターフェイスで自動認識か。

    ところで、
    「引数のない規定のコンストラクタは「静的な」コンストラクタなのですが、…」
    からのくだりがよくわかりません。

    普通にActivator.CreateInstanceに引数渡すのではダメなんでしょうか?
  • # re: とりあえず、半分(カナ?)
    aetos
    Posted @ 2009/06/30 9:53
    アセンブリ内の全部の型を引っ張ってきて(Assembly.GetTypes / GetExportedTypes)、Linq 使ってフィルタ処理(OfType)とか。
  • # re: とりあえず、半分(カナ?)
    Jitta
    Posted @ 2009/07/01 6:54
    なちゃさん、aetosさん、コメントありがとうございます。

    インターフェースを用意していたのですが、インターフェースで用意されたメソッドを使うにはインスタンスがなければなりません。その、判定のために使う、アナライザーとしては無効なインスタンスを用意するというのが、なんとなく、イヤだったのです。

    Activator は、リモート処理の下にありました。リフレクションから検索したので、見つけられませんでした。リモート処理も、一回やっとかなきゃだわ。

    > Assembly.GetTypes
    おお!成るほど。全部リストしてから篩にかければいけるか。
タイトル
名前
Url
コメント