C# 在访问属性之前执行公共代码的模式
严格来说,为了节省代码中的键入,我想找到一些方法将文本附加到另一个类返回的成员。这可能没有道理,举个例子吧。我正在使用的是一个用于管理测试数据的类:C# 在访问属性之前执行公共代码的模式,c#,C#,严格来说,为了节省代码中的键入,我想找到一些方法将文本附加到另一个类返回的成员。这可能没有道理,举个例子吧。我正在使用的是一个用于管理测试数据的类: public class TestFiles { private const string File1RelativePath = @"TestData\File1.xml"; private const string File2RelativePath = @"TestData\File2.xml"; private s
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;
问题是我很懒,当我添加更多的文件时,我必须在两个地方进行:常量字符串和get属性。也许我可以在getter中包含字符串文字,但即使这样,我也必须在每个getter中调用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()方法)
那么,有没有什么方法可以让它工作起来,同时仍然具有强大的键入功能并将代码长度保持在最小值?我有点不愿意使用上面的第一种方法,但我想问一下是否有创造性的解决方案。只需使用一个小的辅助函数
private static string fixupPath (string dir)
{
return Path.Combine(RootPath() + dir);
}
public static string File1
{
get { return fixupPath(File1RelativePath); }
}
如果您真的想优化击键而不是可维护性,请使用较短的函数名。使用运算符重载执行包含根路径的隐式强制转换如何
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);
}
}
类似这样的情况如何?请注意,未经测试的代码:
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);
public enum TestFileType{
文件1,
文件2,
}
公共类测试文件
{
私有静态字典filepath=新字典
{
{TestFileType.File1,@“TestData\File1.xml”},
{TestFileType.File2,@“TestData\File2.xml”}
};
公共静态字符串GetFile(TestFileType fType){
返回Path.Combine(RootPath()+文件路径[fType]);
}
}
//因此使用:
GetFile(TestFileType.File1);
首先,您可以有一个枚举、一个字典和一个“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.combined
随处可见,只需编写:
return _testFiles[tf].RootedAtTestDir();
就我个人而言,我不得不在两个地方改变它。这里有一个我不太喜欢的替代方案,但我理解它满足您的标准:
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);
}
}
这个片段有一些不幸的副作用:
- 使用约定将枚举成员与文件名关联
- 依赖于枚举的ToString()
- 假设RelativeDirectory总是相同的(否则,您将需要进一步的约定来适应)
public static class TestExtensions
{
private static string RootPath = @"C:\Some\Root\Path";
public static string AddRoot(this string path)
{
return Path.Combine(RootPath, path);
}
}
另一种选择是也使用字典,以防您有多个要定义的“根”,这样您可以指定两件事:路径和根键
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);
}
}
希望这有帮助。将文件路径放入数组或字典中。调用一个函数,传递测试集的编号/名称。让该函数修复它。如果文件很多,代码生成可能会有好处。例如,许多回复都采用这种方法,我将把它标记为讨论副作用的答案。T汉克斯!
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");