Как вызвать защищенный конструктор?
public class Foo{
public Foo(a lot of arguments){}
protected Foo(){}
}
var foo=???
Это, очевидно, не проходит тест:
public class FooMock:Foo{}
var foo=new FooMock();
Assert(typeof(Foo), foo.GetType());
Как вызвать защищенный конструктор?
public class Foo{
public Foo(a lot of arguments){}
protected Foo(){}
}
var foo=???
Это, очевидно, не проходит тест:
public class FooMock:Foo{}
var foo=new FooMock();
Assert(typeof(Foo), foo.GetType());
Вы можете вызвать это только из подкласса, в основном. Ваш класс FooMock
уже вызовет защищенный конструктор, потому что он эквивалентен:
public class FooMock : Foo
{
public FooMock() : base() // Call the protected base constructor
{
}
}
Однако ваше утверждение не будет выполнено, потому что тип объекта, называемый foo
, равен FooMock
, а не foo
.
Будет выполнено утверждение формы foo is Foo
.
Вы не можете создать экземпляр только foo
, вызвав защищенный конструктор напрямую. Точка его защиты, а не публичная, заключается в том, чтобы она вызывалась только подклассами (или внутри самого текста foo
).
Возможно, вы могли бы назвать это отражением в полном контексте доверия, но я бы настоятельно рекомендовал вам не делать этого.
Вызывать бесцельный защищенный/закрытый конструктор:
Foo foo = (Foo)Activator.CreateInstance(typeof(Foo), true);
Вызов непубличного конструктора с параметрами:
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){...}
}
Единственный способ вызвать защищенный конструктор, который должен быть вызван, - это вывести его из класса и передать ему делегат производного класса или создать его статический метод или какой-либо другой внутренний метод.
EDIT: Что сказал Скит!
Вы не можете вызвать метод protected
- хотя вы можете вызвать internal
one (используя атрибут InternalsVisibleTo
). Вам нужно разоблачить его по-другому.
Если вы хотите избежать многократного отражения, вы можете использовать выражения. Ниже приведен пример вызова частного конструктора со строковым значением.
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")
Если вам нужно явно вызвать конструктор вашего базового класса в вашем подклассе, вы должны использовать ключевое слово base
Serj-Tm ответил адекватно, но Activator тоже может это сделать:
var foo = (Foo) Activator.CreateInstance(typeof(Foo),
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new object[] { 2.0 },
CultureInfo.InvariantCulture);
Возможно, это поможет:
абстрактный родительский класс:
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() { }
}
класс Kiara, полученный из класса Lion:
public class Kiara : Lion
{
public Kiara(string name) : base(name)
{
}
public override void talk()
{
Console.WriteLine("HRRRR I'm a Kiara");
}
public Kiara() { }
}
класс Simba, полученный из класса Lion:
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();
}