How to obtain TypeReference from TypeDefinition?

Topics: Metadata Model
Jun 22, 2009 at 6:59 AM

When working with immutable interfaces, ITypeReference can be cast direcly from ITypeDefinition. But with mutable objects this approach doesn't work for some reason. Is there any workaround?

Coordinator
Jun 22, 2009 at 3:15 PM

In the CCI object models you should in general never cast from one interface to another. To resolve a type reference to a type definition, use the ResolvedType property.

The only case where it is safe to cast down to an interface is when you have an object which has as its static type a base interface, such as ITypeReference, and which guarantees statically that it implements one of a fixed set of derived interfaces, such as INestedTypeReference, in which case you should use the C# "as" operator to check if the cast succeeds.

Jun 22, 2009 at 5:58 PM

I asked for exactly opposite task. Get a TypeReference for the known TypeDefinition.

Coordinator
Jun 22, 2009 at 6:37 PM

Hmm, sorry, I misread your comment. Since an ITypeDefinition interface always implements ITypeReference, there should be no need to cast and there should be no problem with mutable objects. Could you construct a test case that demonstrates the undesirable behavior and enter an issue?

Jun 22, 2009 at 6:45 PM
Edited Jun 22, 2009 at 7:25 PM

This is overriden method of Mutator class:

  public override TypeReference Visit(TypeReference typeReference)
  {

    // ??????
  }

And I need to return reference to a known TypeDefinition here. How can I do that?

PS I tried to use other signature override - public override TypeReference Visit(ITypeReference typeReference)

But this one doesn't visit some objects, that first one does (custom attributes constructor references, for example). Any advise?

Coordinator
Jun 22, 2009 at 7:21 PM

For this scenario you do need to override ITypeReference Visit(ITypeReference). In the case where you are returning a known ITypeDefinition object, you should not need to actually visit the known object, either because it is from another assembly and should not be mutated, or because it will be visited as the child of another object. In the second case, it is important that you return the type definition that will result from the second visit. You can do that by returning GetMutableObject(ITypeDefinition).

Jun 22, 2009 at 7:30 PM
Edited Jun 23, 2009 at 5:03 AM

I'm using Visit to change all references in assembly from one type to another. And Visit(ITypeReference) works incorrectly- it doesn't visit references to custom attribute types, for example. Visit(TypeReference) does visit them, however.

Jun 23, 2009 at 6:38 PM

So, any advise?

Coordinator
Jun 24, 2009 at 7:49 AM

Visit(TypeReference) is called via Visit(ITypeReference), so I don't quite understand your problem, which makes it difficult to give advice. The reason you should override Visit(ITypeReference) is so that you can return something other than a TypeReference. It is up to the override to ensure that everything gets visited properly.

Jun 24, 2009 at 12:49 PM
Edited Jun 24, 2009 at 12:53 PM

No, it doesn't. Just check the code.

I call visitor on my assembly and Visit(TypeReference) is called for custom attribute type references, while Visit(ITypeReference) is not called for these references. And this is a problem.

 MetadataMutator contains method Visit(CustomAttribute), but method Visit(ICustomAttribute) is not present at all. Is this a bug?

Coordinator
Jun 24, 2009 at 3:56 PM

Visit(CustomAttribute) calls Visit(customAttribute.Constructor) which ends up calling Visit(methodReference.ContainingType) which is the the Visit(ITypeReference) overload.

If you could construct a test case that demonstrates a behavior that you find surprising, it will be easier for me to say something useful or to do something about it. Note that you can change the behavior of the mutator in almost abitrary ways by overridding methods, such as Visit(CustomAttribute).

There is no Visit(ICustomAttribute) because it is less likely to be needed than Visit(ITypeReference). You can, however, introduce one in your derived class and then override Visit(List<ICustomAttribute>) to call Visit(ICustomAttribute).

Finally, if this mutator does not work for you, you can always write your own one and share that with the rest of us. :-)

Jun 24, 2009 at 6:24 PM

I've found the reason, it was in another place. Sorry for disturbance.

BTW, library really needs some code model validation. It takes lots of debugging to find the real reason of problem. If I write some, what I need to submit it to the repository?

Coordinator
Jun 24, 2009 at 7:32 PM

To submit code, you'll have to follow the procedure outlined in http://ccimetadata.codeplex.com/Wiki/View.aspx?title=How%20to%20contribute.

See also http://ccimetadata.codeplex.com/Wiki/View.aspx?title=Unfinished%20business.