В процессе написания текстового шаблона T4 я столкнулся с проблемой, которую никак не могу решить. Мне нужно знать тип обрабатываемого перечисления.
У меня есть перечисления, основанные на byte
и ushort
. Мне нужен текстовый шаблон T4, чтобы написать код для приведения перечисления к правильному типу значения, чтобы сериализовать перечисление и поместить его в массив байтов.
Это пример перечисления типа byte
namespace CodeEnumType
{
public enum MyEnum : byte
{
Member1 = 0,
Member2 = 1,
}
}
А это мой текстовый шаблон T4
<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="EnvDte" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System.Collections.Generic" #>
<#
var serviceProvider = this.Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
var project = dte.Solution.FindProjectItem(this.Host.TemplateFile).ContainingProject as Project;
var projectItems = GetProjectItemsRecursively(project.ProjectItems);
foreach(var projectItem in projectItems)
{
var fileCodeModel = projectItem.FileCodeModel;
if(fileCodeModel == null)
{
continue;
}
CodeElements codeElements = fileCodeModel.CodeElements;
ProcessCodeElements(codeElements);
}
#>
<#+
public void ProcessCodeElements(CodeElements codeElements)
{
if(codeElements == null)
{
return;
}
foreach(CodeElement codeElement in codeElements)
{
switch(codeElement.Kind)
{
case vsCMElement.vsCMElementNamespace:
CodeNamespace codeNamespace = codeElement as CodeNamespace;
CodeElements childCodeElements = codeNamespace.Members;
ProcessCodeElements(childCodeElements);
break;
case vsCMElement.vsCMElementEnum:
CodeEnum codeEnum = codeElement as CodeEnum;
WriteLine(codeEnum.Name);
//
// here I would like the enum type
//
break;
}
}
}
public IEnumerable<ProjectItem> GetProjectItemsRecursively(ProjectItems items)
{
if(items == null)
{
yield break;
}
foreach(ProjectItem item in items)
{
yield return item;
var childItems = GetProjectItemsRecursively(item.ProjectItems);
foreach(ProjectItem childItem in childItems)
{
yield return childItem;
}
}
}
#>
Обратите внимание на ту часть, где я написал
//
// here I would like the enum type
//
Здесь у меня есть информация о перечислении в переменной codeEnum
, и здесь моя проблема. Как мне получить тип byte
или ushort
от codeEnum
?
Я не использую здесь Reflection, поскольку Type.GetType () не работает, если сборка не была скомпилирована.
CodeEnum
? Какую технику генерации кода вы на самом деле используете - T4 или CodeDom? Похоже на причудливую смесь, еслиCode*
относятся к классам CodeDom. - person Ondrej Tucny   schedule 22.08.2016EnvDTE.CodeEnum
a >. Думаю, он спрашивает, как получить из этого базовый целочисленный тип. - person Jeppe Stig Nielsen   schedule 22.08.2016foreach (var b in codeEnum.Bases) { WriteLine(b); }
или подобное? Я подозреваю, что базовый тип можно найти через свойство.Bases
. - person Jeppe Stig Nielsen   schedule 22.08.2016.BaseType
во время размышления. Тогда я подумал, что это может сработать, потому что методAddBase
spec сказал что-то вроде: ДляCodeEnum
объектовBase
- это вариант, содержащий полное имя типа илиCodeType
объект, на котором основано новое перечисление. Для C # это базовый тип перечисления. Не то, чтобы я много об этом знаю. - person Jeppe Stig Nielsen   schedule 22.08.2016Type.GetEnumUnderlyingType()
и посмотрел на тип первого члена перечисления. Я пробовал это раньше, но безуспешно, но, может быть, мне стоит попробовать еще раз. - person Robin Theilade   schedule 22.08.2016value__
и содержит базовое целочисленное значение. Это не первая из констант перечисления, определяемых типом (они статические, и констант перечисления может быть нулевым). То, что делает этот метод, эквивалентно (отражение):.GetField("value__").FieldType
, которое действительно работает! Однажды я задался вопросом об этом поле экземпляра в другом вопросе: Действительно ли типы перечислений .NET являются изменяемыми типами значений? i > - person Jeppe Stig Nielsen   schedule 22.08.2016Type.GetType(codeEnum.FullName).GetEnumUnderlyingType()
? - person Jeppe Stig Nielsen   schedule 22.08.2016