开发者

How to call protected constructor in c#?

How to call protected 开发者_Go百科constructor?

public class Foo{
  public Foo(a lot of arguments){}
  protected Foo(){}
}
var foo=???

This obviously fails test:

public class FooMock:Foo{}
var foo=new FooMock();
Assert(typeof(Foo), foo.GetType());


Call parameterless protected/private constructor:

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

Call non-public constructor with parameters:

  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){...}
  }


You can only call that from a subclass, basically. Your FooMock class will already be calling the protected constructor, because it's equivalent to:

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

However, your assertion will fail because the type of object referred to be foo is FooMock, not Foo.

An assertion of the form foo is Foo will pass though.

You can't construct an instance of just Foo by calling the protected constructor directly. The point of it being protected instead of public is to ensure that it's only called by subclasses (or within the text of Foo itself).

It's possible that you could call it with reflection within a full trust context, but I'd urge you not to do so.


The only way to cause a protected constructor to be called is to derive from the class and have the derived class delegate to it or to have a static method create it or some other internal method.

EDIT: What the Skeet said!


You cannot call a protected method - although you can call an internal one (using InternalsVisibleTo attribute). You need to expose it in a different way.


Serj-Tm answered adequately but Activator can do it too:

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


If you want to avoid repeated reflection cost, you can use expressions. Here is an example of calling a private constructor with a string value.

    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();
    }

Save the cost of compiling the function multiple times by storing it in a static field.

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

Now you can create the object with

CreateInstance.Value("Hello")


If you need to explicitly call the constructor of you base class in your subclass, you have to use the keyword base


may be this will help:

abstract parent class:

 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");

        }


    }

class with protected constructor:

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() { }
    }

class Kiara derived from Lion class :

 public class Kiara : Lion
    {

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

        }

        public override void talk()
        {

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

        }

        public Kiara() { }

    }

class Simba derived from Lion class :

    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() { }

    }

implementation in main function:

       public static void Main(string[] args)
        {


            Animal lion = new Simba();
            lion.Name = "Simba";
            lion.talk(); 
            Animal lion1 = new Kiara();
            lion1.Name = "Kiara";
            lion1.talk();
        }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