c# - ジェネリックメソッドを一種のテンプレートパターンとして使用できますか?

c# .net generics design-patterns

こんにちは、ジェネリックメソッドが私の問題を解決する正しい方法であるかどうかはわかりません。 XMLファイルを解析して、そこからアイテムを読み取る必要があります。アイテムには、orderLines、メモ、添付ファイルなどがあります。これらのアイテムを取得するための基本的な手順はすべて同じです。これらのアイテムのリストを作成する1つのメソッドを作成し、特定のメソッドを呼び出してアイテムを読み取るにはどうすればよいですか?

    public override IList<T> GetItems<T>(XPathNavigator currentOrder) where T : ISortableByLineNumber, new ()
    {
        var itemList = new List<T>();
        var itemXmlNodes = currentOrder.Select(OrderXPath);
        if (itemXmlNodes == null)
            throw new Exception("");
        var lineNumber = 1;
        foreach (XPathNavigator itemXmlNode in itemXmlNodes)
        {
            var item = new T();
            item = ReadItem(itemXmlNode, lineNumber++, item);
            itemList.Add(item);
            Logger.Debug(string.Format("Added item {0}", item));
        }
        return itemList;
    }


私は、ReadItemメソッドでこれを行うことができると思いました。読み取るアイテムの種類ごとにオーバーロードを作成します。

    private ISortableByLineNumber ReadItem(XPathNavigator itemXmlNode, int i, OrderLine item)
    {
        // specific code to read a orderLine
    }

    private ISortableByLineNumber ReadItem(XPathNavigator itemXmlNode, int i, Note item)
    {
        // specific code to read a note
    }


しかし、これをコンパイルしようとすると、「 'XmlOrderParser.XmlOrders.Prs3XmlFileWithOrders.ReadItem(System.Xml.XPath.XPathNavigator、int、XmlOrderParser.Entities.OrderLine)のオーバーロードされたメソッドの最適な一致」にいくつかの無効な引数があります。問題は、コンパイラーがTをOrderLineまたはNoteにキャストする方法を知らないことです。
答え
.NET 4を使用している場合、1つだけ変更することで新しいdynamicタイプを利用できます。

dynamic item = new T(); // instead of var item = new T();


itemdynamicになったため、ランタイムはアイテムの実際のタイプに基づいて自動的にオーバーロードを解決します。
Tがオーバーロードが存在しないタイプである場合、ランタイム例外が発生することに注意してください。



次のスニペットは問題を示しています(LINQPadに貼り付け、言語として「C#プログラム」を選択します)。

void Main()
{
    Method<Class1>(); // Outputs Class1
    Method<Class2>(); // Outputs Class2
    Method<Class2b>(); // Outputs Class2, because it falls back to the base type
    Method<Class3>(); // Throws exception
}

void Method<T>() where T : new()
{
    dynamic c = new T();
    Method(c);
}

void Method(Class1 c) { Console.WriteLine("Class1"); }
void Method(Class2 c) { Console.WriteLine("Class2"); }

class Class1 {}
class Class2 {}
class Class2b : Class2 {}
class Class3 {}
関連記事

c# - セキュリティキーを使用した招待

c# - 2つのxmlノードを比較する方法は?

c# - UDPを使用したアプリケーション間の双方向通信

c# - WPFビデオプレーヤーでフレームにアクセスする

c# - ASP.NET MVC3、Razor-JavaScriptでのViewBagまたはURL変数の使用

c# - Winformsはビットマップ画像をクリアしますか?

c# - 待っているラムダ

c# - ウィンドウのPNGスクリーンショットを撮るが、空気透過性は維持する

c# - 非ブロッキングブロックからブロッキングコードを呼び出すときの制御の流れを理解していますか?

c# - IronPythonでILMergeを使用する