如何创建自定义Reactive属性?

问题描述 投票:0回答:1

我在 WPF 应用程序中使用响应式 UI 库,并且很好奇 [Reactive] 属性如何工作。我发现该属性本身没有任何内容,因此对其实际工作有很多疑问。然后我找到了加载当前程序集的代码段(使用 Mono.CecilFody 库),查找扩展 ReactiveObject 类的所有类,并在那里搜索 [Reactive] 属性(原始源) :

var reactiveObject = new TypeReference("ReactiveUI", "IReactiveObject", ModuleDefinition, reactiveUI);
var targetTypes = ModuleDefinition.GetAllTypes().Where(x => x.BaseType is not null && reactiveObject.IsAssignableFrom(x.BaseType)).ToArray();
var reactiveObjectExtensions = new TypeReference("ReactiveUI", "IReactiveObjectExtensions", ModuleDefinition, reactiveUI).Resolve() ?? throw new Exception("reactiveObjectExtensions is null");
var raiseAndSetIfChangedMethod = ModuleDefinition.ImportReference(reactiveObjectExtensions.Methods.Single(x => x.Name == "RaiseAndSetIfChanged")) ?? throw new Exception("raiseAndSetIfChangedMethod is null");
var reactiveAttribute = ModuleDefinition.FindType("ReactiveUI.Fody.Helpers", "ReactiveAttribute", helpers) ?? throw new Exception("reactiveAttribute is null");

然后为每个属性创建私有字段并绑定一个方法(调用 PropertyChanged 事件)。
一切都很清楚,所以我决定为该属性创建自己的属性和属性解析器,但现在我有一个明显的问题。当解析器更改 IL 代码时 - 它应该重写当前程序集(据我所知))。我对预构建和构建后的事情了解不多,但我认为这些事情不应该在已经运行的程序集中完成,而应该在预构建操作的某个地方完成。这是我实际编写的代码(它压在

module.Write(Assembly.GetExecutingAssembly().Location);
行上(很明显导致当前汇编文件被锁定)):

var module = ModuleDefinition.ReadModule(Assembly.GetExecutingAssembly().Location);
var reactiveResolver = new ReactivePropertyResolver()
{
    ModuleDefinition = module,
};
reactiveResolver.Execute();
module.Write(Assembly.GetExecutingAssembly().Location);
module?.Dispose();

我在 ReactivePropertyResolver 中几乎没有更改任何内容,只更改了一些名称空间和其他小东西。

所以主要问题是 - 我应该在哪里以及如何做所有这些事情才能让它发挥作用?

(我已经问过有关软件工程 SE 的问题,但被否决了 - 很好奇:/ )

c# reflection mono .net-assembly reactive
1个回答
0
投票

好吧,毕竟这一次可以告诉你,创建自定义属性最简单的方法是使用Fody。首先我找到了一个名为 PostSharp 的库,但它不是免费的。然后我尝试使用纯 Mono.Cecil (正如你在问题中看到的那样),但放弃了 MSBuild 疯狂的事情。也许我对这些东西太愚蠢了,比如 AfterBuild 命令等等。
我不想使用 Fody,因为它的配置 .xml.xsd 文件应该位于项目结构的顶部。但现在对我来说没问题,也许我可以摆脱它们(应该测试一下)。
现在对我来说最终的答案是 我基于这些存储库创建的存储库 - PropertyChangedReactiveUIMethodBoundaryAspectFody

© www.soinside.com 2019 - 2024. All rights reserved.