0

良い一日、

ImportFileContext というクラスを含むコードを使用している状況があります。コードは次のようになります。

// One of 5 different types can be passed in
public AddImportData(CustomType ModelData)
{
    // Depending on which 5 different types, the formatted type will change
    FormattedType data = ConvertModelDataToFormattedData(ModelData);
    using (var db = new ImportFileContext())
    {
        // Can this next line be made dynamic?
        db.ImportFormattedData.Add(data);
        db.SaveChanges();
    }
}

基本的に、CustomType は常にメソッドに渡されます。ただし、渡すことができるカスタム タイプは 5 つあります。どの 5 つを渡すことができるかに応じて、データが変更されます。

使用例:

  1. 渡されたカスタム タイプ、データを特定の形式にフォーマットし、その項目を db インスタンスのリストに追加します。
  2. カスタム タイプ 2 が渡され、データを特定の形式にフォーマットし、その項目を db インスタンスのリストに追加します。
  3. カスタム タイプ 3 が渡され、データを特定の形式にフォーマットし、その項目を db インスタンスのリストに追加します。

したがって、私が探しているのは、データ型に応じてリストに項目を追加する方法であり、受け取った型をテストしてから項目を追加するためのいくつかの異なるメソッドを作成する必要はありません。私は戦略パターンを知っており、それを使用できますが、リストにアイテムを追加するのはどうでしょうか?

私は本当に次のようなコードを書くことを避けようとしています:

// One of 5 different types can be passed in
public AddImportData(CustomType ModelData)
{
    // Depending on which 5 different types, the formatted type will change
    FormattedType data = ConvertModelDataToFormattedData(ModelData);
    using (var db = new ImportFileContext())
    {
        if (typeof(ModelData) == "CustomType")
            db.ImportFormattedData.Add(data);
        elseif (typeof(ModelData) == "CustomType1")
            db.ImportCsvData.Add(data);
        elseif (typeof(ModelData) == "CustomType2")
            db.ImportTabDelimetedData.Add(data);
        db.SaveChanges();
    }
}

ティア、

コソン

4

2 に答える 2

0

あなたがダブルディスパッチを探しているように私には聞こえます。これは、Visitor Pattern(基本的にはDavid Masonが詳細に説明したもの)を使用して行うことができます。このパターンでは、データを含むクラスにロジック(訪問)を配置することで、アルゴリズムをデータから切り離します。もちろん、これは機能しますが、アクセスするには、アルゴリズムの外部でクラスを変更する必要があります。

私はこれが複雑だと思っています。静的に型付けされたオブジェクト指向言語は通常、実行時のオーバーロードを行わないため、実際にはそこにあります。幸い、C#4では、dynamicダブルディスパッチをはるかに簡単に実装できるキーワードを導入しました。少なくとも、メソッドのオーバーロードのように見えます。つまり、メソッドのオーバーロードを作成し、動的変数に値を割り当ててから、メソッドを呼び出します。呼び出しを取得するメソッドは、値に基づいて実行時に選択されます。例えば:

public static void AddImportData(CustomType ModelData)
{
    FormattedType data = ConvertModelDataToFormattedData(ModelData);
    using (var db = new ImportFileContext())
    {
        dynamic temp = ModelData;
        ImportData(ModelData, data, db);
    }
}

private static void ImportData(CustomType modelData, FormattedType data, ImportFileContext db)
{
    db.ImportFormattedData.Add(data);
    db.SaveChanges();
}

private static void ImportData(CustomType1 modelData, FormattedType data, ImportFileContext db)
{
    db.ImportCsvData.Add(data);
    db.SaveChanges();
}
private static void ImportData(CustomType1 modelData, FormattedType data, ImportFileContext db)
{
    db.ImportTabDelimetedData.Add(data);
    db.SaveChanges();
}

私のブログの詳細については、http://msmvps.com/blogs/peterritchie/archive/2010/05/24/using-the-dynamic-keyword-in-c-to-improve-object-orientation.aspxをご覧ください。

于 2012-09-19T13:44:50.237 に答える
0

これがあなたのアプリケーションにとってどれほど実現可能かはわかりませんが、いつでも特定の動作を CustomType クラスに追加でき、サブクラスは必要に応じてそれを実装できます。

public class CustomType
{
    public virtual void FormatAndWriteToDB(DataBase db);
}

そして、必要に応じてサブクラスをオーバーライドします

public class CustomType1 : CustomType
{
    public override void FormatAndWriteToDB(DataBase db)
    {
        FormattedType data = ConvertModelDataToFormattedData(ModelData);
        db.ImportCsvData.Add(data);
    }
}

これにより、サンプル メソッドのコードが非常にきれいになります。

public AddImportData(CustomType ModelData)
{
    ModelData.FormatAndWriteToDB(db);
    db.SaveChanges();
}

もちろん、これを少し変更することもできます。たとえば、FormattedType 呼び出しがそれらすべてに共通である場合、それを AddImportData メソッドに残して、それを引数として FormatAndWriteToDB メソッドに渡すことができます。

これの利点は、将来の追加で CustomType の新しいサブクラスを実装するだけで済み、AddImportData を変更する必要がないことです。

于 2012-09-18T22:38:05.960 に答える