2015-06-13 30 views
2

我们在上.NET 4.5(重要)一个静态类的传统的代码库定义的对象类型的许多常量字符串的值(指的x.GetType().ToString()值)主要用于在开关的使用声明。生成在编译时的const字符串用于开关例

这尤其糟糕,因为某些重构打破了所有这些switch语句并在此则采用的是如此巨大,我们不能改变它的地方。我知道其他解决方案,如果我现在写它,但:

是否有任何方法 - 无需更改开关语句 - 定义类型的常量字符串以拾取编译时类型,因为我拥有编译时需要的所有信息时间。

我知道switch语句是在编译时编译成一个查找表,不评估的情况下表达,但有什么办法可以在编译时一次性定义的常量的值?我能想到的唯一事情就是在构建之前动态生成代码。还有其他解决方案吗?

回答

5

C#6被引入特征来解决这个确切的问题,the nameof expression

using System; 

public class Program 
{ 
    public static void Main() 
    { 
     Test(new Foo()); 
     Test(new Bar()); 
    } 

    private static void Test(object x) 
    { 
     switch(x.GetType().ToString()) 
     { 
      case nameof(Foo): 
       Console.WriteLine("Inside Foo's code"); 
      break; 

      case nameof(Bar): 
       Console.WriteLine("Inside Bar's code"); 
      break; 
     } 
    } 
} 

public class Foo {} 
public class Bar {} 

Run Example

FooBarnameof引用的类型,如果重命名类中的任何自动重构工具也将取代类型的nameof

编辑:没赶上“不修改开关”的一部分,你可以用常量字符串也使用它。

const string FooName = nameof(Foo); 
const string BarName = nameof(Bar); 

private static void Test(object x) 
{ 
    switch(x.GetType().ToString()) 
    { 
     case FooName: 
      Console.WriteLine("Inside Foo's code"); 
     break; 

     case BarName: 
      Console.WriteLine("Inside Bar's code"); 
     break; 
    } 
} 

UPDATEnameof不与命名空间只是类型名称,其中Type.ToString()不包括命名空间返回全名。所以也许这不起作用。


如果您不能使用C#6的另一个选择是使用T4 Text templates来动态建立常量的开关语句。与此唯一的问题是组件,它拥有您引用的类型不能存在于您生成的代码所在的相同程序集中。

以下代码假定您有一个名为DataTrasferObjects的项目,命名FooBar

<#@ template debug="false" hostspecific="false" language="C#" #> 
<#@ assembly name="System.Core" #> 
<#@ assembly name="$(SolutionDir)\DataTrasferObjects\bin\Debug\DataTrasferObjects.dll" #> 
<#@ import namespace="System" #> 
<#@ output extension=".cs" #> 

<# 
    Type fooType = typeof(DataTrasferObjects.Foo); 
    Type barType = typeof(DataTrasferObjects.Bar); 
#> 

public static class Names 
{ 
    public const string FooName = "<#= fooType.ToString() #>"; 
    public const string BarName = "<#= barType.ToString() #>"; 
} 

注意,您将需要configure your build server自动重新生成每个生成的代码。

+0

我应该补充说,我卡在.NET 4.5,现在,需要该版本的解决方案。但除了代码生成之外,我没有看到任何其他内容,这是不必要的复杂。我没有看到任何简单的解决方案。 – Sam

+1

是的,我想不出任何适用于C#5或更低版本的非代码生成解决方案(仅供参考,您可以将C#6与.NET 4.5一起使用,您只需通过搭建到发布的版本来更改编译器与VS2015)编辑:如果我得到时间,没有人有回应,我可能会尝试写出另一个答案,显示如何用T4代码genration做到这一点。 –

+0

我添加了一个.net版本,如果你有一个T4的例子,对于这个问题是有好处的 – Sam