How can I copy a class and then change the baseclass type

Topics: Metadata Model
Jul 21, 2011 at 2:30 AM
Edited Jul 21, 2011 at 2:32 AM


Hello,

I am currently working my way through the Metadata model samples and documentation but I can't seem to find an example for changing the baseclass (what I think CCI calls the class we use in the inherits statement).  What I would like to do is open an assembly loop the classes.. find a certain class.. copy it.. change its name and change its baseclass and then save the new class to the same assembly opened in the first step.  If the last step is problematic then saving to a new assembly would work as well.  I have code to open the assembly and loop the classes and find the one I want.. but I am not sure how to copy it so I can change the name and baseclass.  I thought I had to do a directcast from the INamedTypeDefinition to NamedTypeDefinition (which I thought was the mutable type) but the name property is still read only.  Any help would be much appreciated.

Thanks,

Doug   

Coordinator
Jul 21, 2011 at 3:03 AM

If you intend to modify the object model is a good idea to first make a mutable copy of the model and then to traverse the mutable copy. The PeToPe sample has some code that shows you how to make a copy.

Jul 22, 2011 at 2:07 AM

 

Thanks Hermanv,

I looked at that example but I am still not seeing how I can change the class name.  Here is what my code looks like..

Dim AssemblyLoc As String = "TargetAssembly.dll"
Dim Host = New PeReader.DefaultHost()
Dim TargetAssembly = TryCast(Host.LoadUnitFrom(AssemblyLoc), IAssembly)
Dim MutableAssembly = New MetadataDeepCopier(Host).Copy(TargetAssembly)


Dim MutableModuleMTypeCount As Integer = MutableAssembly.AllTypes.Count
Dim i As Integer

For i = 0 To MutableModuleMTypeCount - 1

     Dim INamedTypeDef As INamedTypeDefinition = MutableAssembly.AllTypes.Item(i)
     Dim NamedTypeDef As NamedTypeDefinition
     NamedTypeDef = DirectCast(INamedTypeDef, NamedTypeDefinition)

     If NamedTypeDef.Name.Value = "TargetClassName" Then

           ' ISSUE HERE PROP READY ONLY NamedTypeDef.Name.Value = "NewClassName"

     End If

Next
Do I need to make a mutable copy of the Class(Type)?
Thanks,
Doug
Coordinator
Jul 22, 2011 at 4:27 AM

You need to make a new name. Names remain immutable even after the deep copy. Host.NameTable.GetNameFor("NewClassName") should do the trick.

Jul 22, 2011 at 6:50 AM
Edited Jul 22, 2011 at 7:12 AM

 

Thanks! You are correct that did seem to do the trick.  I am also able to remove an existing BaseClass but I am stuck trying to add a new one.  I see that the add method of the BaseClasses collection wants a type of ITypeReference but I am not sure how to create one that represents the new class I want to add.  Do I need to load the assembly that contains the class I want to use as a new baseclass.. or is there some easier way to go about it? I see in the HelloIL sample there is the line...

testClass.BaseClasses.Add(host.PlatformType.SystemObject);

But this doesn't really help in getting a class I've created.  I did find this function of the PeReader class..

Public Function ResolveSerializedTypeName ( _
	typeName As String, _
	assembly As IAssembly _
) As ITypeDefinition

But this returns a ITypeDefinition and not a ITypeReference.  It would also be great if there was a way to create an ITypeReference for my class without having to know the assembly.  Any help you can give would be much appreciated.

Thanks again,

Doug

 

 



 

Coordinator
Jul 22, 2011 at 11:32 PM

You don't have to load the assembly that contains the base class, but you do have to know the name of the assembly. The PlatformType class in the MetadataHelper project is a good place to look for guidance on how to construct a type reference. It is also OK to use an ITypeDefinition when an ITypeReference is expected.