7

重複の可能性:
リフレクションを使用して静的コンストラクターを呼び出すにはどうすればよいですか?

さまざまなクラスの静的コンストラクターに初期化コードがあります。インスタンスを作成することも、タイプを事前に知ることもできません。クラスがロードされていることを確認したいと思います。

私はこれを試しました:

fooType.TypeInitializer.Invoke (new object[0]);

しかし、MemberAccessExceptionが発生しました:タイプ初期化子は呼び出し可能ではありませんでした。

これは、cctorがプライベートだからだと思いますか?アーキテクチャを変更せずにこれを修正する方法はありますか?

編集:を使用して回避策を見つけましたRuntimeHelpers.RunClassConstructorが、この方法はMSDNにほとんど文書化されていないようで、ハックなのか、合理的な製品システムのような方法なのかわかりません。

4

2 に答える 2

8

なぜこれが機能するのかはわかりませんが、静的クラスがある場合は( Skeetの助けを借りて)推論します

public static class Statics1
{
    public static string Value1 { get; set; }

    static Statics1()
    {
        Console.WriteLine("Statics1 cctor");
        Value1 = "Initialized 1";
    }
}

コード:

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null);
or
staticType.TypeInitializer.Invoke(new object[0]);

どういうわけかこれはクラスの.cctorではなく.ctorに解決されるため、例外を除いてスローします。
明示的に静的なクラスを使用する場合、それは抽象シールされたクラスのように扱われるため、抽象クラスをインスタンス化できないという例外があります。静的コンストラクターで通常のクラスを使用する場合、例外は型初期化子がそうではないということです。呼び出し可能。

しかし、次のように2つのパラメーター(インスタンス、パラメーター)でInvokeオーバーロードを使用する場合:

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null, null);

静的メソッド(最初のnullの意味-インスタンスなし== static)を呼び出していることを明示的に示すと、これは機能し、クラスを初期化します。


とはいえ、静的コンストラクターは奇妙な獣です。この方法で呼び出すと、静的コンストラクターがすでに実行されている場合でも呼び出されます。つまり、次のコードです。

Console.WriteLine(Statics1.Value1);

Type staticType = typeof (Statics1);
staticType.TypeInitializer.Invoke(null, null);

静的コンストラクターを2回呼び出します。したがって、cctorにファイルの作成、データベースのオープンなどの潜在的に重要な副作用がある場合は、このアプローチを再考することをお勧めします。

また、読みやすさの理由から静的コンストラクターを好みますが、パフォーマンスの観点から、フィールド初期化子は静的コンストラクターよりも少し高速です。

于 2010-12-20T13:19:37.290 に答える
0

編集:ポスターの状態は事前にタイプを知ることができないため、明示的にそのままでは機能しません。将来の読者のために明確にするのに役立つかもしれないので、ここを離れる...

私があなたのニーズを正しく理解している場合-同様の状況で、静的クラスを参照するラッパーを作成しますが、テストスイートの一部のままです。次に、ラッパーをインスタンス化し、必要に応じて静的を初期化できます。つまり、アーキテクチャを変更せずに、ラッパーをテストフレームワークの一部として保持できます。

パブリック静的クラスMyStatic
{{
    public static string SomeToolMethod()
    {{
        「こんにちは」を返します。
    }
}

パブリッククラスMyStaticWrapper//またはプロキシ、技術的には?
{{
    public static string SomeToolMethod()
    {{
        MyStatic.SomeToolMethod();を返します。
    }
}

fooType.TypeInitializer.Invoke(new MyStaticWrapper()); ///テストされていません、ここで構文がわかりません
于 2010-12-20T12:51:46.183 に答える