I18N icon indicating copy to clipboard operation
I18N copied to clipboard

Compiled Binding support for Avalonia

Open laolarou726 opened this issue 1 year ago • 6 comments

目前,在 Avalonia 11 开始。Avalonia 项目可以通过修改编译选项来全局开启 “编译绑定”。 启用编译绑定后可以完全舍弃基于反射的绑定,这对于需要启用 NativeAot 的平台(安卓与IOS)是非常关键的。

当前项目的内部实现依旧是使用基于反射的绑定类来实现多语言切换的。如果可以切换至纯编译绑定将会大幅度提升跨平台的可用性。 由于我暂时还没有完全掌握项目代码。因此,我可能无法提交 PR 😂,作者如果可以的话不知能否尝试将内部实现切换为编译绑定?

我这里可以提供一段我在自己项目内使用的一段 helper function 来帮助您创建编译绑定:

public static IDisposable CompiledBind(
        this AvaloniaObject bindTo,
        AvaloniaProperty bindToProperty,
        string bindingPath,
        object source,
        Type propertyType,
        Func<object, object?> getter,
        Action<object, object?>? setter = null)
    {
        var clrProperty = new ClrPropertyInfo(
            bindingPath,
            getter,
            setter,
            propertyType);

        var pathBuilder = new CompiledBindingPathBuilder();
        pathBuilder = pathBuilder.SetRawSource(source);
        pathBuilder = pathBuilder.Property(
            clrProperty,
            PropertyInfoAccessorFactory.CreateInpcPropertyAccessor);
        var path = pathBuilder.Build(); // 这里的 path 类型为 IBinding,可以直接用在其他地方

        var cb = new CompiledBindingExtension(path);
        var ib = cb.Initiate(bindTo, bindToProperty)!;

        return BindingOperations.Apply(bindTo, bindToProperty, ib, null);
}

laolarou726 avatar Nov 06 '23 18:11 laolarou726

还有一个小建议就是源生成器推荐生成相应的属性而非字段,使用公开静态字段的话部分 C# 语言自带的注解将无法使用:

例如验证密码的字段,它可以指定ErrorMessageResourceName,该字段要求必须是属性才行

image

laolarou726 avatar Nov 06 '23 19:11 laolarou726

  • 我在Avalonia的文档里面看到了CompiledBinding相关的内容,但是只停留于使用,具体实现还需要再看一下源码,非常感谢您提供的代码样例。
  • 源生成代码我考虑过几种情况 : const字段 , static字段 或者 static属性。 一开始这个项目的功能是参考的 HandyControl 中的T4模板生成资源键绑定, 他的选择的是生成 const 字段。 在本项目中,我希望能更加自动的配置翻译资源的源,这也就意味着代码需要无感知的提交到I18NExtension管理。而在这个过程中,我遇到了几个问题:
    • 在最初的设计中,静态构造函数扮演了一个十分重要的角色,生成的Provider不借助任何反射也能将自己提交到I18NExtension完成注册的工作。但由于C#的类加载机制,const 引用不会触发类型的静态构造函数,这意味着即便xaml中存在 {x:Static Foo.ConstMember} Foo的静态构造函数也不会被调用。
    • 因此我将其改为了 static字段, 这似乎解决了问题,但倘若调用方纯粹的 Binding 到内存,不使用任何 static字段, 其静态构造函数依然不会被触发, 没有任何办法让一个编译时不产生任何引用的类型强制的触发他的静态构造.......除非反射
    • 这是我最不想使用的办法,检索程序集中继承自......不需要过多的解释你也能明白,总之那个时候因为项目仅限于WPF,就没有过多的拘泥于反射,即便我已经尽可能的避免这么做。至少问题就这么解决了。
    • 这或许有更好的办法,就在我写这个comment的时候产生了一些灵感,稍后我就会去尝试一下。
    • 切换为 static属性 应当是没有问题的,至少目前还没有发现他们有可能存在的问题。是属性还是字段终究是一种取舍。
  • 我十分支持切换为编译绑定, 不过这也许意味着我也得**~~生成更多的东西~~**, 毕竟某个来自 System.Runtime 的东西还在我的实现里面呆着。

feast107 avatar Nov 07 '23 16:11 feast107

WPF平台也有x:Bind的实现了,https://github.com/levitali/CompiledBindings

emako avatar Dec 02 '23 02:12 emako

WPF平台也有x:Bind的实现了,https://github.com/levitali/CompiledBindings

可惜的是WPF本身用到了许多反射,还无法NativeAOT

feast107 avatar Dec 02 '23 10:12 feast107

WPF平台也有x:Bind的实现了,https://github.com/levitali/CompiledBindings

可惜的是WPF本身用到了许多反射,还无法NativeAOT

以及大量COM()

DearVa avatar Jan 02 '24 14:01 DearVa

WPF平台也有x:Bind的实现了,https://github.com/levitali/CompiledBindings

可惜的是WPF本身用到了许多反射,还无法NativeAOT

以及大量COM()

是的,DX是COM, Windows Only 😿

feast107 avatar Jan 02 '24 15:01 feast107