Используя отражение для генерала кода?

public static string ToRelativeDate(DateTime input)
{
    TimeSpan oSpan = DateTime.Now.Subtract(input);
    double TotalMinutes = oSpan.TotalMinutes;
    string Suffix = " ago";

    if (TotalMinutes < 0.0)
    {
        TotalMinutes = Math.Abs(TotalMinutes);
        Suffix = " from now";
    }

    var aValue = new SortedList>();
    aValue.Add(0.75, () => "less than a minute");
    aValue.Add(1.5, () => "about a minute");
    aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes)));
    aValue.Add(90, () => "about an hour");
    aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24
    aValue.Add(2880, () => "a day"); // 60 * 48
    aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30
    aValue.Add(86400, () => "about a month"); // 60 * 24 * 60
    aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365 
    aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2
    aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));

    return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix;
}

http://refactormycode.com/codes/493-twitter-esque-relative-dates

версия C# 6:

static readonly SortedList> offsets = 
   new SortedList>
{
    { 0.75, _ => "less than a minute"},
    { 1.5, _ => "about a minute"},
    { 45, x => $"{x.TotalMinutes:F0} minutes"},
    { 90, x => "about an hour"},
    { 1440, x => $"about {x.TotalHours:F0} hours"},
    { 2880, x => "a day"},
    { 43200, x => $"{x.TotalDays:F0} days"},
    { 86400, x => "about a month"},
    { 525600, x => $"{x.TotalDays / 30:F0} months"},
    { 1051200, x => "about a year"},
    { double.MaxValue, x => $"{x.TotalDays / 365:F0} years"}
};

public static string ToRelativeDate(this DateTime input)
{
    TimeSpan x = DateTime.Now - input;
    string Suffix = x.TotalMinutes > 0 ? " ago" : " from now";
    x = new TimeSpan(Math.Abs(x.Ticks));
    return offsets.First(n => x.TotalMinutes < n.Key).Value(x) + Suffix;
}
6
задан Paul 23 July 2009 в 12:49
поделиться

5 ответов

Рассматривали ли вы использование шаблонов T4 для генерации кода? Похоже, сейчас он получает гораздо больше внимания и внимания, а также больше поддержки в VS2010.

Этот учебник кажется ориентированным на базу данных, но может дать вам некоторые подсказки: http://www.olegsych.com/2008/09/ t4-tutorial-creatating-your-first-code-generator / кроме того, здесь были недавние Hanselminutes на T4: http://www.hanselminutes.com/default.aspx?showID=170 .

Изменить: Еще одно замечательное место - это тег T4 здесь, в StackOverflow: https://stackoverflow.com/questions/tagged/t4

РЕДАКТИРОВАТЬ: (Автор вопроса, новые разработки)

Как из VS2012, T4 теперь поддерживает отражение над активным проектом за один шаг. Это означает, что вы можете внести изменения в свой код, и скомпилированный вывод шаблона T4 будет отражать новейшую версию, не требуя от вас выполнения второго шага отражения / сборки. Имея эту возможность, я помечаю это как принятый ответ.

2
ответ дан 17 December 2019 в 04:50
поделиться

Довольно непонятно, что вы делаете, но что действительно кажется очевидным, так это то, что у вас есть некоторый базовый код, и, основываясь на некоторых его свойствах, вы хотите сгенерировать больше кода.

Итак ключевой вопрос здесь заключается в том, с учетом базового кода, как вы извлекаете интересные свойства и как генерируете код из этих свойств?

Отражение - это способ извлекать свойства запущенного кода (ну, по крайней мере, загруженного) в та же среда выполнения, что и пользовательский код отражения. Проблема с отражением заключается в том, что оно предоставляет только очень ограниченный набор свойств, обычно списки классов, методов или, возможно, имена аргументов. ЕСЛИ вся генерация кода, которую вы хотите сделать, может быть выполнено только с этим, что ж, тогда отражение кажется прекрасным. Но если вам нужны более подробные свойства кода, отражение не поможет.

Фактически, единственный артефакт, из которого могут быть извлечены действительно произвольные свойства кода, - это исходный код в виде символьной строки (как еще вы могли бы ответить, является ли количество символов между оператором добавления и T в середине имени переменной простым числом? ). На практике свойства, которые можно получить из символьных строк, обычно не очень полезны (см. Пример, который я только что привел :).

