2014-09-04 2 views
1

В C можно написать функцию макроса, которая заменяет вход ввода как строку.Директива стиля c в C#, которая позволяет использовать одно выражение дважды #define x (k) {#k, k}

#define x(k) {#k, k} 

'(4)' будет генерировать '{ "4", 4}'

У меня есть USECASE в C#, где я хочу передать входной сигнал, как это к испытанию блока.

private void AssertInt64Expression(Int64 i, string str) 
{ 
    Assert.AreEqual(i, MathFactory.make(str)); 
} 

[Test] 
public void ParseBasic() 
{ 
    AssertInt64Expression(4, "4"); 
    AssertInt64Expression(2+3, "2+3"); 
    AssertInt64Expression(7-11, "7-11"); 
    AssertInt64Expression(7-11 *2, "7-11 *2"); 
    AssertInt64Expression(7 - 11 * 2, "7 - 11 * 2"); 
} 

Я по существу повторяет информацию (включая пробелы) здесь, как я могу использовать что-то вроде макроса с стиле, чтобы решить эту проблему в C#?


редактировать:

по существу я хотел бы написать:

private void AssertInt64Expression(GeneratorMagic magic) 
{ 
    Assert.AreEqual(magic.ToCode(), MathFactory.make(magic.ToString())); 
} 

[Test] 
public void ParseBasic() 
{ 
    AssertInt64Expression(<#7 - 11 * 2#>); 
} 

Я знаю, что это не будет компилироваться.


редактировать:

Я добавил фрагмент кода в ответ, чтобы проиллюстрировать то, что я ищу. Однако этот фрагмент работает очень медленно, так как мне нужно его реорганизовать мои модульные тесты в более чистый код с меньшим количеством повторений. Мне нужно, чтобы фрагмент работал быстрее. Фрагмент по существу обеспечивает magic из предыдущего редактирования как KeyValuePair.

+1

Не уверен, что на самом деле вы пытаетесь сделать, но [Генерация кода и T4 текста Шаблоны] (http://msdn.microsoft.com/en-us/library/bb126445.aspx) может помочь. –

+1

В соответствии с вашим [комментарием] (http://stackoverflow.com/questions/709463/c-sharp-macro-definitions-in-preprocessor#comment40110288_709475) вы нашли вопрос [Определения макросов C# в препроцессоре] (http: //stackoverflow.com/questions/709463/c-sharp-macro-definitions-in-preprocessor). На ваш вопрос не ответил (ответ «Нет»)? – CodeCaster

+0

@CodeCaster Я нашел ответ, и я не ищу препроцессор. У меня есть usecase, где я хочу писать somethign один раз, а не дважды, и я смотрю, как это делается на C#. Кажется маловероятным, что это невозможно. – Johannes

ответ

0

Следующий фрагмент делает то, что мне нужно, но, похоже, работает ужасно медленно.

private KeyValuePair<String, Int64> GenerateCodeInt64(String mathKey) 
    { 
     string codeNamespace = "MathTestCalculator"; 
     string codeClassName = "MathTestCalculator"; 
     string codeMethodName = "Value"; 

     Int64 I64Value = 0; 
     StringBuilder codeBuilder = new StringBuilder(); 

     codeBuilder 
      .Append("using System;\n") 
      .Append("namespace ").Append(codeNamespace).Append(" {\n") 
      .Append("class ").Append(codeClassName).Append("{\n") 
      .Append("public Int64 ").Append(codeMethodName).Append("(){\n") 
      .Append("return (Int64)(").Append(mathKey).Append(");}}}\n"); 

     CompilerParameters cp = new CompilerParameters(); 
     cp.GenerateExecutable = false; 
     cp.GenerateInMemory = true; 

     CompilerResults results = CodeDomProvider 
      .CreateProvider("CSharp") 
      .CompileAssemblyFromSource(cp, codeBuilder.ToString()); 

     if (results.Errors.Count > 0) 
     { 
      StringBuilder error = new StringBuilder(); 
      error.Append("Unable to evaluate: '").Append(mathKey).Append("'\n"); 
      foreach (CompilerError CompErr in results.Errors) 
      { 
       error 
        .Append("Line number ").Append(CompErr.Line) 
        .Append(", Error Number: ").Append(CompErr.ErrorNumber) 
        .Append(", '").Append(CompErr.ErrorText).Append(";\n"); 
      } 
      throw new Exception(error.ToString()); 
     } 
     else 
     { 
      Type calcType = results.CompiledAssembly.GetType(codeNamespace + "." + codeClassName); 
      object o = Activator.CreateInstance(calcType); 
      I64Value = (Int64)calcType.GetMethod(codeMethodName).Invoke(o, null); 
     } 
     return new KeyValuePair<string, long>(mathKey, I64Value); 
    } 
0

Вы можете использовать собственный класс номеров с перегруженными операторами.

static void Main(string[] args) 
{ 
    Console.WriteLine((Number)1 + 5); 
    Console.WriteLine((int)((Number)1 + 5 + 6)); 

} 

public class Number 
{ 
    private string _representation = ""; 
    private int _number = 0; 

    private Number(int n) 
    { 
     _number = n; 
     _representation = n.ToString(); 
    } 

    public Number Plus(int n) 
    { 
     _representation += " + " + n; 
     _number += n; 
     return this; 
    } 

    public static Number operator +(Number value1, int value2) 
    { 
     return value1.Plus(value2); 
    } 

    public static explicit operator Number(int val) 
    { 
     return new Number(val); 
    } 

    public static explicit operator int(Number num) 
    { 
     return num._number; 
    } 

    public override string ToString() 
    { 
     return _representation; 
    } 
} 
+0

было бы направлять ввод строки в мой математический генератор и сравнить его результат с ожидаемым результатом, который по сути является тем, что C# будет вычислять без генератора. Ваш пример будет работать для ограниченного набора и завершится неудачно, если я захочу проверить влияние пробела. «1 + 1» отличается от «1 + 1». – Johannes

+0

Вы можете добавить метод к классу Number для генерации всех возможных конфигураций белого пространства для заданного ввода. – brz

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