C# 条件代码的更好方法
我有一些在C# 条件代码的更好方法,c#,conditional-compilation,C#,Conditional Compilation,我有一些在中定义了大量常量的代码,如果调试#else块;比如: public static class C { #if DEBUG public const string FIELDAAA = "VeryLongDescriptiveFieldName"; public const string FIELDBBB = "AnotherLongDescriptiveFieldName"; public const string FIELDCC
中定义了大量常量的代码,如果调试#else
块;比如:
public static class C
{
#if DEBUG
public const string FIELDAAA = "VeryLongDescriptiveFieldName";
public const string FIELDBBB = "AnotherLongDescriptiveFieldName";
public const string FIELDCCC = "YetAnotherLongFieldName";
// ... many more field definitions
#else
public const string FIELDAAA = "F1";
public const string FIELDBBB = "F2";
// Notice that FIELDCCC is missing - whoever added it to the
// DEBUG block, forgot to add it here.
#endif
}
这些字段用于向第三方服务器生成文本请求-服务器可以采用任何形式的字段名。不过,使用短格式要有效得多,因为每条消息都有大小限制,当请求太大时,必须将其分解为多条消息。每个消息都有成本,因此我们的软件应该在生产中使用短字段名,在开发过程中使用长字段名(用于调试)
此设置有许多源文件,其中大多数在调试块和else块中具有不匹配的常量。由于这些不匹配,由于缺少常量,此应用程序的某些部分无法在发布模式下构建
我试图通过删除巨大的DEBUG
块来解决这个问题,但我需要保留长字段名和短字段名定义,同时确保很难错误地添加新字段名。我还希望将更改的数量保持在最低限度-这是在一个由许多用户使用的大型应用程序中,我不想引入突破性的更改-这些字段在许多地方使用
目前我的想法是:
public static class C
{
public const string FIELDAAA =
#if DEBUG
"VeryLongDescriptiveFieldName";
#else
"F1";
#endif
public const string FIELDBBB =
#if DEBUG
"AnotherLongDescriptiveFieldName";
#else
"F2";
#endif
public const string FIELDCCC =
#if DEBUG
"YetAnotherLongFieldName";
#else
"F3";
#endif
// more constants
}
我不知道我是否有精神障碍,但我想不出比这更好的了。有没有更好的方法可以让我在不太混乱的情况下完成我想做的事情?我在使用#if DEBUG
时没有问题,但这感觉很脏,如果有更干净的解决方案,我更喜欢。是的,有!!。(始终)
我想你可以使用类似工厂模式()的东西,或者使用依赖注入
这样,您应该删除公共静态C类,并且可以使用下面这样的另一个解决方案
通过这种方式,您不必将解决方案仅与#if调试每个字符串绑定,并且使用工厂模式实例化“正确”的常量,这样您就不必担心每个字符串之间的冲突
您的代码将被编译,因为接口要求每个类正确地实现,并且没有集合的属性将不允许程序员更改内容
在使用常数的类中,您可以执行以下操作
public class UsingClass
{
IConstantClass constants;
public UsingClass(){
constants f = new FactoryConstants();
}
}
public class FactoryConstant
{
public FactoryConstant()
{
}
public IConstantClass GetConstant()
{
#if DEBUG
return new ConstantsDebugMode();
#else
return new ConstantsProduction();
#endif
}
}
public interface IConstantClass
{
public string FIELDAAA {get;set;}
public string FIELDBBB {get;set;}
}
public class ConstantsProduction : IConstantClass
{
public string FIELDAAA
{
get { return "ProductionString"; }
set { }
}
public string FIELDBBB
{
get { return "ProductionString2"; }
set { }
}
}
public class ConstantsDebugMode : IConstantClass
{
public string FIELDAAA
{
get { return "ReallyLongStringDebugMode"; }
set { }
}
public string FIELDBBB
{
get { return "ReallyLongStringDebugMode2222"; }
set { }
}
}
注:我没有测试这段代码,但它应该可以工作
依赖注入解决方案将在配置文件中配置系统应如何实现接口类(IConstantClass),因此无需每次实例化Factory类
您可以更改我的代码,并使用正确的解决方案将接口传递给构造函数中的类或属性。您可以从资源文件中读取接口,并使用不同的文件进行调试。据我所知,没有什么比这更好的了。您的解决方案结束了缺少常量的问题,因为如果更改后有人“忘记”add都是constanst,那么他最好改变工作。我想他可能需要变量为
const
。如果不是这样,这是好的。我对你的答案投了赞成票,但我仍在考虑是否应该接受。我在开始时考虑过这种方法,但一开始就放弃了它,因为它需要大量的设置来获得我想要的收益请看“有问题”。在您的回答之后,我对它进行了另一个思考-很明显,它需要比const
方法更多的设置。它确实提供了更多的灵活性,但这些点也可能成为错误点。这肯定会提供使用两组字段定义测试代码的能力(常数是不可能的-这是我最初没有想到的一个方面)。我会再考虑一点-我想看看是否出现了另一种值得考虑的方法。你需要一个初始设置,但之后你就可以“自由行动”,你可以使用一些注入依赖项框架,如Ninject()这样你只需要设置一次界面!我决定使用这种方法-正如我说的,我在提出问题之前考虑过这一点,但由于涉及到大量的设置工作,所以放弃了它。不过,测试两个不同分支的能力非常重要,所以我几次回到这一点上,只是决定咬紧牙关去做吧。