【问题标题】:Pass object and attribute at once for reflect-metadata in TypeScript like in C#像在 C# 中一样在 TypeScript 中为反射元数据一次传递对象和属性
【发布时间】:2018-07-18 00:51:34
【问题描述】:

在 C# 中,我们使用 DataAnnotation 在属性上添加元属性。我需要 TypeScript 中的这个功能用于 ldap 模型类。装饰器应该设置 LDAP 目录内部使用的 LDAP 属性

export class LdapUser {
    @ldapAttribute('sn')
    sureName: string;
}

export function ldapAttribute(attributeName: string): (target: any, propertyKey: string) => void {
    return function (target: any, propertyKey: string) {
        Reflect.defineMetadata("ldapAttribute", attributeName, target, propertyKey);
    }
}

但要获取 ldapAttributedecorator 值,我需要将对象和属性名称作为原始字符串传递,如下所示:

let user = new LdapUser();
let sureNameAttribute = Reflect.getMetadata("ldapAttribute", user, "sureName"); // sn

它有效,但这似乎是不好的做法,因为当sureNameattribute 在LdapUser 中重命名而不将其应用于Reflect.getMetadata()call 时,它会导致运行时而不是编译器错误。而且智能感知也缺失了。所以我正在寻找这样的解决方案:

let sureNameAttribute = Reflect.getMetadata("ldapAttribute", user.sureName);

这里的问题是我需要某种反射来划分属性名称(此处为sureName)和类对象(此处为user)中的user.SureName。我已经在 C# 中使用反射做过类似的事情,但不知道如何在 TS 中做到这一点。

解决方法

它不如在 C# 中使用反射,但比只使用纯字符串更好:

export function getLdapAttribute<T>(instance: T, attributeName: keyof T) : string {
    let value : string = Reflect.getMetadata("ldapAttribute", instance, attributeName);
    return value;
}

用法

let attributeValue = getLdapAttribute(user, "sureName"); // cn

遗憾的是,我们这里没有智能感知。但是,如果属性名称不存在,至少我们会得到一个编译器错误。

【问题讨论】:

  • 问题是?

标签: c# typescript reflection reflect-metadata typescript-decorator


【解决方案1】:

我们使用下一个方法来解决这个问题:

export type FieldSpec<TModel, TResult> = ((model?: TModel) => TResult) | string;

export function getFieldName<TModel, TResult>(fieldSpec: FieldSpec<TModel, TResult>): string {
    if (typeof (fieldSpec) == "string" || !fieldSpec) {
        return fieldSpec as string;
    } else {
        var fullFunc = fieldSpec.toString();
        var parts = fullFunc.split(/[.;}]/).filter(x => x.trim().length > 0);
        return parts[parts.length - 1].trim();
    }
}

使用这些助手,您可以编写:

export function getLdapAttribute<T>(instance: T, attributeName: FieldSpec<T,any>) : string {
    let value : string = Reflect.getMetadata("ldapAttribute", instance, getFieldName(attributeName));
    return value;
}

let user = new LdapUser();
let sureNameAttribute = getLdapAttribute(user, () => user.sureName);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-09
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-23
    相关资源
    最近更新 更多