0

デフォルトのパブリックコンストラクターを持つクラスを作成する方法を探していますが、リフレクション以外での使用は禁止されています。

より詳細には、オブジェクトがそのようなパブリックデフォルトコンストラクターを実装することを要求するオブジェクト永続化フレームワーク(AWS DynamoDB-変更するオプションがありません)を使用しています。フレームワークでは、すべての永続化されたフィールドとプロパティにもパブリックgetおよびsetアクセサーが必要であり、新しいオブジェクトインスタンスを作成および初期化するときにそれらを使用します。アクセサーは2つの目的を果たす必要があるため、これは問題につながります。フレームワークで使用する場合は「ベア」である必要がありますが、コードで使用する場合は制限と検証を適用します。いずれにせよ、私はその部分を解決しましたが、デフォルトのコンストラクター(永続化フレームワークが使用するコンストラクター)を使用して永続化されたオブジェクトをコードで構築できないようにすることに依存しています。

元の質問に戻る-これをすべて機能させるには、永続性フレームワーク(空のパブリックコンストラクターのみを検索する)で使用できるようにしながら、コードがデフォルトコンストラクターを使用することを禁止する必要があります。静的フラグを使用して、潜在的なオブジェクトの永続性の使用の前後に設定し、デフォルトのコンストラクターが設定されていない場合は例外をスローすることから始めましたが、これによりマルチスレッド環境(Webサーバー)で問題が発生し始めました)。1つのスレッドは、他のスレッドで使用するためにコンストラクターを開く永続性フレームワークで使用するためにそれを設定します。ThreadStaticフラグも試しましたが、ワーカースレッドが生成されることがあるため、フレームワークによる構築を妨げるという逆の問題がありました。

今、私は実際にこれを行う方法があるかどうか疑問に思っています。この時点で、それは要件というよりも好奇心になりました。「このコンストラクターは使用しないでください」というコメントはいつでも書くことができますが、ルールを直接適用することで気分が良くなります。以前にPostSharpを使用したことがありますが、コンパイル時の検証にアスペクトを使用して、コードベースのデフォルトコンストラクターの使用を防ぐ方法はありますか?他に何か提案はありますか?

4

2 に答える 2

1

PostSharpを使用すると、アーキテクチャ制約を使用して、一部のコンストラクターがユーザーコードから呼び出されていないことを検証できます(おそらくマルチキャストと継承を使用して、ReferentialConstraintを実行し、制約をクラスにアタッチします)。基本的に、リフレクションからの場合にこのコードの唯一の正当な使用である場合、他のコンストラクターからのチェーンを期待して、コンストラクターへの参照を見つけた場合にエラーを発行する可能性があります。

これは、コンストラクターがコンストラクトから呼び出されることを妨げるものではないことに注意してnew T()ください。ここで、Tはジェネリック型パラメーターです。したがって、新しい演算子のみを禁止します。ReferentialAspectから、ReflectionSearch.GetMethodsUsingDeclarationを使用し、をフィルター処理し(Instructions & MethodUsageInstructions.NewObject) != 0ます。

編集:ReflectionSearch.GetMethodsUsingDeclarationおよびMethodUsageInstructionsに関する詳細を追加しました。

于 2012-05-30T08:56:10.683 に答える
1

私はこれにあまり時間をかけません。それを行うための「クリーンな」方法はありません。そして、試行するのに多くのサイクルを浪費するでしょう。呼び出し元に使用の責任を負わせ、コードに適切なコメントを付けてください。

WinFormsでも同じ問題が発生し、VSデザイナをサポートするためにFormsにパラメータのないコンストラクタが必要ですが、通常の使用法でFormを使用する場合、呼び出し元は特定の引数(たとえば、表示する入力データセット)を提供する必要があります。

ただし、本当に必要な場合は、デフォルトのコンストラクター内でReflectionを使用して呼び出し元を判別し、呼び出し元のアセンブリがDynamoDBでない場合は例外をスローするという方法があります。

if (!Assembly.GetCallingAssembly().FullName.Contains("DynamoDB"))
    throw new InvalidOperationException("BEGONE!");

また、補足として、私は通常、これらの種類の「開発者」チェックを、例外ではなくDebug.Assertsとして実装します。このようにして、開発中に必要な保護を導入しますが、本番環境(リリースビルドを想定)では、アサートはコンパイルされず、この呼び出しが行われるたびに(マイナーな)パフォーマンスヒットが発生することはありません。

Debug.Assert(Assembly.GetCallingAssembly().FullName.Contains("DynamoDB"), "Invalid constructor usage");
于 2012-05-29T22:59:53.950 に答える