5

次のように (eg) を自動的に生成する方法を探していますsingleton

[SingletonPatternAttribute]
public class Logger {
    public void Log (string txt) { /* do logging... */ }
}

ボイラープレートを排除する試みとして。

誰かがそれを達成する方法を知っていますか? CodeDOMReflection.Emitなどがあることは知っていT4ます。また、(最も注目に値する)PostSharpがありますが、上記の課題に対する実際の解決策が見られることを本当にうれしく思います。

たとえば、コンストラクターでコード生成を行うことができますが、コンパイル時間は明らかにはるかに優れています。

編集:

ここでの問題はSingletonではなく、ジェネレーティブ / メタ プログラミングC#- コードを作成する方法 / ボイラー プレートを最適な方法で削除する方法 - 具体的な例にはどのようなものがありますか?

4

2 に答える 2

2

IOCコンテナを使用し、オブジェクトをマッピング/バインドするときにスコープを追加して、ロギングクラスに対してこれとまったく同じことを行います。たとえば、Ninjectを使用すると、バインディングは次のようになります。

Bind<ILogger>().To<Logger>().InSingletonScope();

次に、シングルトンロガーを使用したいクラスで、プロパティインジェクションを使用できます。

[Inject]
public ILogger Logger { get; set; }
于 2013-03-18T14:17:58.073 に答える
1

しばらく時間が経ちましたが、満足のいく回答を読んでいないので、過去に行ったことを書きます。私が達成したことは理想的ではないと感じており、私自身ももっとうまくやりたいと思っているので、他のアプローチにも非常に興味があります。

過去数年間、「強化された」クラスのコード生成について、リストされている 4 つのアプローチのうち 3 つを試しました。

  • Reflection.Emit
  • T4
  • CodeDom (ただし、これは私のプロジェクトの時点で完全ではなかったので、早い段階で破棄しました!)

プラス他の 3 つ:

一般に、私はこれらすべてのツールを調査して、OP の例に似たものから始めて、AOP の方法でコードの「織り」を取得しました。属性「特別」でタグ付けされたクラスとメソッドを作成し、それらの動作を変更します。私の最初のプロジェクトの時点では、C# の AOP ソリューションは十分に成熟していませんでした (ただし、これはその間に変更された可能性があります)。そのため、たとえば PostSharp については何も言えません。前述したように、私の目的は非常に似ていました。クラスとメソッドの属性に基づいて、追加のコード (およびクラス メンバーも) をクラスに追加します。プロトタイプに Reflection.Emit を使用し、最終的に Profiler API を使用して IL 書き換えを終了しました。

最終的に T4 を使用することになった 2 番目のプロジェクトは、少し異なりました。すでにコード ジェネレーター (より具体的にはパーサー ジェネレーター) を使用していましたが、生成されたソース コードをさらに (自動的に!) 修正する必要がありました。

Reflection.Emit

私は次のアプローチを使用しました: クラス (MakeProxy と呼びましょう) が特定のアセンブリをウォークし、属性を検索してから、新しい dll (「プロキシ」) を発行し、内部で元のアセンブリを呼び出し、目的のインターフェイスと動作を提供します。ユーザーに。

私は実際に、.NET 実行可能ファイルであるツールでクラスを使用しました。このツールは、コンパイル パスの後に MS Build によって実行されました。

主な欠点: 参照の扱いが難しい場合があります。自動生成された dll を参照する必要があるため、コードを別のプロジェクトに分割する必要があり、ソリューションで元のプロジェクトを参照することさえできません... 受け入れられない場合があります。また、生成されたコードではなく、元のコードも (IDE で) 「見る」ことができます。これにより、デバッグが困難になる場合があります。

プロファイラ API

この場合、Reflection.Emit の場合と同じ作業を行いますが、「プロキシ」を事前に構築する必要はありません。コードは IL の生成時に挿入されます (つまり、1 回で、パフォーマンスの点で非常に優れています)。(管理されていない) プロファイラー DLL を作成し、その下でプログラムを開始するだけです。あなたの「プロファイラー」は、どの関数が実行されたか (あるいは、どの関数が JIT されたか) を通知され、それに応じて行動することができます。

主な欠点: クラスの「構造」(メソッド、フィールドなど) を変更できない (簡単ではありません)。アンマネージ API を使用した IL の生成は非常に困難です (多くのことを処理する必要があり、問題が発生した場合のデバッグは本当に悪夢です!) 主な利点: 元のコードを変更する必要はありません (特に、呼び出し側 - これは、その特定のプロジェクトの要件を考えると、最終的にこのソリューションに私を導いたものです)。

T4

別のプロジェクトで T4 を使用しましたが、ここで調査結果を共有できます。テキストの変換には適していますが、コードの変換には適していません。構文が「奇妙」になります(コードがあり、コードを生成するコードがコード内にあり、簡単に迷子になります)。

主な利点: IDE およびビルド システムとうまく統合されています。あなたはインテリセンスのサポートを受けます。始めるのは簡単です。実際にデバッグしているものを確認できます

個人的には、T4 のようなものを持ちたい (または自分で構築したい) のですが、それは C# -> C# コード変換を実行します。そうすれば、IDE の利点 (「元の」ものと「生成されたもの」の両方での IntelliSense を含む) と Reflection.Emit のパワーを利用できます。ただし、これらすべての機能を利用するには、おそらく C#/C# コンパイラと VS プラグインの両方をビルドする必要があります。

最後に 1 つ: 今日は、IKVM エミットやSigilなど、Reflection.Emit よりも「高度な」ものを使用します。

于 2013-03-19T12:50:33.513 に答える