3

TypeScriptのクラスの宣言プロセスにフックする方法はありますか?

たとえば、次のクラスを検討してください

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

私は現在、次のようにウィーバーを手動で呼び出すことにより、このタイプにアスペクトを適用しています。

weaver.applyAspects(Foo);

クラスのいくつかのメソッドの動作を変更することを意味します。上記の場合、「Bar」スーパークラスを継承するだけで、これが自動的に発生することを確認したいと思います。

コンストラクターでファンキーなことを行うと、プロトタイプ自体だけでなく、すべての新しいインスタンスに適用されるため、間違っているように見えます。

__extends関数(生成されたjavascript出力で使用される)を上書きできると思いますが、それも少しファンキーなようです。

他の選択肢はありますか?

4

3 に答える 3

4

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();

ソースの例:TypeScriptを使用したAOP

アップデート

クラスと互換性のあるすべてのクラスに同じ懸念事項を追加するために、基本クラスのポイントを再利用することはできません。これは、ラッパーがポイントでラップされた元の基本クラス関数であり、基本クラスを拡張するクラスの実装が間違っているためです。

これが有効になるのは、関数が呼び出さ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();
于 2012-11-01T15:11:47.530 に答える
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;
     }
}

null@failure(null)は、メソッドがエラーをスローしたときに指定値を返す、すぐに使用できる属性です。@failure('')、@ failure(0)、@ failure(false)に変更して、コードを読みやすくすることもできます。

于 2016-10-11T04:35:35.530 に答える
0

タイプスクリプトでAOPテクニックの実装を成功させるには、kaop-tsを使用することをお勧めします

この回答も確認してください

class Component extends SomeOtherComponent {
  ...
  @beforeMethod(YourHttpService.getCached, '/url/to/html')
  @beforeMethod(YourHtmlParser.template)
  invalidate (parsedHtml?: any) {
    this.element.append(parsedHtml)
  }
}
...
componentInstance.invalidate()
// explanation below
于 2017-06-01T08:43:48.700 に答える