Ребята-компиляторы потратили последние 60 лет, выясняя, как извлекать интересные свойства программы, и вы были бы полным идиотом, если бы проигнорировали то, что они узнали за эти полвека.

Они остановились на ряде вопросов. относительно стандартные «структуры данных компилятора»: абстрактные синтаксические деревья (AST), таблицы символов (ST), графы потока управления (CFG), факты потока данных (DFF), троек программ, анализ понтеров и т. д. является ли количество символов между оператором сложения и буквой T в середине имени переменной простым числом?). На практике свойства, которые можно получить из символьных строк, обычно не очень полезны (см. Пример, который я только что привел :).

Ребята-компиляторы потратили последние 60 лет, выясняя, как извлекать интересные свойства программы, и вы были бы полным идиотом, если бы проигнорировали то, что они узнали за эти полвека.

Они остановились на ряде вопросов. относительно стандартные «структуры данных компилятора»: абстрактные синтаксические деревья (AST), таблицы символов (ST), графы потока управления (CFG), факты потока данных (DFF), троек программ, анализ понтеров и т. д. количество символов между оператором сложения и буквой T в середине имени переменной является простым числом?). На практике свойства, которые можно получить из символьных строк, обычно не очень полезны (см. Пример, который я только что привел :).

Ребята-компиляторы потратили последние 60 лет, выясняя, как извлекать интересные свойства программы, и вы были бы полным идиотом, если бы проигнорировали то, что они узнали за эти полвека.

Они остановились на ряде вопросов. относительно стандартные «структуры данных компилятора»: абстрактные синтаксические деревья (AST), таблицы символов (ST), графы потока управления (CFG), факты потока данных (DFF), троек программ, анализ понтеров и т. д. свойства, которые вы можете получить из символьных строк, обычно не очень полезны (см. пример, который я только что привел :).

Ребята-компиляторы потратили последние 60 лет, выясняя, как извлекать интересные свойства программы, и вы были бы полным идиотом, если бы проигнорировали то, что они узнали за эти полвека.

Они остановились на ряде вопросов. относительно стандартные «структуры данных компилятора»: абстрактные синтаксические деревья (AST), таблицы символов (ST), графы потока управления (CFG), факты потока данных (DFF), троек программ, анализ понтеров и т. д. свойства, которые вы можете получить из символьных строк, обычно не очень полезны (см. пример, который я только что привел :).

Ребята-компиляторы потратили последние 60 лет, выясняя, как извлекать интересные свойства программы, и вы были бы полным идиотом, если бы проигнорировали то, что они узнали за эти полвека.

Они остановились на ряде вопросов. относительно стандартные «структуры данных компилятора»: абстрактные синтаксические деревья (AST), таблицы символов (ST), графы потока управления (CFG), факты потока данных (DFF), троек программ, анализ понтеров и т. д. Если вы хотите проанализировать или сгенерировать код, лучше всего сначала обработать его в такие стандартные структуры данных компилятора, а затем выполнить работу. Если у вас есть AST, вы можете ответить на все вопросы о том, какие операторы и операнды используются. Если у вас есть ЗБ, вы можете ответить на вопросы о том, где определено, где видно и какого типа. Если у вас есть CFG, вы можете ответить на вопросы о том, «что было раньше», «от каких условий зависит оператор X». Если у вас есть DFF, вы можете определить, какие назначения влияют на действия в той или иной точке кода. Отражение никогда не предоставит этого ИМХО, потому что оно всегда будет ограничено тем, что разработчики системы времени выполнения готовы оставить при запуске программы. (Возможно, когда-нибудь они сохранят все структуры данных компилятора, но тогда это не будет отражением; наконец-то это будет поддержка компилятора).

