【ZProRx 重装上阵】 第一回 重构

前序

本框架在原ZP框架基础上重构而来,基本思路属性即数据,其核心还是面向数据。重构过程中陆续把相关代码开源。

ZProRx 框架简介

面向属性的编程框架,以属性为基础,构建属性网,同时结合反应式编程、链式编程。

特点:

- 基于UniRx反应式的属性框架。

- 基于面向切片的编程思想,通过修饰(Attribute)配合属性,提供附加信息定义,比如:实现属性间的关联

- 支持与View(Unity)的绑定。用于表现层的分离(MVC框架等)。

核心类图如下所示:

扫描二维码关注公众号,回复: 10310823 查看本文章

Base 基本结构

基本由属性和值 组成 值类可以是任意的类型,包括:Value类型(int、float)、Class、结构体、Interface等,ZProRx提供了一些预制好的值类。 如果一类中包括了ZP属性的定义,那么我们把这种类称为IsPropertable,我们后续简称为ZP类。 这种类也是开发ZP应用的主要载体。可以通过ZPropertyMesh.IsPropertable方法判断一个Type或者Object是否为IsPropertable

基本属性类:

  • ZProperty 属性类的基本定义,通过模板参数指定值类型
  • ZPropertyInterfaceRef 用于定义引用属性,一般其值类型定义为一个接口
  • ZPropertyList 用于定义一个属性数组
  • ZPropertyRefList 用于定义一个引用属性数组

综合属性类:

  • ZRankableProperty 用于定义分级的属性值,支持升级操作
  • ZRuntimableProperty 用于定义实时属性值,支持记录、回放等功能
  • ZTaskProperty 用于定义任务属性
  • ZTimerProperty 用于定义定时器属性

事件类

  • ZEvent
  • ZDirectEvent

事件也是一种属性,其实现了IZEvent/IZEvent<TValue>

主要值类:(预制值类) 以下说明包括主要值类

  • ZIntBar/ZDataBar: 由Cur和Max属性组成。多用于血条、进度条等数值。
  • ZTask: 有对应的ZTaskProperty属性类,用于定义一个任务,这里需要注意与ZTimerProerty属性类的区别。共同点是都可以用于完成一个定时的任务。 不同点是前者支持持久化,其内部会保存创建时间,可用于前后端同步,恢复等,其本质是实现一个离线的Timer。应用案例:定时的宝箱。后者是实时的定时器,其暂停后,定时器也停止了。对于步数的不同,前者步数是不确定的,后者的步数是确定的。

创建与释放

ZProRx 通过如下方法创建ZP类的对象。

var person = ZPropertyMesh.CreateObject<Person>();
person.blood.Value = 100;
person.rank.Value = 2;

ZPropertyMesh.CreateObjectWithParam可以传入构建参数。

通过 ZPropertyMesh.ReleaseObject释放ZP对象。

Attribute 修饰

属性在使用时会带一些附加信息,描述信息也有一定的层次的,包括:名称、简介、详细描述、图片介绍、链接、资源、UI绑定方式等多种形式。即属性又由其子属性组成。属性的附加信息,可以通过Attribute类【标签】来加以定义。

如下PropertyDescriptionAttribute的定义

/// <summary>
/// Property description attribute, the item is the localization item's ID.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = true)]
public class PropertyDescriptionAttribute : Attribute {
    public string description;
    public PropertyDescriptionAttribute(string description)
    {
        this.description = description;
    }
}

使用方法如下:

    [PropertyDescription("blood", "bloodDes")]
    public ZProperty<int> blood = new ZProperty<int>();

通过定义可以看出这些Attribute信息保存在属性类(ZProperty)的定义结构体中,即每一个类只需要一份Attribute信息。每个属性不能不同的类实例都自己保存一份,那样开销很大的。

以下面Attribute为例,支持两种配置名称与描述等修饰方法,第一个是通过Attribute属性,第二个是通过持久化文件 (即JSON),当然后者也需要Attribute属性进行配置,后面的属性Attribute会一一列举出来。

Attribute 的应用场景

Attribute可以定义在三种场景

  1. 成员Attribute,即声明属性成员时定义的Attribute 如:
[PropertyDescription("blood", "bloodDes")]
public ZProperty<int> blood = new ZProperty<int>();

2. 属性Attribute,即定义属性类的Attribute 如:ZMsgList其本身是一个ZProperty类,定义了一个PropertyAddComponentClass,用于在进行Unity的UI/RT 绑定时,调用AddComponent自动绑定到对应的GameObject上。

[PropertyAddComponentClass(typeof(ZUIPropertyListItem))]
public class ZMsgList : ZPropertyRefList<IZMsg>
{
    //...
}

