Я пытаюсь соткать вызов метода, используя Fody, чтобы исправить проблему, которая вызывает некоторую несовместимость между ReactiveUI и PropertyChanged.Fody
Теперь реализация работает отлично для всех моих тестовых случаев, кроме одного - переплетения это открытый тип c.
Вот важные биты:
- Создание ссылки на метод
//get the method to call
var reactiveExRaiseMethod = FindTypeDefinition("ReactiveUI.IReactiveObjectExtensions").GetMethods().Single(x => x.Name == "RaisePropertyChanged");
var reactiveExRaiseMethodRef = ModuleDefinition.ImportReference(reactiveExRaiseMethod);
var raiseMethod = reactiveExRaiseMethodRef.MakeGenericMethod(type);
Генерация IL
var il = method.Body.GetILProcessor();
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, raiseMethod);
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Ret);
MakeGenericMethod
(не уверен, что это правильно - можно найти в другом сообщении по пути)
public static MethodReference MakeGenericMethod(this MethodReference self, params TypeReference[] arguments)
{
if (self.GenericParameters.Count != arguments.Length)
throw new ArgumentException();
var instance = new GenericInstanceMethod(self);
foreach (var argument in arguments)
instance.GenericArguments.Add(argument);
return instance;
}
Вызов этого кода
public class ReactiveObjectPropertyChangeFix : BaseModuleWeaver
{
public override void Execute()
{
foreach (var type in ModuleDefinition.Types)
{
VisitType(type); //this subsequently passes this reference to the code shown above
}
Запустив его, он отлично работает для всего, кроме open generi c type
Когда я смотрю на сгенерированный код в ILSpy, я вижу что он генерирует это:
public class MyReactiveObject<T> : ReactiveObject
{
protected void OnPropertyChanged(string propertyName)
{
((MyReactiveObject<>)this).RaisePropertyChanged(propertyName);
}
}
Вместо этого (взято из проходящего тестового объекта):
public class MyReactiveObject : ReactiveObject
{
protected void OnPropertyChanged(string propertyName)
{
this.RaisePropertyChanged(propertyName);
}
}
Я знаю, что что-то не так с ссылкой, созданной MakeGenericReference()
но я не могу понять, что это, ошибка при запуске кода на закрытом экземпляре generi c (например, MyReactiveObject<string>
):
System.TypeLoadException: не удалось загрузить тип 'Weavers.Tests.MyReactiveObject`1' из сборки 'Weavers.Tests, версия = 1.0.0.0, культура = нейтральная, PublicKeyToken = null'.