2010-12-06 22 views

答えて

21

あなただけ基本的に、サブクラスからそれを呼び出すことができます。オブジェクトの型はfooであることを言及ので

public class FooMock : Foo 
{ 
    public FooMock() : base() // Call the protected base constructor 
    { 
    } 
} 

しかし、あなたのアサーションは失敗しますFooMock、ないFooです:それはと同等ですので、あなたのFooMockクラスはすでに、保護されたコンストラクタを呼び出すことになります。

foo is Fooのアサーションはとなります。

Fooのインスタンスは、保護されたコンストラクタを直接呼び出すことで構築できません。パブリックではなく保護されているのは、サブクラス(またはFoo自体のテキスト内)だけであることを保証することです。

完全信頼コンテキストでリフレクションで呼び出せる可能性がありますが、そうしないことを強くお勧めします。

+0

「私はあなたをないよう強くお勧めしたいですそうするのはなぜですか?私はテストのためにそれが必要です。結局のところそれは意味をなさないでしょうか? –

+1

@Arnis L .:その時点では、テストをパスするためのハックを行うよりも、テストを書くのと全く同じくらい有用です。これは、あなたが探している(そしてテストしている)動作が明示的にサポートされていない(したがって、テスト可能ではない)ことを意味するので、このコンストラクタが 'protected'であることを一度遡って見てみましょう。 – David

+1

@Arnis:通常、リフレクションでアクセシビリティモデルをバイパスする必要がある場合は、問題のメンバーにアクセスしようとするべきではないことを示唆しています。 –

2

保護されたコンストラクタを呼び出させる唯一の方法は、クラスから派生させ、派生クラスに委譲させたり、静的メソッドを作成して他の内部メソッドを作成させることです。

編集:Skeetが言ったこと!

+5

+1編集:Skeetが言ったこと! – Aliostad

1

internalInternalsVisibleTo属性を使用)を呼び出すことはできますが、protectedメソッドを呼び出すことはできません。あなたは別の方法でそれを公開する必要があります。

0

明示的にサブクラスであなたのコンストラクタ基底クラスを呼び出す必要がある場合は、キーワードbase

20

コールパラメータなし保護/プライベートコンストラクタを使用する必要があります。

Foo foo = (Foo)Activator.CreateInstance(typeof(Foo), true); 

コールを非パラメータを持つpublicコンストラクタ:

var foo = (Foo)typeof(Foo) 
    .GetConstructor(
     BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, 
     null, 
     new[] { typeof(double) }, 
     null 
    ) 
    .Invoke(new object[] { 1.0 }); 

    class Foo 
    { 
    private Foo(double x){...} 
    } 
+0

これは受け入れられる回答である必要があります。 –

0

Serj-Tmは適切に回答しましたが、Activatorはそれもやってみましょう:

var foo = (Foo) Activator.CreateInstance(typeof(Foo), 
       BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, 
       null, 
       new object[] { 2.0 }, 
       CultureInfo.InvariantCulture); 
1

繰り返しコストが発生しないようにするには、式を使用します。 以下は、文字列値でプライベートコンストラクタを呼び出す例です。

private static Func<string, T> CreateInstanceFunc() 
    { 
     var flags = BindingFlags.NonPublic | BindingFlags.Instance; 
     var ctor = typeof(T).GetConstructors(flags).Single(
      ctors => 
      { 
       var parameters = ctors.GetParameters(); 
       return parameters.Length == 1 && parameters[0].ParameterType == typeof(string); 
      }); 
     var value = Expression.Parameter(typeof(string), "value"); 
     var body = Expression.New(ctor, value); 
     var lambda = Expression.Lambda<Func<string, T>>(body, value); 

     return lambda.Compile(); 
    } 

静的フィールドに関数を複数回コンパイルするコストを削減します。

private static readonly Lazy<Func<string, T>> CreateInstance = new Lazy<Func<string, T>>(CreateInstanceFunc); 

今、あなたは、これが役立つかもしれ

CreateInstance.Value("Hello") 
0

でオブジェクトを作成することができます。

抽象親クラス:

:保護されたコンストラクタを持つ

public abstract class Animal 
    { 

     private string name; 

     public Animal(string name) 
     { 

      this.Name = name; 
     } 

     public Animal() { } 
     public string Name 
     { 

      get { return this.name; } 

      set { this.name = value; } 

     } 

     public virtual void talk() 
     { 

      Console.WriteLine("Hi,I am an animal"); 

     } 


    } 

クラス

public class Lion : Animal 
    { 
     private string yahoo; 

     protected Lion(string name) : base(name) 
     { 

      this.Yahoo = "Yahoo!!!"; 
     } 

     public string Yahoo 
     { 
      get 
      { 
       return yahoo; 
      } 

      set 
      { 
       yahoo = value; 
      } 
     } 

     public Lion() { } 
    } 
ライオンクラスから派生し

public class Kiara : Lion 
    { 

     public Kiara(string name) : base(name) 
     { 

     } 

     public override void talk() 
     { 

      Console.WriteLine("HRRRR I'm a Kiara"); 

     } 

     public Kiara() { } 

    } 

クラスシンバ:

ライオンクラスから派生したクラスキアラメイン機能で

public class Simba : Lion 
    { 

     public Simba(string name) : base(name) 
     { 

     } 

     public override void talk() 
     { 

      Console.WriteLine("HRRRR I'm a {0} and this is my daughter:{1} {2}", 
      new Simba("Simba").Name, 
      new Kiara("Kiara").Name, 
      new Simba("Simba").Yahoo); 
     } 


     public Simba() { } 

    } 

実装:

 public static void Main(string[] args) 
     { 


      Animal lion = new Simba(); 
      lion.Name = "Simba"; 
      lion.talk(); 
      Animal lion1 = new Kiara(); 
      lion1.Name = "Kiara"; 
      lion1.talk(); 
     } 
関連する問題