6

インターフェイスを実装するサード パーティのプラグイン (DLL) を取り込むエンジンを作成しました。

プラグインされるコードを制御できないため、正しいクラスから (インターフェイスから) 1 つの特定のメソッドを実行できるようにしたいと考えています (インターフェイス化されたクラスが見つかるまで GetTypes ループ)。

Activator.CreateInstanceで実行される優れたコンストラクター コードは誰でも作成できるため、 FormatterServices.GetUninitializedObjectを使用して解決できます。しかし、クラスのフィールドでコードが初期化されている場合、それは役に立ちません。

public class myclass : myinterface {

  public someotherclass name = new someotherclass()

  public myclass() {
     //Unknown code
  }

  //I only want this run.
  public string MyProperty{
    get {
      return "ANiceConstString";
    }
  }
}

両方の方法 (CreateInstance/GetUninitializedObject) の問題は、別のクラスのコンストラクター実行されることです。

あなたが私のニーズを分析し始める前に。これは、一連の標準値を取得するためにエンジンを初期化するときにのみ実行されます。この get'er が他の初期化された値に依存している場合、有効な値が返されないため、「プラグイン」は失敗としてマークされます。失敗としてマークされていない場合、後でクラスはActivator.CreateInstance()で適切にロードされます。

ですから、この質問に固執してください: .Net は、100% 初期化されていないクラスを作成する方法をサポートしていますか?

回答を更新します。質問を投稿する前にこれをテストしました。

他のクラスが実行されないという答えについては、すでにテスト済みで、静的であれば実行されます。

public class myclass : myinterface {

    static Tutle test;

    public myclass () {
         test = new Tutle();
    }

    public class Tutle {
        public Tutle() {
            MessageBox.Show("RUN!");
        }
    }
}

CreateInstance はメッセージ ボックスを表示します。GetUninitializedObject はそうではありません。

public class myclass : myinterface {

    static Tutle test = new Tutle();

    public myclass () {
    }

    public class Tutle {
        public Tutle() {
            MessageBox.Show("RUN!");
        }
    }
}

CreateInstance はメッセージ ボックスを表示します。GetUninitializedObject はメッセージ ボックスを表示します。

静的フィールドの初期化子と ctors を回避する方法はありますか?

4

2 に答える 2

15

単に:

var obj = (myclass)FormatterServices.GetUninitializedObject(typeof(myclass));

それはコンストラクター/フィールド初期化子を実行しません。まったく。のコンストラクターは実行されませsomeotherclassnameとなりますnull

ただし、必要に応じて、標準の .NET ルールの下で、存在する静的コンストラクターを実行します。

でも!このメソッドは、アドホックな使用を意図したものではないことに注意してください。その主な目的は、シリアライザーとリモーティング エンジンで使用することです。この方法で作成された場合、型を有効な状態に戻すための手順を後で実行していない場合、型が正しく機能しない可能性が非常に高くなります (どのシリアライザー/リモート エンジンでも確実に実行されます)。

于 2013-01-03T09:55:01.400 に答える
5

代替設計の考慮事項として:

[SomeFeature("ANiceConstString")]
public class myclass : myinterface {

  public someotherclass name = new someotherclass()

  public myclass() {
     //Unknown code
  }
}

これで、インスタンス化せずに機能にアクセスできます。使用するだけです:

var attrib = (SomeFeatureAttribute)Attribute.GetCustomAttribute(
    type, typeof(SomeFeatureAttribute));
string whatever = attrib == null ? null : attrib.Name;

と:

[AttributeUsage(
    AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public sealed class SomeFeatureAttribute : Attribute
{
    private readonly string name;
    public string Name { get { return name; } }
    public SomeFeatureAttribute(string name) { this.name = name; }
}
于 2013-01-03T10:03:46.203 に答える