2012-01-31 2 views
1

У меня есть следующий класс A.Reflection.Emit code вызывает «base». вместо этого." на булевой поле

public class A 
{ 
    public string Name { get; set; } 
} 

мне нужно излучать динамический прокси, используя Reflection.Emit переопределить Equals.

// This class must be generated by Reflection.Emit. 
public class AProxy : A 
{ 
    private bool equalsHasBeenCalled; 

    public override bool Equals(object obj) 
    { 
     if (this.equalsHasBeenCalled) 
     { 
      return base.Equals(obj); 
     } 

     this.equalsHasBeenCalled = true; 

     return CaseInsensitiveComparer.Equals(this, obj); // Demo. 
    } 
} 

Однако фактический сгенерированный код (если смотреть с отражателем) составляет:

public class AProxy : A 
{ 
    private bool equalsHasBeenCalled; 

    public override bool Equals(object obj) 
    { 
     if (base.equalsHasBeenCalled) 
     { 
      return base.Equals(obj); 
     } 

     base.equalsHasBeenCalled = true; 

     return CaseInsensitiveComparer.Equals(this, obj); 
    } 
} 

..which конечно бросает System.FieldAccessException (так как нет такого участника не существует). Правильно это позвонить this.equalsHasBeenCalled (не base.equalsHasBeenCalled).

Я использую Reflection.Emit надстройка для Отражатель для генерации кода (field1 является FieldInfo для «equalsHasBeenCalled» поле):

 // Writing body 
     gen.Emit(OpCodes.Nop); 

     // I suspect it has to be around here. 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldfld, field1); 
     gen.Emit(OpCodes.Ldc_I4_0); 

     gen.Emit(OpCodes.Ceq); 
     gen.Emit(OpCodes.Stloc_1); 
     gen.Emit(OpCodes.Ldloc_1); 
     gen.Emit(OpCodes.Brtrue_S, label25); 
     gen.Emit(OpCodes.Nop); 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldarg_1); 
     gen.Emit(OpCodes.Call, method2); 
     gen.Emit(OpCodes.Stloc_0); 
     gen.Emit(OpCodes.Br_S, label42); 
     gen.MarkLabel(label25); 

     // ..and probably here also? 
     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldc_I4_1); 
     gen.Emit(OpCodes.Stfld, field1); 

     gen.Emit(OpCodes.Ldarg_0); 
     gen.Emit(OpCodes.Ldarg_1); 
     gen.Emit(OpCodes.Call, method3); 
     gen.Emit(OpCodes.Stloc_0); 
     gen.Emit(OpCodes.Br_S, label42); 
     gen.MarkLabel(label42); 
     gen.Emit(OpCodes.Ldloc_0); 
     gen.Emit(OpCodes.Ret); 
+0

Итак, как вы видите этот выход? Звучит как сломанный декомпилятор ... – leppie

+0

Почему бы вам не показать свой собственный код для Reflection.Emit? – leppie

+3

Почему вы не пишете то, что вам нужно на C#, декомпилируйте IL и посмотрите, как он настроен? Кроме того, если вам нужно сделать что-то подобное в своем проекте, я предлагаю вам заглянуть в Castle DynamicProxy. –

ответ

3

Почему вы не пишете то, что вам нужно на C#, декомпилируйте IL и посмотрите, как он настроен? Кроме того, если вам нужно сделать что-то подобное в своем проекте, я предлагаю вам заглянуть в Castle DynamicProxy.

+0

Это было лучшее, что нужно сделать. Посмотрев на сгенерированный IL, я обнаружил, что сгенерированный код Reflection.Emit был Верно, что я поставил поле «FieldInfo» для «field1», в то время как мне пришлось предоставить экземпляр FieldBuilder для «field1». Все работает. Взгляд на IL был поучительным! –

0

Возможно, это ключевое слово запускающего ошибка в Reflection.Emit, чтобы он генерировал неправильный код. Попробуйте удалить его, поскольку он на самом деле ничего не делает, нет другого equalsHasBeenCalled, который вам нужно устранить с помощью этого ключевого слова.

+0

Да, 'this' и' base' не существует в IL. – leppie

+0

Я попытался удалить его, но все же .. –

+0

@leppie Я предполагал, что из его описания он компилировал код в своем первом примере в IL и затем использовал add in to для генерации кода reflection.emit. –

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

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