开发者

Common Compiler Infrastructure: How to work with ICustomAttribute

开发者 https://www.devze.com 2022-12-15 16:28 出处:网络
I\'m attempting to use CCI-Metadata for creating a code generator, by iterating over a set of assemblies, discovering the types and their metadata and then generating the code. I would like to be able

I'm attempting to use CCI-Metadata for creating a code generator, by iterating over a set of assemblies, discovering the types and their metadata and then generating the code. I would like to be able to control the code generation by attaching custom attributes to the metadata of the original types.

Something like:

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

I have a INamedTypeDefinition and get an IEnumerable from the Attributes property. From here, I can't figure out what to do to get the value of custom attribute and it's properties.

Could someone give 开发者_高级运维me a code sample: given an ICustomAttribute, how I can retrieve the values from my example attribute. Assume it's definition is:

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;
    } 
}

Any help would be very much appreciated. I assume I cast this to some other interface and do something magical on it; but I couldn't find a helper that did anything with it and don't fully understand the implementation/model hierarchy.


Try casting to Microsoft.Cci::IMetadataConstant. Here's a sample code that dumps data out of 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 refers to name/value pairs in the Value blob stream in metadata. They are used to specify fields and properties. For your class, CCI makes IsReallySpecial available as an IMetadataNamedArgument
  • IMetadataExpression refers to argument values of the constructor. So args prop1 and prop2 are kept as MetadataExpression in CCI object model.


Check out Jason Bock's Injectors. I think he does what you are looking for in his InjectorContext.Find() method and then the looks up the different properties/parameters in the NotNullInjector.OnInject() method.

Get his code up and running, then you'll have a better understanding of how to do what you're looking to do.

0

精彩评论

暂无评论...
验证码 换一张
取 消