Общая инфраструктура компилятора: как работать с ICustomAttribute - PullRequest
1 голос
/ 05 января 2010

Я пытаюсь использовать CCI-метаданные для создания генератора кода, перебирая наборы сборок, обнаруживая типы и их метаданные, а затем генерируя код. Я хотел бы иметь возможность контролировать генерацию кода, прикрепляя настраиваемые атрибуты к метаданным исходных типов.

Что-то вроде:

[GenerateSpecialClass(true, "foo", IsReallySpecial=false)]
public class MyClass { ... }

У меня есть INamedTypeDefinition и я получаю IEnumerable из свойства Attributes. Отсюда я не могу понять, что нужно сделать, чтобы получить значение пользовательского атрибута и его свойств.

Может ли кто-нибудь дать мне пример кода: учитывая атрибут ICustomAttribute, как я могу получить значения из моего примера атрибута. Предположим, это определение:

public GenericSpecialClassAttribute : Attribute
{
    public bool Prop1 { get; set; }
    public string Prop2 {get; set; }
    public bool IsReallySpecial {get; set; }
    public GenericSpecialClassAttribute(bool prop1, string prop2)
    {
       Prop1 = prop1;
       Prop2 = prop2;
    } 
}

Любая помощь будет принята с благодарностью. Я предполагаю, что приведу это к какому-то другому интерфейсу и сделаю с ним что-нибудь волшебное; но я не смог найти помощника, который бы что-нибудь делал с ним и не полностью понимал иерархию реализации / модели.

Ответы [ 2 ]

1 голос
/ 15 декабря 2012

Попробуйте привести к Microsoft.Cci::IMetadataConstant. Вот пример кода, который выводит данные из Microsoft.Cci::ICustomAttribute.

public static void parseCustomAttribute(Cci::ICustomAttribute customAttribute)
{ 
    foreach (Cci::IMetadataNamedArgument namedArg in customAttribute.NamedArguments)
    { 
        parseNamedArgument(namedArg);
    }

    foreach (Cci::IMetadataExpression arg in customAttribute.Arguments)
    {
        parseFixedArgument(arg);
    }

    Console.WriteLine("Type Reference:\t\t"+ customAttribute.Type.ToString());

    var constructor = customAttribute.Constructor as Cci::IMethodDefinition;
    if (constructor != null)
    {
        //parseMethodDefinition(constructor);
    }
    else
    {
        //parseMethodReference(constructor);
    }
}

private static void parseFixedArgument(Cci::IMetadataExpression fixedArgument)
{
    Console.WriteLine("Type Reference:\t\t" + fixedArgument.Type.ToString());

    var constValue = fixedArgument as Cci::IMetadataConstant;

    if (constValue != null)
    {
        Console.WriteLine("Value :"  + constValue.Value);
    }
}

private static void parseNamedArgument(Cci::IMetadataNamedArgument namedArg)
{
    Console.WriteLine("Name:" + "\t\t" + namedArg.ArgumentName.Value);
    parseFixedArgument(namedArg.ArgumentValue);
}
  • IMetadataNamedArgument относится к парам имя / значение в потоке больших двоичных объектов Value в метаданных. Они используются для указания полей и свойств. Для вашего класса CCI делает IsReallySpecial доступным как IMetadataNamedArgument
  • IMetadataExpression относится к значениям аргумента конструктора. Таким образом, аргументы prop1 и prop2 сохраняются как MetadataExpression в объектной модели CCI.
0 голосов
/ 31 января 2010

Проверьте Джейсон Бок Форсунки . Я думаю, что он делает то, что вы ищете в своем методе InjectorContext.Find (), а затем просматривает различные свойства / параметры в методе NotNullInjector.OnInject ().

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

...