源生成器源码仓库
github:https://github.com/Avalon712/UniVue-SourceGenerator
源码更新说明
本次更新完全删除了之前的BaseModel、MonoModel、ScriptableModel,改用接口的默认实现完全替代了这些类,以此实现更多更加灵活的数据绑定,对结构体、单个int、float、string、bool、Sprite等支持绑定的类型都允许进行绑定。本次改动较大,提供的功能更加灵活,同时使用了源生成器优化了低级代码的生成。
背景
在使用源生成器时,重写接口IModelUpdater、IUINotifier接口中基于反射实现的接口时,这些代码往往很冗余,同时这些接口方法会破坏Model层的可见性,即:Model层应该只可以看见自定义的数据,而不应该访问上层ViewModel层的接口,为此在原来的基础上通过默认接口方法和隐式实现的默认接口方法的方式来使得Model层对ViewModel层的接口方法不可见。
为了实现上述目的,实现方式为如下举例:
public partial class Model : IBindableModel
{
void IUINotifier.NotifyAll()
{
//非反射方式的实现逻辑
}
void IModelUpdater.UpdateModel(string propertyName,int propertyValue)
{
//非反射方式的实现逻辑
}
void IModelUpdater.UpdateModel(string propertyName,float propertyValue)
{
//非反射方式的实现逻辑
}
void IModelUpdater.UpdateModel(string propertyName,string propertyValue)
{
//非反射方式的实现逻辑
}
void IModelUpdater.UpdateModel(string propertyName,bool propertyValue)
{
//非反射方式的实现逻辑
}
void IModelUpdater.UpdateModel(string propertyName,Sprite propertyValue)
{
//非反射方式的实现逻辑
}
}
这种隐式实现的方式,只要当将Model向上转换为IBindableModel时才可以访问到ViewModel层的方法,当没有进行转换时,只能访问到Model内定义的方法。
同时这些非反射的实现逻辑都是固定的,为此使用了C#的源生成器来自动生成这些重复的代码,这样做的好处是使得Model层看起来更加美观,把那些低级的实现代码使用源生成器来完成。
使用源生器也更加灵活、随时都可以对代码进行修改而不必重新编写ViewModel层的接口方法。
原生成器的使用
注:使用源生成器需要Unity编辑器的版本为2021以上
关于Unity中对C#源生成器的支持看这儿:Roslyn analyzers and source generators - Unity 手册
1.导入源生器的dll文件到Unity中
将仓库中dlls目录下的UniVue.SourceGenerator.dll程序集文件导入到Unity的Assets目录下的任意一个目录。
2.配置dll文件
导入dll文件后需要将进行以下步骤:
在资产浏览器中,单击UniVue.SourceGenerator.dll文件以打开插件检查器窗口。
转到为插件选择平台(英文:Select platforms for plugin)并禁用任何平台(英文:Any Platform)。
转到包含平台(英文:Include Platforms)并禁用所有选项。
转到资产标签,然后打开资产标签子菜单。(就是点击那个检查面板右下角的蓝色小图标)
创建并分配一个名为 RoslynAnalyzer的新标签。为此,请在“资产标签”子菜单的文本输入窗口中输入“*RoslynAnalyzer*”。此标签必须完全匹配且区分大小写。为第一个分析器创建标签后,标签将显示在*“资产标签*”子菜单中。您可以单击菜单中的标签名称以将其分配给其他分析器。
点击Apply,等待编译完成。
重启Visual Studio编辑器。
3.使用AutoNotifyAttribute特性
之后在任何你想要进行绑定的模型的字段上添加[AutoNotify]特性。但是此特性不是随意的,它具有以下限制:
只能注解在字段上;
只能注解在顶级类或结构体(即这个类或结构体的外部不能包含其它类或结构体);
类或结构体的修饰符必须为public partial,这是因为源生成器的实现原理如此;
类或结构体必须有一个命名空间(特别是新手,创建类都不喜欢使用命名空间,直接放到根命名空间,这是一个非常不好的习惯);
注意:为了防止源生成器为标记了AutoNotifyAttribute的字段生成的属性重名,你应该了解源生器将字段名转为属性名的逻辑:
_name => Name m_name => Name _headIcon => HeadIcon m_headIcon => HeadIcon 即:将以下划线'_'和字符串"m_"的进行删掉,首字母转为大写即可。
此外注解了[AutoNotify]的特性的类或结构体将会自动实现IBindableModel接口(如果你没有主动实现的话),因此你无需显示实现这个接口。