Thank you Jb, this information is very useful
However I did exactly what you said, same steps, and I've almost the same
problem,
PeVerify fails with this message:
[MD]: Error: Signature contains long form (such as
ELEMENT_TYPE_CLASS<token of System.String>). [token:0x1B000002]

If i use a class defined in the same assembly instead "int", everything
works ok.

One of the things i noticed, is that when i read genericArgument is
"System.Int32" but the Module property is "MyAssembly.dll",
is that ok? should not be something like "mscorlib" or
CommonLanguageRuntimeLibrary...

Thank you again.


2011/1/20 Jb Evain <[email protected]>

> Hey,
>
> On Thu, Jan 20, 2011 at 11:51 PM, José F. Romaniello
> <[email protected]> wrote:
> > ok, i have an assembly "A" just with these three things:
> > //interface for template
> > public interface IFoo<T>
> > {
> > }
> > //template
> > public class Foo<T> : IFoo<T>
> > {}
> > //target
> > [ExtendWith(typeof(Foo<int>))]
> > public class Target
> > {
> > }
> > From another assembly "B",  I am  trying to modify this one, in order to
> > make Target implement IFoo<int> (just that for now).
> > So, i look all types that has the ExtendWith attribute, and then i read
> the
> > constructor arguments and i get a GenericInstanceType pointing to
> Foo<int>
> > and i have the Type Definition of Target.
> > So, what is the best way to get IFoo<int> from the GenericInstanceType?
> > If i do genericInstanceType.Resolve().Interfaces <- these generic
> instance
> > types doesn't have the arguments...
>
> So first of all, you need to take a few things into account. In one
> assembly, you can get a generic instance of a type, without having all
> the details of a type, that is, if the type is defined in another
> assembly.
>
> If you have GenericInstanceType, you usually use .ElementType to
> figure out the type which is instantiated. If you use .Resolve(), it
> will return the definition of the ElementType. Which means that it may
> have to go look for it in another assembly.
>
> And with Cecil, you can't directly use types defined in a module into
> another module. You have to create references.
>
> So in your scenario, if IFoo<T> is in IFoo.dll, if Foo<T> is is
> Foo.dll, and Target in Target.dll, you have to take care of a few
> things.
>
> When you have the TypeDefinition `Target`, and that you get its custom
> attribute, you'll get a TypeReference to Foo`1 (in that case, a
> GenericInstanceType with the ElementType being Foo`1 and with a
> generic argument being a reference to int32.
>
> If you Resolve this reference, it will open Foo.dll and get you the
> TypeDefinition of Foo`1.
> If you browse its interfaces, you'll have a TypeReference to IFoo`1 .
> If you Resolve this reference, it will open IFoo.dll and get you the
> TypeDefinition of IFoo`1.
>
> So now we're all down the chain, and you want to make Target implement
> IFoo`1 with the generic arguments of the GenericInterfaceType in the
> CustomAttribute.
>
> You can't just add the interface, you have to create the proper references.
>
> ModuleDefinition targetModule = ...;
> TypeDefinition targetType = ...;
> GenericInstanceType foo_of_int_ref = (GenericInstanceType)
> targetType.CustomAttributes [0].ConstructorArguments [0];
> TypeReference foo_of_t_ref = foo_of_int_ref.ElementType;
>
> TypeDefinition foo_of_t = foo_of_t_ref.Resolve (); // opens Foo.dll,
> foo_of_t.Module is Foo.dll
> TypeReference ifoo_of_t_ref = foo_of_t.Interfaces [0];
>
> TypeDefinition ifoo_of_t = ifoo_of_t_ref.Resolve (); // opens
> IFoo.dll, ifoo_of_t.Module is IFoo.dll
>
> So now, let's make targetType implement IFoo with the arguments passed to
> Foo.
>
> TypeReference ifoo_ref_in_target = targetModule.Import (ifoo_of_t);
>  GenericInstanceType ifoo_instance_in_target = new GenericInstanceType
> (ifoo_ref_in_target);
>
> foreach (TypeReference argument in foo_of_int_ref)
>    ifoo_instance_in_target.GenericArguments.Add (argument);
>
> targetType.Interfaces.Add (ifoo_instance_in_target);
>
> And here we are. The important thing here is to get a proper reference
> (import) for IFoo for the target module. Of course the code above is a
> bit long and you cant short circuit a few things, but it helps
> remembering all the different steps that need to happen.
>
> Also note that in the loop:
>
> foreach (TypeReference argument in foo_of_int_ref)
>    ifoo_instance_in_target.GenericArguments.Add (argument);
>
> We can re-use the argument as they are, because they are already
> scoped for the targetModule, after all, the original Foo<int>
> instantiation is declared in targetModule, so we don't need to create
> a proper reference for them.
>
> Jb
>
> --
> --
> mono-cecil

-- 
--
mono-cecil

Reply via email to