Теперь, после того как вы определили интересующие свойства, что вы делаете для генерации кода? Здесь разработчики компиляторов были настолько сосредоточены на генерации машинного кода, что не предлагают стандартных ответов. Ребята, которые это делают, - это сообщество по трансформации программ ( http://en.wikipedia.org/wiki/Program_transformation ). Здесь идея состоит в том, чтобы сохранить хотя бы одно представление вашей программы в виде AST и обеспечить специальную поддержку для синтаксиса сопоставления исходного кода (путем создания AST сопоставления с шаблоном из интересующих фрагментов кода) и предоставить правила "перезаписи", которые говорят в эффект: «когда вы видите этот узор, замените его на этот узор при этом условии». что вы делаете для генерации кода? Здесь разработчики компиляторов были настолько сосредоточены на генерации машинного кода, что не предлагают стандартных ответов. Ребята, которые это делают, - это сообщество по трансформации программ ( http://en.wikipedia.org/wiki/Program_transformation ). Здесь идея состоит в том, чтобы сохранить хотя бы одно представление вашей программы в виде AST и обеспечить специальную поддержку для синтаксиса сопоставления исходного кода (путем создания AST сопоставления с шаблоном из интересующих фрагментов кода) и предоставить правила "перезаписи", которые говорят в эффект: «когда вы видите этот узор, замените его на этот узор при этом условии». что вы делаете для генерации кода? Здесь разработчики компиляторов были настолько сосредоточены на генерации машинного кода, что не предлагают стандартных ответов. Ребята, которые это делают, - это сообщество по трансформации программ ( http://en.wikipedia.org/wiki/Program_transformation ). Здесь идея состоит в том, чтобы сохранить хотя бы одно представление вашей программы в виде AST и обеспечить специальную поддержку синтаксиса сопоставления исходного кода (путем создания AST сопоставления с образцом из интересующих фрагментов кода), а также предоставить правила "перезаписи", которые говорят в эффект: «когда вы видите этот узор, замените его на этот узор при этом условии». Ребята, которые это делают, - это сообщество по трансформации программ ( http://en.wikipedia.org/wiki/Program_transformation ). Здесь идея состоит в том, чтобы сохранить хотя бы одно представление вашей программы в виде AST и обеспечить специальную поддержку синтаксиса сопоставления исходного кода (путем создания AST сопоставления с образцом из интересующих фрагментов кода), а также предоставить правила "перезаписи", которые говорят в эффект: «когда вы видите этот узор, замените его на этот узор при этом условии». Ребята, которые это делают, - это сообщество по трансформации программ ( http://en.wikipedia.org/wiki/Program_transformation ). Здесь идея состоит в том, чтобы сохранить хотя бы одно представление вашей программы в виде AST и обеспечить специальную поддержку для синтаксиса сопоставления исходного кода (путем создания AST сопоставления с шаблоном из интересующих фрагментов кода) и предоставить правила "перезаписи", которые говорят в эффект: «когда вы видите этот узор, замените его на этот узор при этом условии». Соединяя условие с различными механизмами извлечения свойств от разработчиков компилятора, вы получаете относительно простой способ сказать, что вы хотите, подкрепленное этим 50-летним опытом. Такие системы преобразования программ имеют возможность считывать исходный код, выполнять анализ и преобразования и, как правило, регенерировать код после преобразования.

Для вашей задачи генерации кода вы должны считывать базовый код в AST, применять анализ для определения интересных свойств, использовать преобразования для создания новых AST, и затем выплюнуть ответ.

Для того, чтобы такая система была полезной, она также должна уметь анализировать и распечатывать большое количество языков исходного кода, чтобы люди, кроме любителей C #, также могли пользоваться преимуществами кода анализ и порождение.

Все эти идеи воплощены в DMS Software Reengineering Toolkit . DMS обрабатывает C, C ++, C #, Java, COBOL, JavaScript, PHP, Verilog, ... и многие другие языки.

(Я архитектор DMS, поэтому у меня довольно предвзятое мнение. YMMV) .

2
ответ дан 17 December 2019 в 04:50
поделиться

Вы можете использовать CodeDom , так что вам нужно будет собрать только один раз.

Во-первых, я бы прочитал эту статью CodeProject , чтобы убедитесь, что нет языковых функций, которые вы не смогли бы поддерживать без использования Reflection.

1
ответ дан 17 December 2019 в 04:50
поделиться

Я не уверен, как лучше это сделать, но вы можете сделать это

  • В качестве шага после сборки вашей базовой dll запустите генератор кода
  • Как другой шаг после сборки, запустите csc или msbuild , чтобы построить сгенерированную dll

  • . Другие вещи, которые зависят от сгенерированной dll, также должны будут зависеть от базовой dll, поэтому порядок сборки остается правильным

0
ответ дан 17 December 2019 в 04:50
поделиться

Насколько я понимаю, вы можете использовать что-то вроде Common Compiler Infrastructure ( http://ccimetadata.codeplex.com/ ) для программного анализа существующего исходного кода C #.

Мне это кажется довольно сложным, а CCI, по-видимому, полностью поддерживает только спецификацию языка C # 2. Лучшей стратегией может быть вместо этого оптимизация существующего метода.

0
ответ дан 17 December 2019 в 04:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: