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

[编辑 - 我读代码有点太快了,所以这就是我真正的意思:]

(恕我直言,名字不好)方法的目的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 回答