Bootstrap

Unity3D自学笔记——架构应用(三)JsonToEntity帮助类

JsonToEntity帮助类

JsonData 转 Entity

前面我们从数据库里读取英雄数据功能已经测试成功,所以需要添加更多的英雄属性,于是数据库及服务端相关类增加字段。

数据库
这里写图片描述

ALI.ARPG.Operations
实体类

[Serializable]
    public class HeroEntity : IEntityIntKey
    {
        public virtual int ID { get; set; }
        public virtual int Lv { get; set; }
        public virtual int MaxLv { get; set; }
        public virtual int Hp { get; set; }
        public virtual int Mp { get; set; }
        public virtual int Atk { get; set; }
        public virtual int Def { get; set; }
        public virtual int Spd { get; set; }
        public virtual int Hit { get; set; }
        public virtual double CriticalRate { get; set; }
        public virtual double AtkSpd { get; set; }
        public virtual double MoveSpd { get; set; }
        public virtual int HpGrowth { get; set; }
        public virtual int MpGrowth { get; set; }
        public virtual int AtkGrowth { get; set; }
        public virtual int DefGrowth { get; set; }
        public virtual int SpdGrowth { get; set; }
        public virtual int HitGrowth { get; set; }
        public virtual double CriticalRateGrowth { get; set; }
        public virtual double AtkSpdGrowth { get; set; }
        public virtual double MoveSpdGrowth { get; set; }
        public virtual double HpRegenTime { get; set; }
        public virtual double MpRegenTime { get; set; }
        public virtual string Desc { get; set; }
    }

ALI.ARPG.Data
映射类

public class HeroMap: ClassMap<HeroEntity>
    {
        public HeroMap()
        {
            Table("heroinfo");
            Id(x => x.ID).Column("id");
            Map(x => x.Lv).Column("Lv");
            Map(x => x.MaxLv).Column("maxLv");
            Map(x => x.Hp).Column("hp");
            Map(x => x.Mp).Column("mp");
            Map(x => x.Atk).Column("atk");
            Map(x => x.Def).Column("def");
            Map(x => x.Spd).Column("spd");
            Map(x => x.Hit).Column("hit");
            Map(x => x.CriticalRate).Column("criticalRate");
            Map(x => x.AtkSpd).Column("atkSpd");
            Map(x => x.MoveSpd).Column("moveSpd");
            Map(x => x.HpGrowth).Column("hp_growth");
            Map(x => x.MpGrowth).Column("mp_growth");
            Map(x => x.AtkGrowth).Column("atk_growth");
            Map(x => x.DefGrowth).Column("def_growth");
            Map(x => x.SpdGrowth).Column("spd_growth");
            Map(x => x.HitGrowth).Column("hit_growth");
            Map(x => x.CriticalRateGrowth).Column("criticalRate_growth");
            Map(x => x.AtkSpdGrowth).Column("atkSpd_growth");
            Map(x => x.MoveSpdGrowth).Column("moveSpd_growth");
            Map(x => x.HpRegenTime).Column("hpRegenTime");
            Map(x => x.MpRegenTime).Column("mpRegenTime");
            Map(x => x.Desc).Column("desc");
        }
    }

客户端
从服务器获得Json消息后也要做相应修改,下面是单元测试方法
头大了,属性太多了,增加点属性要写那么多,于是想偷懒了,想通过代码进行Mapping,服务端已经用了AutoMapper和NHibernate所以不需要改了

 [TestMethod]
        public void TestGetAllHero()
        {
            Dictionary<int, IEntity> cache = new Dictionary<int, IEntity>();
            var result = commandBus.Submit(new HeroInfoCommand()) as CommandResult<HeroEntity>;
            string json = JsonMapper.ToJson(result.Result);
            var data = JsonMapper.ToObject(json);
            for (int i = 0; i < data.Count; i++)
            {
                HeroEntity entity = new HeroEntity();
                entity.ID = (int)data[i]["ID"];
                entity.Lv = (int)data[i]["Lv"];
                entity.Desc = data[i]["Desc"].ToString();
                //LvMax
                //Hp
                //Mp
                //Atk
                //......
                cache.Add(entity.ID, entity);
            }
        }

观察规律
1.因为JsonData也是从Entity序列化的,所以其属性名是完全一样的,如
entity.ID = (int)data[i][“ID”]; 所以首先需要想办法获取Entity里的所有属性,然后在转化成字符串,传给Data
2.类型转换是根据Entity属性对应的类型转化的,所以需要得到属性的类型
3.开始查资料

  • 获取所有属性 PropertyInfo[] Propertys = XX.GetType().GetProperties();
    获取属性的类型 Type type = PropertyInfo.PropertyType;
HeroEntity entity = new HeroEntity();
entity.ID = (int)data[i]["ID"];
entity.Lv = (int)data[i]["Lv"];
entity.Desc = data[i]["Desc"].ToString();
cache.Add(entity.ID, entity);

实现
根据泛型获取对应的Entity对象,如HeroEntity

public class JsonToEntity<T> where T : IEntityIntKey , new()
{
    PropertyInfo[] m_Propertys;
    JsonData m_Data;
    PhotonCacheType m_CacheType;

    public PropertyInfo[] Propertys
    {
        get
        {
            //获取Entity的所有属性
            m_Propertys = new T().GetType().GetProperties();
            return m_Propertys;
        }
    }

    //构造函数中传入CacheType, 和反序列化的JsonData
    public JsonToEntity(PhotonCacheType cacheType, JsonData data)
    {
        this.m_CacheType = cacheType;
        this.m_Data = data;
    }
    //遍历JsonData,构造Entity
    public void BuildEntityToCache()
    {
        for (int i = 0; i < m_Data.Count; i++)
        {
            T entity = BuildEntity(m_Data[i]);
            PhotonDataCache.AddOrUpdateDataCache(this.m_CacheType, entity);
        }

    }

    //重点
    private T BuildEntity(JsonData childData)
    {
        T entity = new T();
        //遍历属性
        foreach (var item in Propertys)
        {
            string name = item.Name;
            Type type = item.PropertyType;

            //给实体对应的属性进行赋值, 如entity.ID = 2;
            item.SetValue(entity, TransformType(childData[name], type), null);
        }

        return entity;
    }

    //转型,根据属性的类型,对jsonData进行转型
    private object TransformType(object data, Type type)
    {
        if (type == typeof(int))
        {
            int val;
            Int32.TryParse(data.ToString(), out val);
            return val;
        }
        else if (type == typeof(float))
        {
            float val;
            float.TryParse(data.ToString(), out val);
            return val;
        }
        else if(type == typeof(double))
        {
            double val;
            double.TryParse(data.ToString(), out val);
            return val;
        }
        else if (type == typeof(string))
        {
            return data.ToString();
        }
        return null;
    }
}

好了,成功搞定,一劳永逸

private void HandleHeroInfoResponse(OperationResponse operationResponse)
    {
        switch ((ReturnCode)operationResponse.ReturnCode)
        {
            case ReturnCode.Sucess:
                object json;
                operationResponse.Parameters.TryGetValue((byte)ReturnCode.Sucess, out json);
                if (json != null)
                {
                    JsonData data = JsonMapper.ToObject(json.ToString());
                    //使用
                    new JsonToEntity<HeroEntity>(PhotonCacheType.HeroList, data).BuildEntityToCache();
                }
                break;
        }
    }

效果图
这里写图片描述

这里写图片描述

;