2015-09-17 5 views
2

Есть ли возможность выполнить некоторый код во время компиляции?Код запуска во время компиляции

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

//this code has no actual purpose, just as an example 
public class Sample<T> 
{ 
    public Sample<T>(T instance) 
    { 
     foo = Value = instance; 
     /* adding some extra code(e.g. logging) to the methods of T, by 
inserting a "M" in front of the method names of T */ 
    } 

    public T Value { get; } 
    public dynamic foo { get; } 
} 

Как бы/можно было бы использовать

var foo = new Sample<string>("hey"); 
foo.MSubstring(0,0); 

Теперь я хочу знать, если есть возможность выполнить код во время компиляции, например, бросить исключение до выполнения, что foo.MgetSize() не существует в Т.

(Этот вопрос только о том, как выполнить код во время компиляции, этот пример не является реальной проблемой.)

Я не» У меня есть план, как это сделать. Может быть, используя эти #if - вещи?

+0

Одна из этих "' # if' вещей "называется [Директива препроцессора] (https://msdn.microsoft.com/en-us/library/ed8yd1ha.aspx). –

+4

Является ли это проблемой XY? – Tom

+1

Статическая типизация существует, чтобы обеспечить в значительной степени эту функцию: ошибка времени компиляции при несоответствии типов. Выбирая использовать динамическую типизацию в этой точке, вы явно отказываетесь от этой точной функции. Если это всего лишь пример, а не настоящая проблема, которую вы пытаетесь решить, возможно, вы должны это описать. –

ответ

-1

Вы не можете выполнить код во время компиляции по определению. Однако вы можете выполнить код во время загрузки (на самом деле до того, как первый экземпляр создается или ссылается любые статические члены) с использованием статических конструкторов:

link to msdn

+3

Какое определение? Конечно, вы можете иметь компилятор, который выполняет произвольный код как часть компиляции. –

+0

Я имею в виду определение слова «скомпилировать». То, как я это понимаю, заключается в том, что во время компиляции код компиляции не выполняется. –

+0

Компиляторы C++ обычно «выполняют код» во время компиляции (для различных значений термина, что-либо от TMP до явно с 'constexpr'). Это правда, однако, что компиляторы C# этого не делают. –

2

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

Что вы спрашиваете, как настроить этот процесс сборки и выполнить некоторую дополнительную логику во время его работы. Как вы это сделаете, это зависит от реальных инструментов, которые вы используете - например, для Visual Studio и системы MSBuild, вы можете обратиться к MSDN documentation on custom build steps and build events.

Каков будет ваш пользовательский инструмент построения, зависит от того, в какой части процесса он будет запускаться. Если он работает с исходным кодом, он должен иметь возможность анализировать исходный код C# (и, возможно, файлы проекта VS). Если он работает, проверяя испущенную сборку (двоичный файл, созданный в конце типичного процесса сборки), он может просто использовать отражение, чтобы обнаружить нужные вам ошибки. Я бы сказал, что последнее более удобно.

+1

Да, для этого необходим «шаг пользовательской сборки»; в языке C# ничего не встроено. –

0

В C# вы можете запустить какой-то код, который вы только что скомпилировали на шаге «Построить» визуальной студии.

Возможно, вы сможете использовать такой инструмент, как Post #, чтобы делать то, что вам нужно, создавая атрибуты, которые вы проверяете, имея в виду. См.: https://www.postsharp.net/product/how-it-works

На других языках, таких как Jai, вы можете сделать это легко. См. «Произвольное выполнение кода компиляции», здесь: https://sites.google.com/site/jailanguageprimer/

2

Теоретически вы можете использовать T4 для проверки времени компиляции.
Другой способ - использовать языки, поддерживающие макросы времени компиляции. Например, Nemerle или Boo.
Возможно, вы можете использовать Roslyn. Но только в C# 6.

+0

Пожалуйста, объясните, что такое T4 и Roslyn. –

0

Сценарий, в котором определенная функция может существовать и может не существовать, немного отрывочна. Лучше включить метод Convert в свой интерфейс, и сам объект может рассказать вам, реализует ли он функциональность и возвращает объект с соответствующим интерфейсом, или null, если это не так.

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

#define HASMETHOD 

и в своем использовании исполнитель:

#ifdef HASMETHOD 
    foo.MSubstring(0,0); 
#endif 

, но опять же, STRONLY рекомендуют против этого. Используйте метод, который вы вызываете во время выполнения, чтобы определить, что возвращает интерфейс для вызова.

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