1

コードの入力を節約するために、別のクラスから返されたメンバーにテキストを追加する方法を見つけたいと思います。それはおそらく意味がないので、例です。私が取り組んでいるのは、テストデータを管理するためのクラスです。

public class TestFiles
{
    private const string File1RelativePath = @"TestData\File1.xml";
    private const string File2RelativePath = @"TestData\File2.xml";

    private static string RootPath()
    {
        // don't know the deployment location until runtime 
        return Some_DirectoryName_Determined_At_Run_Time_Returned_BySomeOtherModule();
    }

    public static string File1
    {
        get { return Path.Combine(RootPath() + File1RelativePath); }
    }

    public static string File2
    {
        get { return Path.Combine(RootPath() + File2RelativePath); }
    }
}   

このクラスは私が望んでいることを正確に実行し、次のように簡単に呼び出すことができます。

String FileToUseForTest = TestFiles.File1;

問題は私が怠惰であるということです、そして私がさらにファイルを追加するとき、私は2つの場所でそれをしなければなりません:定数文字列とgetプロパティ。ゲッターに文字列リテラルを含めることもできますが、それでも各ゲッターでPath.Combine(RootPath()...を呼び出す必要があります。これは私にとっては非常に手間がかかります。

したがって、以下に示す理由で機能しない別のアプローチを試してください。

public class TestFiles
{
    public class FileRelativePaths
    {
        private const string File1RelativePath = @"TestData\File1.xml";
        private const string File2RelativePath = @"TestData\File2.xml";
    }

    private static FileRelativePaths relPaths = new RulePackages();

    FileRelativePaths FullPaths
    {
        get { return relPaths; }
    }

    private static string RootPath()
    {
        // No longer called, but somehow need to find a way to append to paths returned in FullPaths
        return Some_DirectoryName_Determined_At_Run_Time_Returned_BySomeOtherModule();
    }
}   

これはほぼ機能します。強い型付けを取得し、発信者は次の方法でファイルを取得できます。

String FileToUseForTest = TestFiles.FullPaths.File1;

しかし、問題は、これが相対パスのみを提供していることです。ここで、返された文字列にコードを追加したかったのです(RootPath()メソッドを使用)。

それで、強い型付けを持ち、コードの長さを最小限に抑えながら、これを機能させる方法はありますか?私は上記の最初のアプローチを使用することに少し辞任しましたが、創造的な解決策があるかどうか尋ねたいと思いました。

4

6 に答える 6

1

ルート パスを含む暗黙のキャストを行うために、演算子のオーバーロードを使用するのはどうですか?

class Program
{
    static void Main(string[] args)
    {
        RelativePath relative = @"Relative\Path\One";

        Console.WriteLine(relative.Path);
        string path = relative;
        Console.WriteLine(path);

        Console.ReadLine();
    }
}

public class RelativePath
{

    public static string RootPath()
    {
        return @"C:\MyRootPath\";
    }

    public string Path
    {
        get;
        protected set;
    }

    public RelativePath(string relativePath)
    {
        this.Path = relativePath;
    }

    public static implicit operator RelativePath(string path)
    {
        return new RelativePath(path);
    }

    public static implicit operator string(RelativePath relativePath)
    {
        return System.IO.Path.Combine(RootPath(), relativePath.Path);
    }

}
于 2012-04-09T18:37:56.380 に答える
1

個人的には、2 か所を変更する必要があることを辞任します。これは私があまり好きではない代替案ですが、私が理解しているようにあなたの基準を満たしています:

public enum XmlFile{
    File1,
    File2
};

public static class TestFiles{
    const string RelativeDirectory = @"TestData";
    const string XmlExtension = @"xml";
    static string RootPath {
        get
        {
            return Some_DirectoryName_Determined_At_Run_Time_Returned_BySomeOtherModule();
        }
    }

    //overload as necessary for other extensions or pass it as an additional parameter
    public static string GetFullPath(XmlFile file){
        return string.Format(@"{0}{1}\{2}.{3}", RootPath, RelativeDirectory, file, XmlExtension);
    }
}

このスニペットには、いくつかの残念な副作用があります。

  • 規則を使用して、列挙型メンバーをファイル名に関連付けます
  • enum の ToString() に依存
  • RelativeDirectory が常に同じであると仮定します (そうでない場合は、対応するためにさらに規則が必要になります)
于 2012-04-09T19:09:00.343 に答える
0

このようなものはどうですか?テストされていないコードが先にあることに注意してください。

public enum TestFileType {
    File1,
    File2,
}

public class TestFiles
{
    private static Dictionary<TestFileType, String> filePaths = new Dictionary<TestFileType, String> 
        { 
            { TestFileType.File1, @"TestData\File1.xml" }, 
            { TestFileType.File2, @"TestData\File2.xml" } 
        };

    public static String GetFile(TestFileType fType) {
        return Path.Combine(RootPath() + filePaths[fType]);
    }
}

// Use thus: 
TestFiles.GetFile(TestFileType.File1);
于 2012-04-09T18:39:24.960 に答える
0

いくつかのことが思い浮かびます。まず、個別のプロパティを持つ代わりに、列挙、辞書、および単一の "get" 関数を持つことができます。

public enum TestFile { File1, File2 };

public class TestFiles {

  private static Dictionary<TestFile,string> _testFiles = new Dictionary<TestFile,string> {
    { TestFile.File1, @"TestData\File1.xml" },
    { TestFile.File2, @"TestData\File2.xml" },
  };

  public string RootPath() {
    return @"C:\";
  }

  public string Get( TestFile tf ) {
    return Path.Combine( RootPath(), _testFiles[tf] );
  }

  // even better, you can override the array indexing operator
  public string this[TestFile tf] {
    get { 
        return Path.Combine( RootPath(), _testFiles[tf] );
    }
  }
}

繰り返しコードを抽象化したい場合はPath.Combine、いつでもヘルパー クラスを使用できますが、ここで多くのことを得ることができるかどうかは疑わしいです。それでも、読みやすさが向上する可能性があります。

public static class TestFileHelper {
    public static string RootPath() {
      return @"C:\";
    }

    public static string RootedAtTestDir( this string s ) {
        return Path.Combine( RootPath(), s );
    }
}

次に、どこでも呼び出す代わりに、次のPath.Combineように書くことができます。

return _testFiles[tf].RootedAtTestDir();
于 2012-04-09T18:41:35.150 に答える
0

これは、実際には拡張機能の良いユースケースかもしれません。これをテスト アセンブリ/ファイルに追加して、必要な場所で参照するだけです。

public static class TestExtensions
{
    private static string RootPath = @"C:\Some\Root\Path";
    public static string AddRoot(this string path)
    {
        return Path.Combine(RootPath, path);
    }
}

別のオプションは、定義したい「ルート」が複数ある場合に辞書を使用することです。この方法では、パスとルート キーの 2 つを指定します。

public static class TestExtensions
{
    private static Dictionary<string, string> RootPaths = new Dictionary<string, string>();

    public static void RegisterRoot(string rootKey, string rootPath)
    {
        // Omitted null checking, but should do it.
        RootPaths[rootKey] = rootPath;
    }

    public static string AddRoot(this string path, string rootKey)
    {
        return Path.Combine(RootPaths[rootKey], path);
    }
}

使い方は簡単です。任意の文字列インスタンスで拡張メソッドを呼び出すだけです。いいえ:

// Single root version.
TestFiles.File1.AddRoot(); 
// String literal...
@"Relative\Path\File.xml".AddRoot();
// Dictionary root version.
TestExtensions.RegisterRoot("testRoot", @"C:\Some\Test\Directory");
TestFiles.File1.AddRoot("testRoot"); 

それが役立つことを願っています。

于 2012-04-09T19:12:57.270 に答える