What about array types? You also need to replace the T in "T[]". In fact, you'd have to handle all the type specifications. For example, a field "volatile T member;" will require replacement of the GenericParameter within the OptionalModifierType when one wants to move the field to another class.
I think replacing types is something that belongs directly into Cecil --
so far, all of my projects using Cecil have required something like
this, even if its just for determining the parameter types of a generic
method call.
The visitor pattern works quite well for this - take a look at how
System.Linq.Expressions.ExpressionVisitor can be used for replacing
nodes within an expression tree. And it's useful for more than just
replacements.
For example, here are two type visitors I use in the NRefactory type
system, where I've already implemented this idea:
sealed class Substitution : TypeVisitor
{
readonly IType[] typeArguments;
public Substitution(IType[] typeArguments)
{
this.typeArguments = typeArguments;
}
public override IType VisitTypeParameter(ITypeParameter type)
{
int index = type.Index;
if (type.OwnerType == EntityType.TypeDefinition) {
if (index >= 0 && index < typeArguments.Length)
return typeArguments[index];
else
return SharedTypes.UnknownType;
} else {
return type.VisitChildren(this);
}
}
}
// Usage: IType result =
type.AcceptVisitor(new Substitution(typeArguments));
sealed class TypeClassificationVisitor : TypeVisitor
{
internal bool isOpen;
public override IType VisitTypeParameter(ITypeParameter type)
{
isOpen = true;
return type.VisitChildren(this);
}
}
So TypeReference would have two methods:
AcceptVisitor() is the regular visitor pattern and just calls the
appropriate Visit-Method on the visitor.
VisitChildren() will call AcceptVisitor() for all child types, and then
reconstruct the type around the return values of those child calls. For
non-TypeSpecifications, VisitChildren() simply is "return this;"
For TypeSpecifications, it would look similar to this:
public override IType VisitChildren(TypeVisitor visitor) // in ArrayType
{
IType e = elementType.AcceptVisitor(visitor);
if (e == elementType)
return this;
else
return new ArrayType(e, dimensions);
}
Daniel
On 5/2/2011 10:44, Alex Corrado wrote:
> Hi,
>
> As far as I know, there is no easy way to do this, though I would love
> if someone proved me wrong. I'm working on an async method
> transformation that extracts method bodies into Cecil-generated nested
> classes. I wrote a couple of extension methods to fix up the generic
> type tokens. Basically, you will need to inspect every instruction
> that emits a type or method reference in the IL and replace any
> generic type tokens with the correct ones from the new method you
> created. You can use the methods I wrote to do that replacement if
> you'd like:
....
signature.asc
Description: OpenPGP digital signature
