0

これは奇妙な要求のように思えますが、それはありがたいのですが、状況は次のとおりです。

少数のファイルの読み取りに依存するプログラムがあります。これらのファイルの名前は次のようになりますfoo_bar_BAZ.txt。 BAZ はプロジェクトの名前で、実行時まで不明です。ただし、プログラムの実行全体で変更されることはありません。

すべてのファイル名を格納する文字列の列挙リストが必要です。これまでのところ、次のようなシール クラスを使用してきました。

public sealed class SQLFile
{
    private readonly String name;
    private readonly String value;

    public static readonly SQLFile CrByAuthors = new SQLFile("Changes_CR_By_Authors_%project_name%.txt", "CrByAuthors");
    public static readonly SQLFile DocumentCrMetrics = new SQLFile("Changes_Document_CR_Output_%project_name%.txt", "DocumentCrMetrics");
    [...]


    private SQLFile(String value, String name)
    {
        this.name = name;
        this.value = value;
    }

    public String ToString(string projectName)
    {
        return this.value.Replace("%project_name%", projectName);
    }
}

ご覧のとおり、これは、ファイル名が実行時の最初から最後まで実際には一定であるにもかかわらず、ファイル名にアクセスするたびにプロジェクト名変数を提供することに依存しています。

この状況を処理するよりエレガントな方法はありますか?

4

3 に答える 3

0

に静的プロパティを追加しますSQLFile

public sealed class SQLFile
{  
    //...
    private static string sProjectName;
    public static string ProjectName
    {
        get
        {
            return sProjectName;
        }
        set
        {
            //optionally, you could prevent updates with:
            //if (string.IsNullOrEmpty(sProjectName))
            sProjectName= value;
            //else throw Exception("ProjectName was already set!");
        }
}
于 2013-09-17T08:57:14.597 に答える
0

[編集 - コードを読むのが少し速すぎたので、これが実際の意味です:]

(不適切な名前の IMHO) メソッドの目的はToString、特定のプロジェクト名に対応するファイルの名前を返すことです。別のクラスに属する責任かもしれませんが、それは何も悪いことではありません。

たとえば、コードをリファクタリングして、その意図をより明確に表現できます。

interface ISqlFileNameProvider 
{
     string SqlFilename { get; }
}

次に、単純な (「貧乏人の」) 実装を行います。

public class SimpleSqlFileNameProvider : ISqlFileNameProvider
{
    private readonly string _filename;
    public SimpleSqlFileNameProvider(string filename)
    {
        _filename = filename;
    }

    public string SqlFilename
    {
        get { return _filename; }
    }
}

そして、ここから特殊な実装を導き出します。

public class TemplateSqlFileNameProvider : SimpleSqlFileNameProvider
{
    public TemplateSqlFileNameProvider(string template, string projectName)
        : base(template.Replace("%project_name%", projectName))
    { }
}

public class CrByAuthorsFileNameProvider : TemplateSqlFileNameProvider
{
    public CrByAuthorsFileNameProvider(string projectName)
        : base("Changes_CR_By_Authors_%project_name%.txt", projectName)
    { }
}

public class DocumentCrMetricsFileNameProvider : TemplateSqlFileNameProvider
{
    public DocumentCrMetricsFileNameProvider(string projectName)
        : base("Changes_Document_CR_Output_%project_name%.txt", projectName)
    { }
}

まず、がこれらの特殊化されたクラスのprojectNameのパラメータのままであることに注意してください。constructorここにはグローバルはありません。次に、プロジェクトに配管コードを少し追加したとしても、テストを簡単にするためにクラスを分離する方が簡単です: のモック実装を作成し、ISqlFileNameProvider好きなものを返して、実際に書き込むことなく残りの機能をテストできます。データファイル。

グローバル プロパティを使用しないことをお勧めします。プロジェクト名をコンストラクターのパラメーターとして指定できるということは、クラスが意図したとおりに動作することを簡単にテストできることを意味します。また、プロジェクトの存続期間中に変更されると考えていても、実行時にプロジェクト名を一時的に切り替える必要があるシナリオに簡単に遭遇する可能性があります。グローバルを使用しないことをお勧めします。

于 2013-09-17T09:02:22.023 に答える
0

ProjectName簡単な解決策は、プロパティを持つ静的クラスを持つことです。このプロパティの値は、アプリケーションの起動時に設定されます。その後、クラスはそのプロパティを使用できます。

于 2013-09-17T08:51:16.370 に答える