2016-02-05 6 views
3

Использование Mono.Cecil, учитывая этот методСоздание Инструкция по типу

private Instruction LoadOnStack(MetadataType type, object value) 
{ 
    switch (type) 
    { 
     case MetadataType.String: 
      return _processor.Create(OpCodes.Ldstr, (string) value); 
     case MetadataType.Int32: 
      return _processor.Create(OpCodes.Ldc_I4, (Int32) value); 
     case MetadataType.Int64: 
      return _processor.Create(OpCodes.Ldc_I8, (Int64) value); 
     case MetadataType.Boolean: 
      return _processor.Create(OpCodes.Ldc_I4, (bool) value ? 1 : 0);     
    } 

    throw new NotSupportedException("Not a supported primitve parameter type: " + type); 
} 

Как я могу создать Instruction, который может загружать value, когда value имеет тип Type?

Я замечаю, когда value имеет тип Type, что я могу проверить это для него, как так:

if (value is TypeReference) 
    return _processor.Create(???, ???); 

Но я не могу понять, что мне нужно, чтобы перейти к Create, чтобы получить значение для правильной загрузки.

EDIT:

Используя это:

if (value is TypeReference) 
    return _processor.Create(OpCodes.Ldobj, type.Resolve()); 

Получает меня один шаг ближе. Кажется, он принимает тип. Но тогда, когда я пытаюсь написать сборку, это ошибка, говоря:

System.ArgumentException : Member 'System.Type' is declared in another module and needs to be imported 
+0

Я не знаком с тем, что доступно il; является отражением вариант? Вы могли бы искать '_processor' для метода' Create', второй аргумент которого имеет тип 'Type'? В качестве альтернативы, все может быть привязано к объекту ...? – object88

+0

Вы пытаетесь загрузить экземпляр объекта типа 'Type' в стек? – cubrr

+0

@ object88 Отражение в данном случае не является вариантом. И 'OpCodes' не имеют записи для' Type'. Я пробовал 'OpCodes.Ldobj',' OpCodes.Ldind_Ref' и еще несколько других, я не могу вспомнить – swestner

ответ

3

Как @cubrr уже указал на это:

Мы используем этот код для MethodBoundaryAspect.Fody

private IList<Instruction> LoadValueOnStack(TypeReference parameterType, object value, ModuleDefinition module) 
{ 
    if (parameterType.IsPrimitive || (parameterType.FullName == "System.String")) 
     return new List<Instruction> {LoadPrimitiveConstOnStack(parameterType.MetadataType, value)}; 

    if (parameterType.IsValueType) // enum 
    { 
     var enumUnderlyingType = GetEnumUnderlyingType(parameterType.Resolve()); 
     return new List<Instruction> {LoadPrimitiveConstOnStack(enumUnderlyingType.MetadataType, value)}; 
    } 

    if (parameterType.FullName == "System.Type") 
    { 
     var typeName = value.ToString(); 
     var typeReference = module.GetType(typeName, true); 

     var typeTypeRef = _referenceFinder.GetTypeReference(typeof (Type)); 
     var methodReference = _referenceFinder.GetMethodReference(typeTypeRef, md => md.Name == "GetTypeFromHandle"); 

     var instructions = new List<Instruction> 
     { 
      _processor.Create(OpCodes.Ldtoken, typeReference), 
      _processor.Create(OpCodes.Call, methodReference) 
     }; 

     return instructions; 
    } 

    throw new NotSupportedException("Parametertype: " + parameterType); 
} 

private Instruction LoadPrimitiveConstOnStack(MetadataType type, object value) 
{ 
    switch (type) 
    { 
     case MetadataType.String: 
      return _processor.Create(OpCodes.Ldstr, (string) value); 
     case MetadataType.Int32: 
      return _processor.Create(OpCodes.Ldc_I4, (int) value); 
     case MetadataType.Int64: 
      return _processor.Create(OpCodes.Ldc_I8, (long) value); 
     case MetadataType.Boolean: 
      return _processor.Create(OpCodes.Ldc_I4, (bool) value ? 1 : 0); 
    } 

    throw new NotSupportedException("Not a supported primitive parameter type: " + type); 
} 

private static TypeReference GetEnumUnderlyingType(TypeDefinition self) 
{ 
    foreach (var field in self.Fields) 
    { 
     if (field.Name == "value__") 
      return field.FieldType; 
    } 

    throw new ArgumentException(); 
} 

где класс ReferenceFinder это:

private readonly ModuleDefinition _moduleDefinition; 

public ReferenceFinder(ModuleDefinition moduleDefinition) 
{ 
    _moduleDefinition = moduleDefinition; 
} 

public MethodReference GetMethodReference(Type declaringType, Func<MethodDefinition, bool> predicate) 
{ 
    return GetMethodReference(GetTypeReference(declaringType), predicate); 
} 

public MethodReference GetMethodReference(TypeReference typeReference, Func<MethodDefinition, bool> predicate) 
{ 
    var typeDefinition = typeReference.Resolve(); 

    MethodDefinition methodDefinition; 
    do 
    { 
     methodDefinition = typeDefinition.Methods.FirstOrDefault(predicate); 
     typeDefinition = typeDefinition.BaseType == null 
      ? null 
      : typeDefinition.BaseType.Resolve(); 
    } while (methodDefinition == null && typeDefinition != null); 

    return _moduleDefinition.Import(methodDefinition); 
} 

public TypeReference GetTypeReference(Type type) 
{ 
    return _moduleDefinition.Import(type); 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^