3

Is there a way to create an attribute with a typeof expression with a generic type?

The following code works only partially:

CSharpElementFactory factory = ...
IClassDeclaration typeDeclaration = ...

IClassDeclaration classDeclaration = ...
IType[] attributeTypeParameters = 
    (from typeParameter in classDeclaration.TypeParameters
    select (IType)TypeFactory.CreateUnknownType(module)).ToArray();
IType classType = TypeFactory.CreateType(classDeclaration.DeclaredElement, 
                                         attributeTypeParameters);

var attribute = factory.CreateAttribute(
    new SpecialAttributeInstance(
        ClrTypeNames.ContractClassAttribute,
        module,
        () => new[] { new AttributeValue(classType) },
        Enumerable.Empty<Pair<string, AttributeValue>>));
typeDeclaration.AddAttributeAfter(attribute, null);
Michael Damatov
  • 15,253
  • 10
  • 46
  • 71

1 Answers1

1

I suspect the problem is the way in which you are defining your class declaration. Here's a code snippet which decorates the class in context with [ContractClass(typeof(Dictionary<,>))]

ClrTypeName contractClassAttribute = 
  new ClrTypeName("System.Diagnostics.Contracts.ContractClassAttribute");
ClrTypeName someGenericClass = new ClrTypeName("System.Collections.Generic.Dictionary`2");

var module = provider.PsiModule;
var owner = provider.GetSelectedElement<IClassDeclaration>(true, true);
var factory = CSharpElementFactory.GetInstance(module);

var someGenericTypeElement = TypeElementUtil.GetTypeElementByClrName(someGenericClass, module);
var unknownType = TypeFactory.CreateUnknownType(module);
var someGenericType = TypeFactory.CreateType(someGenericTypeElement, unknownType, unknownType);
var contractClassTypeElement = TypeElementUtil.GetTypeElementByClrName(contractClassAttribute, module);
var attribute = factory.CreateAttribute(contractClassTypeElement, new[] {new AttributeValue(someGenericType)},
                                        EmptyArray<Pair<string, AttributeValue>>.Instance);
owner.AddAttributeAfter(attribute, null);
Dmitri Nesteruk
  • 23,067
  • 22
  • 97
  • 166
  • `TypeElementUtil.GetTypeElementByClrName(someGenericClass, module)` is null. So `TypeFactory.CreateType(someGenericTypeElement...` throws an exception. – Michael Damatov Jan 17 '12 at 06:28
  • What version of .Net are you using? (I mean, .Net framework target for the project.) – Dmitri Nesteruk Jan 17 '12 at 12:58
  • Your snippet works because you are using an **existing** type, but in my case I'm creating a completely new generic class that should be referenced by a `typeof(GenericType<,>)` within an attribute. – Michael Damatov Jan 17 '12 at 21:53
  • Okay, so then let's say you have an existing type. In this case, you simply take its declaration: `var someGenericType = TypeFactory.CreateType(someDeclarationIHave.DeclaredElement, ...)` – Dmitri Nesteruk Jan 18 '12 at 21:06