2015-06-13 4 views
2

У нас есть базовая база кода .net 4.5 (important) статический класс, который определяет множество константных строковых значений типов объектов (означает значения x.GetType().ToString()), главным образом для использования в коммутаторе заявления.Генерировать константные строки во время компиляции для корпусов коммутаторов

Это особенно плохо, потому что некоторые рефакторинги нарушают все эти инструкции switch, а места, где это используется, настолько обширны, что мы не можем его изменить. Я знаю другие решения, если бы я написал его сейчас, но:

Есть ли какой-либо способ - без изменений инструкции switch - определять константные строки типов для получения типа времени компиляции, поскольку у меня есть вся информация, которая мне нужна при компиляции время.

Я знаю, что операторы switch скомпилированы во время компиляции в таблицу поиска и не оценивают выражение в случаях, но есть ли способ определить значение const однажды во время компиляции? Единственное, о чем я могу думать, это динамически генерировать код перед сборкой. Есть ли другое решение?

ответ

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

Foo и Bar ссылки в nameof типы, если вы переименовать класс любые автоматические средства рефакторинга также заменить тип в 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; 
    } 
} 

UPDATE: nameof не возвращает полное имя с пространством имен только имя типа, где Type.ToString() действительно включает пространство имен. Так что, возможно, это не сработает.


Если вы не можете использовать C# 6 другого вариант заключается в использовании T4 Text templates динамически создавать свои константы для операторов переключения. Единственная проблема с этим - сборка, которая содержит типы, на которые вы ссылаетесь, не может существовать в той же сборке, в которой вы генерируете код.

В следующем коде предполагается, что у вас есть проект DataTrasferObjects в том же решении с классами названный Foo и Bar

<#@ 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 или ниже (FYI, вы можете использовать C# 6 с .NET 4.5, вам нужно только изменить свой компилятор, построив его на один отправленный с VS2015) EDIT: Если я получаю время, и никто другой не ответил, я мог бы попытаться написать еще один ответ, показывающий, как это сделать с тирацией кода T4. –

+0

Я добавил версию .net, было бы хорошо для вопроса, если у вас есть пример с T4 – Sam

Смежные вопросы