3. 值 Attribute, 定义属性Value类的Attribute 如:以下ZMsg是一个Value类,定义了一个绑定的UIItem

[PropertyUIItemResClass("Msgs/Msg")]
//for hint msg UI
public class ZMsg : IZMsg, IIndexable

这里需要注意的是对于ZPropertyRefList ZPropertyList 这类的ListLike属性,成员Attribute和值 Attribute是对 List的Item生效的。但属性Attribute 即List的Attribute是不对Item生效的。 这里的例子就是ZMsgList 和ZHintList 属性类。

Attribute 优化级

以上定义的Attribute 的场景,如果出现冲突,对于一些互斥的Attribute,即只能获取一个。 这时按如下优化顺序返回

  1. 成员Attribute,即声明属性成员时定义的Attribute
  2. 属性Attribute,即定义属性类的Attribute
  3. 值 Attribute, 定义属性Value类的Attribute

注:根据C#语法特性,分为:互斥的Attribute和支持重复定义的Attribute

常用的Attribute

[PropertyLinkSync] 用于与修饰[PropertyLink] 配合使用,即如果设置后,Link宿主属性发生变化时,当前属性也能接收到消息并进行自动同步。

Access & Query

通过如下API用于对属性访问 

ZPropertyMesh.GetPropertyZPropertyMesh.GetProperties

  • 支持“Class.Property” 命名进行查询属性。

ZPropertyMesh.GetPropertyEx

  • 支持“.XXX” 查询子属性,用于查询通用的子属性,比如:从同一基类进行派生后,其主类名已经不同,这时
  • 支持多层查询,如“.XXX.XXX”
  • 支持模糊查询,如”.*.XXX“,即当前节点的所有子节点的XXX属性。

ZPropertyMesh.GetPropertyInSubs

  • 支持所有Child的查询

详细的使用方法,可以参考 ZP.Lib.Server.Test 工程,TestAssessQuery测试用例

后续将支持正则表达式进行查询

单体

ZProRx 架构提供了一些常用的单体模式,方便ZP类的使用

public class ZPlayer : PropObjectSingleton<ZPlayer>
{
}

之后直接使用ZPlayer.Instance进行访问,其会自动调用CreateObject创建ZP对象。

生命周期

OnCreate OnLoad OnPreBind 在UI进行绑定之前进行调用,可以用于一些UI GameObject/Transform 相关的初始化操作。 OnBind 与UI进行绑定 OnPreUnBind 在UI进行解绑定之前进行调用,可以用于一些UI GameObject/Transform 相关的释放操作。 OnUnbind 与UI解除绑定,这时,对于通过[PropertyUIItemRes]属性进行创建的GameObject,还会保留下来。如果需要释放,需要自行进行处理,比如通过OnPreUnBind方法中,进行GameObject.Destroy。 OnCopy OnDestroy

属性的持久化支持

正常的持久化,一般常常使用[Serializable]标签进行说明。如果使用这种方法的话,对JSON的支持是个问题。即需要有一些多于的信息被持久化,或者JSON的中属性也使用List的方法,但这样就不是很直观了,当然可以通过Editor扩展工具进行配置。ZP框架内部使用的是LitJson,它支持通过JsonData(类似字典结构)持久化为JSON一步步串行的进行持久化工作,中间加入这一层进行转换。 LitJson的官方地址如下, https://litjson.net

持久化方法如下:

var person = ZPropertyMesh.CreateObject<Person>();
ZPropertyPrefs.Load(person, "../../../Assets/TestPerson.json");
ZPropertyPrefs.Save(person, "../../../Assets/TestPersonCopy.json");

类似的还有: ZPropertyPrefs.LoadFromStr/LoadFromRes/LoadFrameRawData等方法用于ZP类的加载。

相关链接:

项目开源地址:https://github.com/bennychao/ZProRx.Lib

下载安装:(ZP.Lib.Server 是ZRroRx的核心库,后续其它功能库陆续开放中)

  • .Net CLI >dotnet add package ZP.Lib.Server --version 1.0.3
  • 或 VS 2019 Nuget 包管理中搜索"ZP.Lib.Server"并安装(推荐)

ZProRx.Lib Unity Package 1.0.3 (用于在Untiy中使用)下载地址: 

https://github.com/bennychao/ZProRx.Lib/releases/ 

https://github.com/bennychao/ZProRx.Lib/Publish/ZProRx.Lib.package

下一节

【ZProRx 重装上阵】 第二回 矩阵

发布了51 篇原创文章 · 获赞 10 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/FeiBin2013/article/details/104507497