30

プライベート デフォルト コンストラクターとパラメーターを持つパブリック コンストラクターを使用してクラスを定義する場合、プライベート コンストラクターにアクセスするにはどうすればよいですか?

public class Bob
{
   public String Surname { get; set; }

   private Bob()
   { }

   public Bob(string surname)
   {
      Surname = surname;
   }
}

次のように、クラスの静的メソッドを介してプライベート コンストラクターにアクセスできます。

public static Bob GetBob()
{
   return new Bob();
}

(私の理解によると)拡張メソッドはクラスの静的メソッドのように見えるように変換されるため、拡張メソッドを介してプライベートコンストラクターにアクセスできると思いましたが、できません:

static class Fred
{
   public static Bob Bobby(this Bob bob)
   {
      return new Bob();
   }
}

では、プライベート コンストラクターにアクセスするにはどうすればよいでしょうか。

ありがとうございました


編集:

これを行う理由は、ビジネス クラスの 1 つのテストを作成したかったが、このクラスのコンシューマーがオブジェクトを誤ってインスタンス化できないようにしたかったからです。私はそれをテストしているので、どのような状況でテストが失敗するかを知っています (願っています!)。私はまだテスト中なので、私の考えは「間違った方法」だったかもしれませんし、そうでなかったかもしれません。

テスト戦略を変更して、このクラスのコンシューマと同じように処理を行うようにしました。つまり、パブリック メソッドを呼び出し、パブリック メソッドに問題がない場合は、プライベート メソッドに問題がないことを前提としています。私はまだプライベートな方法をテストしたいと思っていますが、私の上司成果物で首をかしげています:-(

4

8 に答える 8

55

新しい答え(9年後)

Activator.CreateInstanceには、非パブリック コンストラクターを使用できるオーバーロードがいくつかあります。

Activator.CreateInstance(typeof(YourClass), true);

true= 非パブリック コンストラクターを使用します。

.

古い答え

デフォルトのコンストラクターは、理由によりプライベートです。開発者は楽しみのためにそれを非公開にしません。

ただし、デフォルトのコンストラクターを引き続き使用する場合は、リフレクションを使用して取得します。

var constructor = typeof(Bob).GetConstructor(BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[0], null);
var instance = (Bob)constructor.Invoke(null);

編集

テストに関するあなたのコメントを見ました。保護されたまたはプライベートなメソッド/プロパティをテストしないでください。パブリック API を介してこれらのメソッド/プロパティをテストできない場合は、おそらく何か問題があります。それらを削除するか、クラスをリファクタリングしてください。

編集 2

バインディング フラグを忘れました。

于 2010-11-12T08:30:16.850 に答える
2

リフレクションを介してプライベートコンストラクターを呼び出す方法を説明する@jgauffinの回答に加えて:

プライベート コンストラクターの修飾子を変更することは可能ですか?

コードに Factory Pattern を実装しているようです。したがって、修飾子は であるはずinternalです。

public class Product
{
   //others can't create instances directly outside the assembly
   internal Product() { }    
}
public class ProductProvider
{
   //they can only get standardized products by the provider
   //while you have full control to Product class inside ProductProvider
   public static Product CreateProduct()
   {
       Product p = new Product();    
       //standardize the product
       return p;
   }  
}

拡張方法

public static MyExt
{
   public static void DoSomething(this Product p) { }
}

呼び出しp.DoSomething()は、実際には に等しくなりMyExt.DoSomething(p)ます。このメソッドをクラス Product に入れているわけではありません。

于 2010-11-12T09:22:05.720 に答える
2

この問題を回避するには、いくつかの方法があります。

1 : コンストラクターを公開します。クラスの外部からアクセスする必要がある場合、なぜプライベートなのですか (テストのためにプライベート コンストラクターにのみアクセスしたい場合、これは有効な問題です)。

2 : コンストラクターを保護し、派生クラスを介してアクセスします。

public class Bob
{
    public String Surname { get; set; }

    protected Bob()
    { }

    public Bob(string surname)
    {
        Surname = surname;
    }
}

public class Fred : Bob
{
    public Fred()
        : base()
    {
    }
}

3 : リフレクションを使用します (jgauffin で示されているように)。

于 2010-11-12T08:33:36.950 に答える
-1

リフレクションを介してそのタイプのインスタンスをインスタンス化できます。

于 2010-11-12T08:30:24.430 に答える
-1
public class demo
{
   private demo()
    {
        Console.WriteLine("This is no parameter private constructor");
    }
    public demo(int a)
    {
        demo d = new demo('c');// u can call both private contstructors from here
        demo dd = new demo();
        Console.WriteLine("This is one parameter public constructor");
    }
    private demo(char a)
    {
        Console.WriteLine("This is one parameter public constructor::" + a);
    }
}

class Program
{
    static void Main(string[] args)
    {
        demo obj = new demo(7);
        // demo obj = new demo();  // it will raise error
        Console.ReadLine();
    }
}
于 2014-04-04T06:57:41.060 に答える
-2

メソッド Bobby はまだ Fred という別のクラスにあります。これが、Bob クラスのプライベート コンストラクターにアクセスできない理由です。あなたがやろうとしていることは、添付されたメソッドでは不可能です。別のクラスにアタッチできる場合でも、そのクラスの外で宣言され、通常のスコープ/アクセス ルールに従います。

于 2010-11-12T08:29:35.007 に答える