Public GenericParameter constructor that takes context-free position
See original GitHub issueIn a project using Mono.Cecil to write IL, I need to specify member references such as System.Collections.Generic.Dictionary`2<string, string>::.ctor(class System.Collections.Generic.IEqualityComparer`1<!0>)
Because the corresponding reference assemblies may not be available at the time, I’m not loading mscorlib.dll/System.Collections.dll/netstandard.dll etc. Just emitting the correct assembly name reference (if needed) and the correct IL. That requires me to construct the type specification for System.Collections.Generic.IEqualityComparer`1<!0>
without having a GenericParameterCollection from the reference assembly to set the generic parameter position.
The only option so that the project is not blocked is to use reflection to get the Position property set to something other than -1 which of course serialization chokes on:
var genericParameter0 = (GenericParameter)typeof(GenericParameter)
.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] { typeof(int), typeof(GenericParameterType), typeof(ModuleDefinition) },
null)
.Invoke(new object[] { 0, GenericParameterType.Type, module });
// Instantiate IEqualityComparer<> with Dictionary<,>'s TKey
var equalityComparer = new TypeReference(
"System.Collections.Generic",
"IEqualityComparer`1",
module,
scope: assemblyContainingSystemCollections);
var equalityComparerInstantiation = new GenericInstanceType(equalityComparer)
{
GenericArguments = { genericParameter0 }
};
il.Emit(OpCodes.Newobj, new MethodReference(
".ctor",
returnType: dictionaryField.Module.TypeSystem.Void,
declaringType: dictionaryField.FieldType)
{
HasThis = true,
Parameters =
{
new ParameterDefinition(module.ImportReference(equalityComparerInstantiation))
}
});
Ideally, this constructor would be public:
namespace Mono.Cecil
{
public sealed class GenericParameter : TypeReference, ICustomAttributeProvider
{
public GenericParameter(IGenericParameterProvider owner);
public GenericParameter(string name, IGenericParameterProvider owner);
+ public GenericParameter(
+ int position,
+ GenericParameterType type,
+ ModuleDefinition module);
}
}
Does this sound good to you?
Issue Analytics
- State:
- Created 4 years ago
- Comments:13 (5 by maintainers)
Maybe dnlib would work best for you?
https://github.com/0xd4d/dnlib
You want to emit:
Based on your code, the declaringType for the ctor is:
dictionaryField.FieldType
Which means that
dictionaryField.FieldType
is aGenericInstanceType
that is instantiatingDictionary<TKey,TValue>
with<string, string>
.So the
ElementType
of theGenericInstanceType
is going to be aTypeReference
, it’s going to have a.GenericParameters
collection.Basically, you want to use the
[0]
of theGenericParameters
of that instead of crafting your own.