TypeScript将方面应用于类

时间:2012-11-01 14:29:52

标签: javascript typescript

有没有办法在TypeScript中挂钩类的声明过程?

e.g。考虑以下课程

class Foo extends Bar
{
      constructor() { super(); }
}

我目前通过手动调用weaver来将方面应用于此类型:

weaver.applyAspects(Foo);

这意味着我修改了类中某些方法的行为。 我宁愿看到这只是通过在上面的例子中继承“Bar”超级类而自动发生。

在构造函数中做一些时髦的东西似乎是错误的,因为这将适用于每个新实例,而不仅仅是原型本身。

我想我可以覆盖__extends函数(在生成的javascript输出中使用),但这看起来有点时髦。

还有其他选择吗?

3 个答案:

答案 0 :(得分:3)

如果要在TypeScript中使用AOP,可以通过为现有AOP框架提供定义来使用它。这是一个使用jQuery.aop的完整示例。

以这种方式使用AOP不会影响任何现有定义,因为AOP代码在您交叉的代码上是不可见的。

aop.d.ts

declare class Advice {
    unweave(): void;
}

declare interface PointCut {
    target: Object;
    method: string;
}

declare class Aop {
    before: (pointCut: PointCut, advice: Function) => Advice[];
    after: (pointCut: PointCut, advice: Function) => Advice[];
    afterThrow: (pointCut: PointCut, advice: Function) => Advice[];
    afterFinally: (pointCut: PointCut, advice: Function) => Advice[];
    around: (pointCut: PointCut, advice: Function) => Advice[];
    introduction: (pointCut: PointCut, advice: Function) => Advice[];
}

interface JQueryStatic {
    aop: Aop;
}

app.ts

/// <reference path="jquery.d.ts" />
/// <reference path="aop.d.ts" />

class ExampleClass {
    exampleMethod() {
        alert('Hello');
    }
}

jQuery.aop.before(
    { target: ExampleClass, method: 'exampleMethod' },
    function () { alert('Before exampleMethod'); }
);

jQuery.aop.after(
    { target: ExampleClass, method: 'exampleMethod' },
    function () { alert('After exampleMethod'); }
);

var example = new ExampleClass();
example.exampleMethod();

示例来源:AOP with TypeScript

<强>更新

要向类和所有兼容类添加相同的关注点,您不能重用基类点。这是因为包装器是包含在点中的原始基类函数,这将是扩展基类的类的错误实现。

这个唯一有效的时间是你的函数只调用super(),在这种情况下它会起作用。

以下是我将如何将相同的问题添加到许多类中 - AopHelper只需要在程序中存在一次:

/// <reference path="jquery.d.ts" />
/// <reference path="aop.d.ts" />

class ExampleClass {
    exampleMethod() {
        alert('Hello');
    }
}

class SecondClass extends ExampleClass {
    exampleMethod() {
        alert('World');
    }
}

class AopHelper {
    static weave(targets: Object[], method: string, point: Function, advice: Function) {
        for (var i = 0; i < targets.length; i++) {
            point({ target: targets[i], method: method }, advice );
        }
    }
}

var classes: any[] = [ExampleClass, SecondClass];

AopHelper.weave(classes, 'exampleMethod', jQuery.aop.before, () => { alert('Before exampleMethod'); });
AopHelper.weave(classes, 'exampleMethod', jQuery.aop.after, () => { alert('After exampleMethod'); });

var example = new SecondClass();
example.exampleMethod();

答案 1 :(得分:0)

https://github.com/agentframework/agentframework

这是TypeScript的另一个AOP使用最新的装饰器功能。

您可以使用装饰器

添加自己的拦截器

让我们说以下是您想要的行为

class Directory {
    public getRoot(): string {
        try {
            return this._root.path;
        }
        catch(err) {
            return null;
        }
    }
}

您可以在AgentFramework

中执行以下操作
@agent('DirAgent')
class Directory {
     @failure(null)
     public getRoot(): string {
         return this._root.path;
     }
}

@failure(null)是一个开箱即用的属性,当方法抛出错误时,它将返回给定值null。你也可以改成@failure(''),@ failure(0),@ failure(false)来使你的代码更具可读性。

答案 2 :(得分:0)

为了在打字稿中成功实施AOP技术,我建议使用kaop-ts

同时检查此answer

class Component extends SomeOtherComponent {
  ...
  @beforeMethod(YourHttpService.getCached, '/url/to/html')
  @beforeMethod(YourHtmlParser.template)
  invalidate (parsedHtml?: any) {
    this.element.append(parsedHtml)
  }
}
...
componentInstance.invalidate()
// explanation below