ef583813eb
Former-commit-id: 943baa9f16a098c33e129777827f3a9d20da00d6
814 lines
24 KiB
C#
814 lines
24 KiB
C#
//
|
|
// Author:
|
|
// Jb Evain (jbevain@gmail.com)
|
|
//
|
|
// Copyright (c) 2008 - 2015 Jb Evain
|
|
// Copyright (c) 2008 - 2011 Novell, Inc.
|
|
//
|
|
// Licensed under the MIT/X11 license.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Mono.Collections.Generic;
|
|
using SR = System.Reflection;
|
|
|
|
using Mono.Cecil.Metadata;
|
|
|
|
namespace Mono.Cecil {
|
|
|
|
public interface IMetadataImporterProvider {
|
|
IMetadataImporter GetMetadataImporter (ModuleDefinition module);
|
|
}
|
|
|
|
public interface IMetadataImporter {
|
|
AssemblyNameReference ImportReference (AssemblyNameReference reference);
|
|
TypeReference ImportReference (TypeReference type, IGenericParameterProvider context);
|
|
FieldReference ImportReference (FieldReference field, IGenericParameterProvider context);
|
|
MethodReference ImportReference (MethodReference method, IGenericParameterProvider context);
|
|
}
|
|
|
|
public interface IReflectionImporterProvider {
|
|
IReflectionImporter GetReflectionImporter (ModuleDefinition module);
|
|
}
|
|
|
|
public interface IReflectionImporter {
|
|
AssemblyNameReference ImportReference (SR.AssemblyName reference);
|
|
TypeReference ImportReference (Type type, IGenericParameterProvider context);
|
|
FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context);
|
|
MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context);
|
|
}
|
|
|
|
struct ImportGenericContext {
|
|
|
|
Collection<IGenericParameterProvider> stack;
|
|
|
|
public bool IsEmpty { get { return stack == null; } }
|
|
|
|
public ImportGenericContext (IGenericParameterProvider provider)
|
|
{
|
|
if (provider == null)
|
|
throw new ArgumentNullException ("provider");
|
|
|
|
stack = null;
|
|
|
|
Push (provider);
|
|
}
|
|
|
|
public void Push (IGenericParameterProvider provider)
|
|
{
|
|
if (stack == null)
|
|
stack = new Collection<IGenericParameterProvider> (1) { provider };
|
|
else
|
|
stack.Add (provider);
|
|
}
|
|
|
|
public void Pop ()
|
|
{
|
|
stack.RemoveAt (stack.Count - 1);
|
|
}
|
|
|
|
public TypeReference MethodParameter (string method, int position)
|
|
{
|
|
for (int i = stack.Count - 1; i >= 0; i--) {
|
|
var candidate = stack [i] as MethodReference;
|
|
if (candidate == null)
|
|
continue;
|
|
|
|
if (method != NormalizeMethodName (candidate))
|
|
continue;
|
|
|
|
return candidate.GenericParameters [position];
|
|
}
|
|
|
|
throw new InvalidOperationException ();
|
|
}
|
|
|
|
public string NormalizeMethodName (MethodReference method)
|
|
{
|
|
return method.DeclaringType.GetElementType ().FullName + "." + method.Name;
|
|
}
|
|
|
|
public TypeReference TypeParameter (string type, int position)
|
|
{
|
|
for (int i = stack.Count - 1; i >= 0; i--) {
|
|
var candidate = GenericTypeFor (stack [i]);
|
|
|
|
if (candidate.FullName != type)
|
|
continue;
|
|
|
|
return candidate.GenericParameters [position];
|
|
}
|
|
|
|
throw new InvalidOperationException ();
|
|
}
|
|
|
|
static TypeReference GenericTypeFor (IGenericParameterProvider context)
|
|
{
|
|
var type = context as TypeReference;
|
|
if (type != null)
|
|
return type.GetElementType ();
|
|
|
|
var method = context as MethodReference;
|
|
if (method != null)
|
|
return method.DeclaringType.GetElementType ();
|
|
|
|
throw new InvalidOperationException ();
|
|
}
|
|
|
|
public static ImportGenericContext For (IGenericParameterProvider context)
|
|
{
|
|
return context != null ? new ImportGenericContext (context) : default (ImportGenericContext);
|
|
}
|
|
}
|
|
|
|
public class DefaultReflectionImporter : IReflectionImporter {
|
|
|
|
readonly protected ModuleDefinition module;
|
|
|
|
public DefaultReflectionImporter (ModuleDefinition module)
|
|
{
|
|
Mixin.CheckModule (module);
|
|
|
|
this.module = module;
|
|
}
|
|
|
|
enum ImportGenericKind {
|
|
Definition,
|
|
Open,
|
|
}
|
|
|
|
static readonly Dictionary<Type, ElementType> type_etype_mapping = new Dictionary<Type, ElementType> (18) {
|
|
{ typeof (void), ElementType.Void },
|
|
{ typeof (bool), ElementType.Boolean },
|
|
{ typeof (char), ElementType.Char },
|
|
{ typeof (sbyte), ElementType.I1 },
|
|
{ typeof (byte), ElementType.U1 },
|
|
{ typeof (short), ElementType.I2 },
|
|
{ typeof (ushort), ElementType.U2 },
|
|
{ typeof (int), ElementType.I4 },
|
|
{ typeof (uint), ElementType.U4 },
|
|
{ typeof (long), ElementType.I8 },
|
|
{ typeof (ulong), ElementType.U8 },
|
|
{ typeof (float), ElementType.R4 },
|
|
{ typeof (double), ElementType.R8 },
|
|
{ typeof (string), ElementType.String },
|
|
{ typeof (TypedReference), ElementType.TypedByRef },
|
|
{ typeof (IntPtr), ElementType.I },
|
|
{ typeof (UIntPtr), ElementType.U },
|
|
{ typeof (object), ElementType.Object },
|
|
};
|
|
|
|
TypeReference ImportType (Type type, ImportGenericContext context)
|
|
{
|
|
return ImportType (type, context, ImportGenericKind.Open);
|
|
}
|
|
|
|
TypeReference ImportType (Type type, ImportGenericContext context, ImportGenericKind import_kind)
|
|
{
|
|
if (IsTypeSpecification (type) || ImportOpenGenericType (type, import_kind))
|
|
return ImportTypeSpecification (type, context);
|
|
|
|
var reference = new TypeReference (
|
|
string.Empty,
|
|
type.Name,
|
|
module,
|
|
ImportScope (type),
|
|
type.IsValueType);
|
|
|
|
reference.etype = ImportElementType (type);
|
|
|
|
if (IsNestedType (type))
|
|
reference.DeclaringType = ImportType (type.DeclaringType, context, import_kind);
|
|
else
|
|
reference.Namespace = type.Namespace ?? string.Empty;
|
|
|
|
if (type.IsGenericType)
|
|
ImportGenericParameters (reference, type.GetGenericArguments ());
|
|
|
|
return reference;
|
|
}
|
|
|
|
protected virtual IMetadataScope ImportScope (Type type)
|
|
{
|
|
return ImportScope (type.Assembly);
|
|
}
|
|
|
|
static bool ImportOpenGenericType (Type type, ImportGenericKind import_kind)
|
|
{
|
|
return type.IsGenericType && type.IsGenericTypeDefinition && import_kind == ImportGenericKind.Open;
|
|
}
|
|
|
|
static bool ImportOpenGenericMethod (SR.MethodBase method, ImportGenericKind import_kind)
|
|
{
|
|
return method.IsGenericMethod && method.IsGenericMethodDefinition && import_kind == ImportGenericKind.Open;
|
|
}
|
|
|
|
static bool IsNestedType (Type type)
|
|
{
|
|
return type.IsNested;
|
|
}
|
|
|
|
TypeReference ImportTypeSpecification (Type type, ImportGenericContext context)
|
|
{
|
|
if (type.IsByRef)
|
|
return new ByReferenceType (ImportType (type.GetElementType (), context));
|
|
|
|
if (type.IsPointer)
|
|
return new PointerType (ImportType (type.GetElementType (), context));
|
|
|
|
if (type.IsArray)
|
|
return new ArrayType (ImportType (type.GetElementType (), context), type.GetArrayRank ());
|
|
|
|
if (type.IsGenericType)
|
|
return ImportGenericInstance (type, context);
|
|
|
|
if (type.IsGenericParameter)
|
|
return ImportGenericParameter (type, context);
|
|
|
|
throw new NotSupportedException (type.FullName);
|
|
}
|
|
|
|
static TypeReference ImportGenericParameter (Type type, ImportGenericContext context)
|
|
{
|
|
if (context.IsEmpty)
|
|
throw new InvalidOperationException ();
|
|
|
|
if (type.DeclaringMethod != null)
|
|
return context.MethodParameter (NormalizeMethodName (type.DeclaringMethod), type.GenericParameterPosition);
|
|
|
|
if (type.DeclaringType != null)
|
|
return context.TypeParameter (NormalizeTypeFullName (type.DeclaringType), type.GenericParameterPosition);
|
|
|
|
throw new InvalidOperationException();
|
|
}
|
|
|
|
static string NormalizeMethodName (SR.MethodBase method)
|
|
{
|
|
return NormalizeTypeFullName (method.DeclaringType) + "." + method.Name;
|
|
}
|
|
|
|
static string NormalizeTypeFullName (Type type)
|
|
{
|
|
if (IsNestedType (type))
|
|
return NormalizeTypeFullName (type.DeclaringType) + "/" + type.Name;
|
|
|
|
return type.FullName;
|
|
}
|
|
|
|
TypeReference ImportGenericInstance (Type type, ImportGenericContext context)
|
|
{
|
|
var element_type = ImportType (type.GetGenericTypeDefinition (), context, ImportGenericKind.Definition);
|
|
var instance = new GenericInstanceType (element_type);
|
|
var arguments = type.GetGenericArguments ();
|
|
var instance_arguments = instance.GenericArguments;
|
|
|
|
context.Push (element_type);
|
|
try {
|
|
for (int i = 0; i < arguments.Length; i++)
|
|
instance_arguments.Add (ImportType (arguments [i], context));
|
|
|
|
return instance;
|
|
} finally {
|
|
context.Pop ();
|
|
}
|
|
}
|
|
|
|
static bool IsTypeSpecification (Type type)
|
|
{
|
|
return type.HasElementType
|
|
|| IsGenericInstance (type)
|
|
|| type.IsGenericParameter;
|
|
}
|
|
|
|
static bool IsGenericInstance (Type type)
|
|
{
|
|
return type.IsGenericType && !type.IsGenericTypeDefinition;
|
|
}
|
|
|
|
static ElementType ImportElementType (Type type)
|
|
{
|
|
ElementType etype;
|
|
if (!type_etype_mapping.TryGetValue (type, out etype))
|
|
return ElementType.None;
|
|
|
|
return etype;
|
|
}
|
|
|
|
protected AssemblyNameReference ImportScope (SR.Assembly assembly)
|
|
{
|
|
return ImportReference (assembly.GetName ());
|
|
}
|
|
|
|
public virtual AssemblyNameReference ImportReference (SR.AssemblyName name)
|
|
{
|
|
Mixin.CheckName (name);
|
|
|
|
AssemblyNameReference reference;
|
|
if (TryGetAssemblyNameReference (name, out reference))
|
|
return reference;
|
|
|
|
reference = new AssemblyNameReference (name.Name, name.Version)
|
|
{
|
|
PublicKeyToken = name.GetPublicKeyToken (),
|
|
Culture = name.CultureInfo.Name,
|
|
HashAlgorithm = (AssemblyHashAlgorithm) name.HashAlgorithm,
|
|
};
|
|
|
|
module.AssemblyReferences.Add (reference);
|
|
|
|
return reference;
|
|
}
|
|
|
|
bool TryGetAssemblyNameReference (SR.AssemblyName name, out AssemblyNameReference assembly_reference)
|
|
{
|
|
var references = module.AssemblyReferences;
|
|
|
|
for (int i = 0; i < references.Count; i++) {
|
|
var reference = references [i];
|
|
if (name.FullName != reference.FullName) // TODO compare field by field
|
|
continue;
|
|
|
|
assembly_reference = reference;
|
|
return true;
|
|
}
|
|
|
|
assembly_reference = null;
|
|
return false;
|
|
}
|
|
|
|
FieldReference ImportField (SR.FieldInfo field, ImportGenericContext context)
|
|
{
|
|
var declaring_type = ImportType (field.DeclaringType, context);
|
|
|
|
if (IsGenericInstance (field.DeclaringType))
|
|
field = ResolveFieldDefinition (field);
|
|
|
|
context.Push (declaring_type);
|
|
try {
|
|
return new FieldReference {
|
|
Name = field.Name,
|
|
DeclaringType = declaring_type,
|
|
FieldType = ImportType (field.FieldType, context),
|
|
};
|
|
} finally {
|
|
context.Pop ();
|
|
}
|
|
}
|
|
|
|
static SR.FieldInfo ResolveFieldDefinition (SR.FieldInfo field)
|
|
{
|
|
return field.Module.ResolveField (field.MetadataToken);
|
|
}
|
|
|
|
static SR.MethodBase ResolveMethodDefinition (SR.MethodBase method)
|
|
{
|
|
return method.Module.ResolveMethod (method.MetadataToken);
|
|
}
|
|
|
|
MethodReference ImportMethod (SR.MethodBase method, ImportGenericContext context, ImportGenericKind import_kind)
|
|
{
|
|
if (IsMethodSpecification (method) || ImportOpenGenericMethod (method, import_kind))
|
|
return ImportMethodSpecification (method, context);
|
|
|
|
var declaring_type = ImportType (method.DeclaringType, context);
|
|
|
|
if (IsGenericInstance (method.DeclaringType))
|
|
method = ResolveMethodDefinition (method);
|
|
|
|
var reference = new MethodReference {
|
|
Name = method.Name,
|
|
HasThis = HasCallingConvention (method, SR.CallingConventions.HasThis),
|
|
ExplicitThis = HasCallingConvention (method, SR.CallingConventions.ExplicitThis),
|
|
DeclaringType = ImportType (method.DeclaringType, context, ImportGenericKind.Definition),
|
|
};
|
|
|
|
if (HasCallingConvention (method, SR.CallingConventions.VarArgs))
|
|
reference.CallingConvention &= MethodCallingConvention.VarArg;
|
|
|
|
if (method.IsGenericMethod)
|
|
ImportGenericParameters (reference, method.GetGenericArguments ());
|
|
|
|
context.Push (reference);
|
|
try {
|
|
var method_info = method as SR.MethodInfo;
|
|
reference.ReturnType = method_info != null
|
|
? ImportType (method_info.ReturnType, context)
|
|
: ImportType (typeof (void), default (ImportGenericContext));
|
|
|
|
var parameters = method.GetParameters ();
|
|
var reference_parameters = reference.Parameters;
|
|
|
|
for (int i = 0; i < parameters.Length; i++)
|
|
reference_parameters.Add (
|
|
new ParameterDefinition (ImportType (parameters [i].ParameterType, context)));
|
|
|
|
reference.DeclaringType = declaring_type;
|
|
|
|
return reference;
|
|
} finally {
|
|
context.Pop ();
|
|
}
|
|
}
|
|
|
|
static void ImportGenericParameters (IGenericParameterProvider provider, Type [] arguments)
|
|
{
|
|
var provider_parameters = provider.GenericParameters;
|
|
|
|
for (int i = 0; i < arguments.Length; i++)
|
|
provider_parameters.Add (new GenericParameter (arguments [i].Name, provider));
|
|
}
|
|
|
|
static bool IsMethodSpecification (SR.MethodBase method)
|
|
{
|
|
return method.IsGenericMethod && !method.IsGenericMethodDefinition;
|
|
}
|
|
|
|
MethodReference ImportMethodSpecification (SR.MethodBase method, ImportGenericContext context)
|
|
{
|
|
var method_info = method as SR.MethodInfo;
|
|
if (method_info == null)
|
|
throw new InvalidOperationException ();
|
|
|
|
var element_method = ImportMethod (method_info.GetGenericMethodDefinition (), context, ImportGenericKind.Definition);
|
|
var instance = new GenericInstanceMethod (element_method);
|
|
var arguments = method.GetGenericArguments ();
|
|
var instance_arguments = instance.GenericArguments;
|
|
|
|
context.Push (element_method);
|
|
try {
|
|
for (int i = 0; i < arguments.Length; i++)
|
|
instance_arguments.Add (ImportType (arguments [i], context));
|
|
|
|
return instance;
|
|
} finally {
|
|
context.Pop ();
|
|
}
|
|
}
|
|
|
|
static bool HasCallingConvention (SR.MethodBase method, SR.CallingConventions conventions)
|
|
{
|
|
return (method.CallingConvention & conventions) != 0;
|
|
}
|
|
|
|
public virtual TypeReference ImportReference (Type type, IGenericParameterProvider context)
|
|
{
|
|
Mixin.CheckType (type);
|
|
return ImportType (
|
|
type,
|
|
ImportGenericContext.For (context),
|
|
context != null ? ImportGenericKind.Open : ImportGenericKind.Definition);
|
|
}
|
|
|
|
public virtual FieldReference ImportReference (SR.FieldInfo field, IGenericParameterProvider context)
|
|
{
|
|
Mixin.CheckField (field);
|
|
return ImportField (field, ImportGenericContext.For (context));
|
|
}
|
|
|
|
public virtual MethodReference ImportReference (SR.MethodBase method, IGenericParameterProvider context)
|
|
{
|
|
Mixin.CheckMethod (method);
|
|
return ImportMethod (method,
|
|
ImportGenericContext.For (context),
|
|
context != null ? ImportGenericKind.Open : ImportGenericKind.Definition);
|
|
}
|
|
}
|
|
|
|
public class DefaultMetadataImporter : IMetadataImporter {
|
|
|
|
readonly protected ModuleDefinition module;
|
|
|
|
public DefaultMetadataImporter (ModuleDefinition module)
|
|
{
|
|
Mixin.CheckModule (module);
|
|
|
|
this.module = module;
|
|
}
|
|
|
|
internal virtual TypeReference ImportType (TypeReference type, ImportGenericContext context)
|
|
{
|
|
if (type.IsTypeSpecification ())
|
|
return ImportTypeSpecification (type, context);
|
|
|
|
var reference = new TypeReference (
|
|
type.Namespace,
|
|
type.Name,
|
|
module,
|
|
ImportScope (type),
|
|
type.IsValueType);
|
|
|
|
MetadataSystem.TryProcessPrimitiveTypeReference (reference);
|
|
|
|
if (type.IsNested)
|
|
reference.DeclaringType = ImportType (type.DeclaringType, context);
|
|
|
|
if (type.HasGenericParameters)
|
|
ImportGenericParameters (reference, type);
|
|
|
|
return reference;
|
|
}
|
|
|
|
protected virtual IMetadataScope ImportScope (TypeReference type)
|
|
{
|
|
return ImportScope (type.Scope);
|
|
}
|
|
|
|
protected IMetadataScope ImportScope (IMetadataScope scope)
|
|
{
|
|
switch (scope.MetadataScopeType) {
|
|
case MetadataScopeType.AssemblyNameReference:
|
|
return ImportReference ((AssemblyNameReference) scope);
|
|
case MetadataScopeType.ModuleDefinition:
|
|
if (scope == module) return scope;
|
|
return ImportReference (((ModuleDefinition) scope).Assembly.Name);
|
|
case MetadataScopeType.ModuleReference:
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
public virtual AssemblyNameReference ImportReference (AssemblyNameReference name)
|
|
{
|
|
Mixin.CheckName (name);
|
|
|
|
AssemblyNameReference reference;
|
|
if (module.TryGetAssemblyNameReference (name, out reference))
|
|
return reference;
|
|
|
|
reference = new AssemblyNameReference (name.Name, name.Version) {
|
|
Culture = name.Culture,
|
|
HashAlgorithm = name.HashAlgorithm,
|
|
IsRetargetable = name.IsRetargetable,
|
|
IsWindowsRuntime = name.IsWindowsRuntime,
|
|
};
|
|
|
|
var pk_token = !name.PublicKeyToken.IsNullOrEmpty ()
|
|
? new byte [name.PublicKeyToken.Length]
|
|
: Empty<byte>.Array;
|
|
|
|
if (pk_token.Length > 0)
|
|
Buffer.BlockCopy (name.PublicKeyToken, 0, pk_token, 0, pk_token.Length);
|
|
|
|
reference.PublicKeyToken = pk_token;
|
|
|
|
module.AssemblyReferences.Add (reference);
|
|
|
|
return reference;
|
|
}
|
|
|
|
static void ImportGenericParameters (IGenericParameterProvider imported, IGenericParameterProvider original)
|
|
{
|
|
var parameters = original.GenericParameters;
|
|
var imported_parameters = imported.GenericParameters;
|
|
|
|
for (int i = 0; i < parameters.Count; i++)
|
|
imported_parameters.Add (new GenericParameter (parameters [i].Name, imported));
|
|
}
|
|
|
|
TypeReference ImportTypeSpecification (TypeReference type, ImportGenericContext context)
|
|
{
|
|
switch (type.etype) {
|
|
case ElementType.SzArray:
|
|
var vector = (ArrayType) type;
|
|
return new ArrayType (ImportType (vector.ElementType, context));
|
|
case ElementType.Ptr:
|
|
var pointer = (PointerType) type;
|
|
return new PointerType (ImportType (pointer.ElementType, context));
|
|
case ElementType.ByRef:
|
|
var byref = (ByReferenceType) type;
|
|
return new ByReferenceType (ImportType (byref.ElementType, context));
|
|
case ElementType.Pinned:
|
|
var pinned = (PinnedType) type;
|
|
return new PinnedType (ImportType (pinned.ElementType, context));
|
|
case ElementType.Sentinel:
|
|
var sentinel = (SentinelType) type;
|
|
return new SentinelType (ImportType (sentinel.ElementType, context));
|
|
case ElementType.FnPtr:
|
|
var fnptr = (FunctionPointerType) type;
|
|
var imported_fnptr = new FunctionPointerType () {
|
|
HasThis = fnptr.HasThis,
|
|
ExplicitThis = fnptr.ExplicitThis,
|
|
CallingConvention = fnptr.CallingConvention,
|
|
ReturnType = ImportType (fnptr.ReturnType, context),
|
|
};
|
|
|
|
if (!fnptr.HasParameters)
|
|
return imported_fnptr;
|
|
|
|
for (int i = 0; i < fnptr.Parameters.Count; i++)
|
|
imported_fnptr.Parameters.Add (new ParameterDefinition (
|
|
ImportType (fnptr.Parameters [i].ParameterType, context)));
|
|
|
|
return imported_fnptr;
|
|
case ElementType.CModOpt:
|
|
var modopt = (OptionalModifierType) type;
|
|
return new OptionalModifierType (
|
|
ImportType (modopt.ModifierType, context),
|
|
ImportType (modopt.ElementType, context));
|
|
case ElementType.CModReqD:
|
|
var modreq = (RequiredModifierType) type;
|
|
return new RequiredModifierType (
|
|
ImportType (modreq.ModifierType, context),
|
|
ImportType (modreq.ElementType, context));
|
|
case ElementType.Array:
|
|
var array = (ArrayType) type;
|
|
var imported_array = new ArrayType (ImportType (array.ElementType, context));
|
|
if (array.IsVector)
|
|
return imported_array;
|
|
|
|
var dimensions = array.Dimensions;
|
|
var imported_dimensions = imported_array.Dimensions;
|
|
|
|
imported_dimensions.Clear ();
|
|
|
|
for (int i = 0; i < dimensions.Count; i++) {
|
|
var dimension = dimensions [i];
|
|
|
|
imported_dimensions.Add (new ArrayDimension (dimension.LowerBound, dimension.UpperBound));
|
|
}
|
|
|
|
return imported_array;
|
|
case ElementType.GenericInst:
|
|
var instance = (GenericInstanceType) type;
|
|
var element_type = ImportType (instance.ElementType, context);
|
|
var imported_instance = new GenericInstanceType (element_type);
|
|
|
|
var arguments = instance.GenericArguments;
|
|
var imported_arguments = imported_instance.GenericArguments;
|
|
|
|
for (int i = 0; i < arguments.Count; i++)
|
|
imported_arguments.Add (ImportType (arguments [i], context));
|
|
|
|
return imported_instance;
|
|
case ElementType.Var:
|
|
var var_parameter = (GenericParameter) type;
|
|
if (var_parameter.DeclaringType == null)
|
|
throw new InvalidOperationException ();
|
|
return context.TypeParameter (var_parameter.DeclaringType.FullName, var_parameter.Position);
|
|
case ElementType.MVar:
|
|
var mvar_parameter = (GenericParameter) type;
|
|
if (mvar_parameter.DeclaringMethod == null)
|
|
throw new InvalidOperationException ();
|
|
return context.MethodParameter (context.NormalizeMethodName (mvar_parameter.DeclaringMethod), mvar_parameter.Position);
|
|
}
|
|
|
|
throw new NotSupportedException (type.etype.ToString ());
|
|
}
|
|
|
|
FieldReference ImportField (FieldReference field, ImportGenericContext context)
|
|
{
|
|
var declaring_type = ImportType (field.DeclaringType, context);
|
|
|
|
context.Push (declaring_type);
|
|
try {
|
|
return new FieldReference {
|
|
Name = field.Name,
|
|
DeclaringType = declaring_type,
|
|
FieldType = ImportType (field.FieldType, context),
|
|
};
|
|
} finally {
|
|
context.Pop ();
|
|
}
|
|
}
|
|
|
|
MethodReference ImportMethod (MethodReference method, ImportGenericContext context)
|
|
{
|
|
if (method.IsGenericInstance)
|
|
return ImportMethodSpecification (method, context);
|
|
|
|
var declaring_type = ImportType (method.DeclaringType, context);
|
|
|
|
var reference = new MethodReference {
|
|
Name = method.Name,
|
|
HasThis = method.HasThis,
|
|
ExplicitThis = method.ExplicitThis,
|
|
DeclaringType = declaring_type,
|
|
CallingConvention = method.CallingConvention,
|
|
};
|
|
|
|
if (method.HasGenericParameters)
|
|
ImportGenericParameters (reference, method);
|
|
|
|
context.Push (reference);
|
|
try {
|
|
reference.ReturnType = ImportType (method.ReturnType, context);
|
|
|
|
if (!method.HasParameters)
|
|
return reference;
|
|
|
|
var parameters = method.Parameters;
|
|
var reference_parameters = reference.parameters = new ParameterDefinitionCollection (reference, parameters.Count);
|
|
for (int i = 0; i < parameters.Count; i++)
|
|
reference_parameters.Add (
|
|
new ParameterDefinition (ImportType (parameters [i].ParameterType, context)));
|
|
|
|
return reference;
|
|
} finally {
|
|
context.Pop();
|
|
}
|
|
}
|
|
|
|
MethodSpecification ImportMethodSpecification (MethodReference method, ImportGenericContext context)
|
|
{
|
|
if (!method.IsGenericInstance)
|
|
throw new NotSupportedException ();
|
|
|
|
var instance = (GenericInstanceMethod) method;
|
|
var element_method = ImportMethod (instance.ElementMethod, context);
|
|
var imported_instance = new GenericInstanceMethod (element_method);
|
|
|
|
var arguments = instance.GenericArguments;
|
|
var imported_arguments = imported_instance.GenericArguments;
|
|
|
|
for (int i = 0; i < arguments.Count; i++)
|
|
imported_arguments.Add (ImportType (arguments [i], context));
|
|
|
|
return imported_instance;
|
|
}
|
|
|
|
public virtual TypeReference ImportReference (TypeReference type, IGenericParameterProvider context)
|
|
{
|
|
Mixin.CheckType (type);
|
|
return ImportType (type, ImportGenericContext.For (context));
|
|
}
|
|
|
|
public virtual FieldReference ImportReference (FieldReference field, IGenericParameterProvider context)
|
|
{
|
|
Mixin.CheckField (field);
|
|
return ImportField (field, ImportGenericContext.For (context));
|
|
}
|
|
|
|
public virtual MethodReference ImportReference (MethodReference method, IGenericParameterProvider context)
|
|
{
|
|
Mixin.CheckMethod (method);
|
|
return ImportMethod (method, ImportGenericContext.For (context));
|
|
}
|
|
}
|
|
|
|
static partial class Mixin {
|
|
|
|
public static void CheckModule (ModuleDefinition module)
|
|
{
|
|
if (module == null)
|
|
throw new ArgumentNullException (Argument.module.ToString ());
|
|
}
|
|
|
|
public static bool TryGetAssemblyNameReference (this ModuleDefinition module, AssemblyNameReference name_reference, out AssemblyNameReference assembly_reference)
|
|
{
|
|
var references = module.AssemblyReferences;
|
|
|
|
for (int i = 0; i < references.Count; i++) {
|
|
var reference = references [i];
|
|
if (!Equals (name_reference, reference))
|
|
continue;
|
|
|
|
assembly_reference = reference;
|
|
return true;
|
|
}
|
|
|
|
assembly_reference = null;
|
|
return false;
|
|
}
|
|
|
|
static bool Equals (byte [] a, byte [] b)
|
|
{
|
|
if (ReferenceEquals (a, b))
|
|
return true;
|
|
if (a == null)
|
|
return false;
|
|
if (a.Length != b.Length)
|
|
return false;
|
|
for (int i = 0; i < a.Length; i++)
|
|
if (a [i] != b [i])
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static bool Equals<T> (T a, T b) where T : class, IEquatable<T>
|
|
{
|
|
if (ReferenceEquals (a, b))
|
|
return true;
|
|
if (a == null)
|
|
return false;
|
|
return a.Equals (b);
|
|
}
|
|
|
|
static bool Equals (AssemblyNameReference a, AssemblyNameReference b)
|
|
{
|
|
if (ReferenceEquals (a, b))
|
|
return true;
|
|
if (a.Name != b.Name)
|
|
return false;
|
|
if (!Equals (a.Version, b.Version))
|
|
return false;
|
|
if (a.Culture != b.Culture)
|
|
return false;
|
|
if (!Equals (a.PublicKeyToken, b.PublicKeyToken))
|
|
return false;
|
|
return true;
|
|
}
|
|
}
|
|
}
|