Here is a minimalist example to show what I've run into:

-----------------------------------------------------------------------
class Test<U> : IEnumerable<U>
{
    // This is an implicit implementation, so it doesn’t have an
    // override declaration
    public IEnumerator<U> GetEnumerator() { return null; }
    // (don’t care about this one)
    IEnumerator System.Collections.IEnumerable.GetEnumerator()
    { return null; }
}

partial class Program
{
    static void Main(string[] args)
    {
        var self = AssemblyDefinition.ReadAssembly(
            Assembly.GetExecutingAssembly().Location);
        var TestU = self.MainModule.Types.Single(
            t => t.FullName == "X.Test`1");

        // This gets me the method declared above, to which I want to
        // add an explicit override declaration
        var TestUGetEnumerator = TestU.Methods.Single(
            t => t.Name == "GetEnumerator");

        var IEnumerableU = TestU.Interfaces.Single(i => i.FullName
            .StartsWith("System.Collections.Generic.IEnumerable`1"));
        var IEnumerable = IEnumerableU.GetElementType().Resolve();

        // This gets me the right method in the original,
        // non-constructed generic IEnumerable<T> type
        var IEnumerableGetEnumerator = IEnumerable.Methods.Single(
            m => m.Name == "GetEnumerator");

        // Try to add the override!
        TestUGetEnumerator.Overrides.Add(IEnumerableGetEnumerator);
        self.Write("Temp_out.exe");
    }
}
-----------------------------------------------------------------------

Of course, this doesn't work because IEnumerableGetEnumerator contains
the method from the unconstructed type, but we need one for the
constructed type IEnumerable<U>, which I have in IEnumerableU. So I
tried to create a MethodReference for this:

-----------------------------------------------------------------------
    var newMethodReference = new MethodReference("GetEnumerator",
        IEnumerableGetEnumerator.ReturnType)
    {
        DeclaringType = IEnumerableU,
        HasThis = IEnumerableGetEnumerator.HasThis,
        ExplicitThis = IEnumerableGetEnumerator.ExplicitThis,
        CallingConvention = MethodCallingConvention.Generic
    };

    // This method doesn't have any parameters, but if it did,
    // I would add them like this
    foreach (var parameter in IEnumerableGetEnumerator.Parameters)
        newMethodReference.Parameters.Add(new ParameterDefinition(
            parameter.ParameterType));

    // Try to add the override!
    TestUGetEnumerator.Overrides.Add(newMethodReference);
    self.Write("Temp_out.exe");
-----------------------------------------------------------------------

Unfortunately, this still doesn't work. PEVerify shows the following
validation error:

[MD]: Error: Signature has an invalid token (token: 0x02000036;
offset: 0x00000004). [token:0x0A000069]
[MD]: Error: Signature has generic type of arity 0 instantiated at
different arity 1 at byte=0x00000007. [token:0x0A000069]

What am I doing wrong?

Many thanks!
Timwi

-- 
--
mono-cecil

Reply via email to