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:
....

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to