[解決済み] リフレクションによる拡張手法の特定
2023-08-30 15:21:14
質問
C#において、あるメソッドが拡張メソッドとしてクラスに追加されたかどうかを判断するために、リフレクションを使用するテクニックはありますか?
以下のような拡張メソッドがある場合、Reverse()がstringクラスに追加されたことを判断することは可能でしょうか?
public static class StringExtensions
{
public static string Reverse(this string value)
{
char[] cArray = value.ToCharArray();
Array.Reverse(cArray);
return new string(cArray);
}
}
拡張メソッドが開発者によって適切に追加されたことを単体テストで判断するための仕組みを探しています。 これを試みる理由の一つは、開発者によって実際のクラスに同様のメソッドが追加される可能性があり、もしそうであれば、コンパイラはそのメソッドをピックアップすることでしょう。
どのように解決するのか?
拡張メソッドが定義されている可能性のあるすべてのアセンブリを確認する必要があります。
で装飾されたクラスを探します。
ExtensionAttribute
で装飾されたクラス、そしてそのクラス内のメソッドで
も
で装飾された
ExtensionAttribute
. そして、最初のパラメーターの型をチェックして、興味のある型にマッチするかどうかを確認します。
これが完全なコードです。より厳密であるべきですが(型がネストされていないことや、少なくとも1つのパラメータがあることをチェックしていません)、これはあなたの手助けになるはずです。
using System;
using System.Runtime.CompilerServices;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
public static class FirstExtensions
{
public static void Foo(this string x) {}
public static void Bar(string x) {} // Not an ext. method
public static void Baz(this int x) {} // Not on string
}
public static class SecondExtensions
{
public static void Quux(this string x) {}
}
public class Test
{
static void Main()
{
Assembly thisAssembly = typeof(Test).Assembly;
foreach (MethodInfo method in GetExtensionMethods(thisAssembly,
typeof(string)))
{
Console.WriteLine(method);
}
}
static IEnumerable<MethodInfo> GetExtensionMethods(Assembly assembly,
Type extendedType)
{
var query = from type in assembly.GetTypes()
where type.IsSealed && !type.IsGenericType && !type.IsNested
from method in type.GetMethods(BindingFlags.Static
| BindingFlags.Public | BindingFlags.NonPublic)
where method.IsDefined(typeof(ExtensionAttribute), false)
where method.GetParameters()[0].ParameterType == extendedType
select method;
return query;
}
}
関連
-
[解決済み】Entity FrameworkからのSqlException - セッション内で他のスレッドが動作しているため、新しいトランザクションは許可されません。
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み] リフレクションを使用して文字列からプロパティ値を取得する
-
[解決済み] リフレクションとは何か、なぜ有用なのか?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] リフレクションを使ってジェネリックメソッドを呼び出すにはどうしたらいいですか?
-
[解決済み] C#のリフレクションで型がインターフェースを実装しているかどうかを判断する方法
-
[解決済み] 既存の静的クラスに拡張メソッドを追加することはできますか?
-
[解決済み】C#には拡張プロパティがある?
-
[解決済み] 拡張メソッドはインターフェースに適用できますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】GDI+、JPEG画像をMemoryStreamに変換する際にジェネリックエラーが発生しました。
-
[解決済み】WebForms UnobtrusiveValidationModeは、jqueryのScriptResourceMappingを必要とする
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】なぜこのコードはInvalidOperationExceptionを投げるのですか?
-
[解決済み】Socket.Selectがエラー "An operation was attempted on something that is not a socket" を返す。
-
[解決済み】"指定されたパスのフォーマットはサポートされていません。"
-
[解決済み】HRESULTからの例外:0x800A03ECエラー
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】画像のペイントにTextureBrushを使用する方法
-
[解決済み】スレッド終了またはアプリケーションの要求により、I/O操作が中断されました。