Add property to IAttribute (or Add IPropertyAssignment to IAttribute)

Say I have this:

Insert a property to an attribute?

[XFactor(IsRequired = false)]
public string Myth { get; set; }

and I want to insert a new property to this attribute so it becomes:

[XFactor(Level = 1, IsRequired=false)]
public string Myth { get; set; }

What's the preferred way to do this?

Cannot insert IPropertyAssignment
I can navigate the IAttribute.PropertyAssignments and try to do do IAttribute.PropertyAssignments.Add(EternalLifetime.Instance, someMadeUpProeprtyAssignment), but it'll throw an exception saying


'attribute.PropertyAssignments.Add(EternalLifetime.Instance, someMadeUpProeprtyAssignment)' threw an exception of type 'System.InvalidOperationException'
"Operation is not valid due to the current state of the object."

Can insert an expression but will get hover error "Cannot resolve symbol 'Level'"

I can somehow insert a TreeNode created with CSharpElementFactory.CreateExpression("Level  = 1") after the left parenthesis (so yes I can get this:

[XFactor(Level = 1, IsRequired=false)]
public string Myth { get; set; }

However I doubt this is the correct way to do it as though it works, the part "Level = 1" will show up in red, and gives an hover hint "Cannot resolve symbol 'Level'", and as I check attribute.PropertyAssignments, the newly inserted TreeNode is not included (or resolved).

Possibly there are 2 solutions:

1) There is a way to Resolve the symbol after I insert the TreeNode to the attribute, something like Resolve() or UpdateSymbols
2) There is a way to instantiate an IPropertyAssignment (which I can't find using any factory or util) and insert it to the attribute without getting the InvalidOperationException.

Please help - any ideas highly appreciated.

4 comments
Comment actions Permalink

You can't call PropertyAssignments.Add - sadly, the propert implements IList<T>, but it's a read only list, so it throws an InvalidOperationException when you try to add (ReSharper has only just started targetting .net 4.0, so doesn't use any nicer read only interfaces). Instead, you should use IAttribute.AddPropertyAssignmentBefore or AddPropertyAssignmentAfter.

By adding a tree node that you received from CreateExpression, you most likely added an invalid tree node - an expression in the property assignment list, rather than an actual property assignment. So, while the text might look correct, the tree is invalid. As you state, you'll need to add a property assignment node. You can use CSharpElementFactory.CreatePropertyAssignment in order to create an IPropertyAssignment that you can pass to IAttribute.AddPropertyAssigmnetBefore/After. You pass in the name of the property that you're trying to assign to, then the value that you're trying to assign, as an expression. If you're setting it to the integer value "1", then you can use CSharpElementFactory.CreateExpressionByConstantValue(new ConstantValue(1, attribute.GetPsiModule(), attribute.GetResolveContext()).

0
Comment actions Permalink

Thanks Matt - very interesting. However I cannot find the methods you mentioned:


CSharpElementFactory.CreatePropertyAssignment


IAttribute.AddPropertyAssigmnetBefore/After


Are they extension methods? Or are they only available at a very new version that I should upgrade to?

Upgraded SDK to latest and works like a charm!

Thanks!

0
Comment actions Permalink

Hi Matt - I notice these PropertyAssignment methods are only available for Resharper 9. Is there a workaround for 8.2?

Thanks!

0
Comment actions Permalink

The AddPropertyAssignmentBefore/After are just wrappers around ModificationUtil.AddChild, although they include logic to handle missing braces, and adding commas.

And when you updated the SDK, did you update to the 9.x SDK? That won't work on 8.2...

0

Please sign in to leave a comment.