类似java的反射. 或者白鹭的这个的实现
let obj;
let className=“Skill”;
let c= egret.getDefinitionByName(className);
obj = new c();
// 此时obj就是一个Skill的对象
cocos有类似的方法吗. 我确实找不到.
类似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();
}
}

装饰器去实现也想过,主要是如何优雅的不对上层业务人员暴露接口,就简单通过一个函数的性质获取字符串的类,譬如说,对类自定义类进行了装饰,假设是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实现。