2009-06-30 9 views
2

一般的なベースクラスのリフレクションには、いくつかの便利で便利な方法がありますが、ここではロックとハードな場所の間にあるケースがあります。リフレクションを使用するか、意味的に非公開でなければなりません(つまり、誰もそれらを使用できるはずはありません)。私はいくつかのコードは、ここでの順序であると仮定しますベースクラスのリフレクションは悪い設計アイデアですか?

public abstract class SingletonForm<TThis> : Form 
    where TThis : SingletonForm<TThis> 
{ 
    private static TThis m_singleton; 
    private static object m_lock = new object(); 
    private static ISingletonFormFactory<TThis> m_factory; 

    protected SingletonForm() { } 

    public static TThis Singleton 
    { 
     get 
     { 
      lock (m_lock) 
      { 
       if (m_factory == null) 
       { 
        foreach (Type t in typeof(TThis).GetNestedTypes(BindingFlags.NonPublic)) 
        { 
         foreach (Type i in t.GetInterfaces()) 
         { 
          if (i == typeof(ISingletonFormFactory<TThis>)) 
           m_factory = (ISingletonFormFactory<TThis>)Activator.CreateInstance(t); 
         } 
        } 

        if (m_factory == null) 
         throw new InvalidOperationException(string.Format(
          CultureInfo.InvariantCulture, 
          "{0} does not implement a nested ISingletonFormFactory<{0}>.", 
          typeof(TThis).ToString())); 
       } 

       if (m_singleton == null || m_singleton.IsDisposed) 
       { 
        m_singleton = m_factory.GetNew(); 
       } 

       return m_singleton; 
      } 
     } 
    } 
} 

さて、このコードは私のために動作しますが、それは恐ろしいその場しのぎおよび/または本当に悪い考えですか?もう1つのオプションは、型パラメータとしてFactoryの型を渡していますが、Visiblityの制限により、Factoryクラスはpublicでなければなりません。

+0

になります。そして、あなたは、あなたがロックする前にヌルをチェックして、後でチェックすることに役立つかもしれません。 –

+0

これは私が得ようとしていることを示唆しますが、ここで "第3版"を見て、あなたの考えを教えてください:http://www.yoda.arachsys.com/csharp/singleton.html –

+0

私の実際のクラスを含むように編集 –

答えて

3

ジェネリックスを扱う場合、頻繁にリフレクションを使用する必要があります。それに関して、私はあなたが大丈夫だと思います。

つまり、ここでは2種類のコードの匂いがあります。しかし、それらはコード衛生上の問題が原因である可能性がありますので、私はそれらにコメントします:

まず、あなたの静的プロパティは一般的な項目です。私は99.999%がこれもコンパイルされないことを確認しています。もしそうなら、それは悪い形です。

第2に、Barへのすべての呼び出しで新しいインスタンスが返されているようです。これはまたゲッターのために悪い形とみなされます。私は代わりにCreateBar()または類似のものと呼ばれるメソッドを持っています。

+0

が実際のコードで更新されました。 2つ目は消毒によるものです。最初のものについては、m_singleton、またはm_lockを参照していますか? –

+1

私は保護された人生を送る必要があります。私はGenericsでReflectionを使う必要はなかった。とりわけ、質問のようなコードは、維持する必要があるほどではないと主張します。あなたはReflectionを理解している開発者によって管理されているコードに自分自身を限定していますが、その代償として何を得るのか分かりません。 –

+0

私に頭痛を与えない単一のインスタンスフォーム。これは何よりも個人的なプロジェクトです(少なくとも今のところ) –

0

もし可能であれば、私はあなたがそれを取り除くことができればリフレクションの使用を避けようとします。

これを行うには、Abstract Factory patternを使用して、状況に応じてパブリックファクトリタイプを直接公開するという問題を回避できます。

Wikipediaの例では、ファクトリインターフェイスを作成してファクトリインターフェイスを作成し、コードに何かを入れて必要なファクトリを生成し、ファクトリインターフェイスとして返します。

これを行う別の方法は、抽象ファクトリ用のインターフェイスではなく抽象クラスを作成し、この抽象クラス内に必要な型ファクトリを返す静的メソッドを作成することです。

0

ちょうどFYI、以下では、このような状況にもより良いあなたが明示的に使用するタイプを定義することができるカスタム属性で処理され

if(typeof(ISingletonFormFactory<TThis>).IsAssignableFrom(t)) 
    m_factory = Activator.CreateInstance(t) as ISingletonFormFactory<TThis>; 
1

foreach (Type i in t.GetInterfaces()) 
{ 
    if (i == typeof(ISingletonFormFactory<TThis>)) 
     m_factory = (ISingletonFormFactory<TThis>)Activator.CreateInstance(t); 
} 

から減少させることができます。

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
public sealed class SingletonFactoryAttribute : Attribute 
{ 
    public Type FactoryType{get;set;} 
    public SingletonFormAttribute(Type factoryType) 
    { 
     FactoryType = factoryType; 
    } 
} 

あなたのシングルトンプロパティは、今、あなたは、これが達成しようとしていたものを言った場合、それが役立つだろう

public static TThis Singleton 
{ 
    get 
    { 
     lock (m_lock) 
     { 
      if (m_factory == null) 
      { 
       var attr = Attribute.GetCustomAttribute( 
           typeof(TThis), 
           typeof(SingletonFactoryAttribute)) 
           as SingletonFactoryAttribute; 

       if (attr == null) 
        throw new InvalidOperationException(string.Format(
         CultureInfo.InvariantCulture, 
         "{0} does not have a SingletonFactoryAttribute.", 
         typeof(TThis).ToString())); 

       m_factory = Activator.CreateInstance(attr.FactoryType); 
      } 

      if (m_singleton == null || m_singleton.IsDisposed) 
      { 
       m_singleton = m_factory.GetNew(); 
      } 

      return m_singleton; 
     } 
    } 
} 
+0

実際、私の最終的な解決策は単純です:m_singleton = Activator.CreateInstance(this.GetType()、true); *ヘッドデスク* –

+0

+1私に何か新しいことを教えるため –

関連する問題