请问,cocos有没有提供反射类的方式呢. 类似egret.getDefinitionByName

类似java的反射. 或者白鹭的这个的实现
let obj;
let className=“Skill”;
let c= egret.getDefinitionByName(className);
obj = new c();
// 此时obj就是一个Skill的对象

cocos有类似的方法吗. 我确实找不到.

这个好像没有用过,一般都是使用的都是export class a{},在需要引用a 这个类的地方 import a from “./a”;

这个了解. 但是我想用的是类似java的反射那种.
我想通过配置文件, 在打开游戏的时候, 初始化一些内容. 比如读取配置文件里配置的各个数据模版.
这就需要用这种方式来找到对应的class 来生成对应的对象.

已解决
有两种方式
cc.js.getClassByName(className)
或者
cc.js._registeredClassNames[className]

你这个只能够创建cocos内置的对象 如果自定义的对象就不行 egret白鹭那边那个方法是任意存在于项目工程中的类

在类定义时加上@ccclass(‘xxx’)

提供一个思路吧,本质上是收集类的构造函数,用装饰器即可。

/**
 * 构造函数
 */
interface SKillConstructor {
    new(): BaseSkill;
}

/**
 * 装饰器
 * @param name 技能描述
 * @returns 
 */
export function skill(name: string) {
    return function (target: SKillConstructor) {
        Skills.set(name, target);
    }
}

/**
 * 通过装饰器注册进入这个结构
 */
export let Skills: Map<string, SKillConstructor> = new Map();

/**
 * 通过这个方法可以找到对应的构造函数
 * @param name 
 * @returns 
 */
export let FindSkill = function (name: string) {
    return Skills.get(name);
}

/**
 * 类基类
 */
export abstract class BaseSkill {
    constructor() {

    }

    abstract execute():void;
}


/**
 * 实际脚本Skill123
 */
@skill("Skill123")
export class Skill123 extends BaseSkill {

    execute(): void {
        console.log("skill123 execute");
    }
}

实际上的效果

@ccclass('Test')
export class Test extends Component {
    start() {
        console.log(Skills);
        let fuc = Skills.get("Skill123");
        let skill123 = new fuc();
        skill123.execute();
    }
}

image

装饰器去实现也想过,主要是如何优雅的不对上层业务人员暴露接口,就简单通过一个函数的性质获取字符串的类,譬如说,对类自定义类进行了装饰,假设是ReflectClass的一个装饰器方法内部已经具备字符串映射一个类的数据对象,如下

装时期和映射表一个文件
export let RefectClassMap: Map<string, any> = new Map();
/**

  • 装饰器用于描述反射类

  • @param name 类名

  • @returns 返回类

*/

export function RefClass(name: string) {

     return function (target: any) {

         RefectProxyMap.set(name, target);

     }

}
export GetClassByName(className:string,…param){
let CS = RefectProxyMap.get(className);
return new CS(…param);
}

  **自定义类独立一个文件**
    @RefClass("A")
    export class A {
     constructor(){
            console.log("this is A");
        }
    }


//正式入口程序(运行场景独立一个文件)
main(){
     let classA = GetClassByName("A");
     let ca = new classA();
     //上面就是我希望达到的效果,注意是有三个文件分开,可实际上,真实环境中如果不是刻意new一个C,装饰器方法永远不能被启动,也就无法运行装饰器中存储字符串和类之间的映射关系了
}

基于如何定义好装饰器,并且通过运用在类上以后,在使用过程当中怎样提前运行装饰器使其达到反射效果呢

是要通过类名字符串反射得到类吗

// 动态类
export class DynamicClazz {}
// 装饰器
export function add2DynamicClazz (target: any){
DynamicClazz [target.name] = target;
}
// 添加到动态类
@add2DynamicClazz
class Test {}
// 使用场景
let clazz = DynamicClazz[‘Test’];
let test = new clazz();

不是这个意思,我希望把动态类隐藏到装饰器中,对于需要动态创建的类只需要放一个装饰器,
然后使用场景就通过一个方法getXXX(“className”)就可以获得动态类,
同时映射表和装饰器一个文件,自定义类一个文件,使用场景一个文件,三个文件这个架构模式

装饰器在编译时,并不是在运行时。我看你写的你再加一个用来缓存你的模块不就完事了,并不需要刻意new,而是去检查缓存有没有

那就只能刻意的去把自定义类加到一个缓存里了 是么 我想过 但是这样就会有一个专门的类里边很多import自定义类

你可以搜一下ioc,这才是你要的东西,找一个ts的ioc实现。