Ответ 1
Если вы явно не вызываете какой-либо конструктор в базовом классе, конструктор без параметров будет называться неявно. Нет никакого способа обойти это, вы не можете создать экземпляр класса без вызываемого конструктора.
У меня есть (плохо написанный) базовый класс, который я хочу обернуть в прокси-объект. Базовый класс похож на следующее:
public class BaseClass : SomeOtherBase
{
public BaseClass() {}
public BaseClass(int someValue) {}
//...more code, not important here
}
и мой прокси напоминает:
public BaseClassProxy : BaseClass
{
public BaseClassProxy(bool fakeOut){}
}
Без конструктора "fakeOut" ожидается, что будет создан базовый конструктор. Однако с этим я ожидал, что это не будет вызвано. В любом случае, мне либо нужен способ не называть конструкторы базового класса, либо каким-либо другим способом эффективно проксировать этот (злой) класс.
Если вы явно не вызываете какой-либо конструктор в базовом классе, конструктор без параметров будет называться неявно. Нет никакого способа обойти это, вы не можете создать экземпляр класса без вызываемого конструктора.
Существует способ создания объекта без вызова каких-либо конструкторов экземпляров.
Прежде чем продолжить, будьте уверены, что хотите сделать это таким образом. 99% времени это неправильное решение.
Вот как вы это делаете:
FormatterServices.GetUninitializedObject(typeof(MyClass));
Вызовите его вместо конструктора объекта. Он создаст и вернет вам экземпляр без вызова каких-либо конструкторов или инициализаторов полей.
При десериализации объекта в WCF он использует этот метод для создания объекта. Когда это происходит, конструкторы и даже инициализаторы полей не запускаются.
Необходимо вызвать не менее 1 ctor. Единственный путь, который я вижу, это сдерживание. Имейте класс внутри или ссылаясь на другой класс.
Если вы хотите, чтобы не вызывал один из двух конструкторов базового класса, это невозможно.
Конструкторы класса С# должны вызывать конструкторы базового класса. Если вы не вызываете одно явно, подразумевается base(). В вашем примере, если вы не укажете, какой конструктор базового класса вызывать, это то же самое, что:
public BaseClassProxy : BaseClass
{
public BaseClassProxy() : base() { }
}
Если вы предпочитаете использовать другой конструктор базового класса, вы можете использовать:
public BaseClassProxy : BaseClass
{
public BaseClassProxy() : base(someIntValue) { }
}
В любом случае, один из двух будет вызываться явно или неявно.
Я не верю, что вы можете обойти вызов конструктора. Но вы можете сделать что-то вроде этого:
public class BaseClass : SomeOtherBase
{
public BaseClass() {}
protected virtual void Setup()
{
}
}
public BaseClassProxy : BaseClass
{
bool _fakeOut;
protected BaseClassProxy(bool fakeOut)
{
_fakeOut = fakeOut;
Setup();
}
public override void Setup()
{
if(_fakeOut)
{
base.Setup();
}
//Your other constructor code
}
}
Я боюсь, что базовый вызывающий конструктор не является опцией.
Когда вы создаете объект BaseClassProxy, НУЖНО создавать экземпляр базового класса, поэтому вам нужно вызвать конструктор базового класса, что вы можете сделать, выбрав тот, который вы хотите вызвать, например:
public BaseClassProxy (bool fakeOut) : base (10) {}
Чтобы вызвать второй конструктор вместо первого
В итоге я сделал что-то вроде этого:
public class BaseClassProxy : BaseClass
{
public BaseClass BaseClass { get; private set; }
public virtual int MethodINeedToOverride(){}
public virtual string PropertyINeedToOverride() { get; protected set; }
}
Это привело меня к некоторым неправильным действиям базового класса.
являются общедоступными. не используйте конструктор и не используйте другое для построения и не делайте его private.so вы создадите экземпляр без параметров и вызовите эту функцию для создания экземпляра объекта.
Хорошо, вот уродливое решение проблемы одного класса, наследующего конструкторы другого класса, который я не хотел позволять некоторым из них работать. Я надеялся избежать использования этого в моем классе, но вот оно:
Вот мой конструктор класса:
public MyClass();
{
throw new Exception("Error: Must call constructor with parameters.");
}
Хорошо, теперь вы были предупреждены, что это было некрасиво. Без претензий, пожалуйста!
Я хотел получить хотя бы минимальные параметры из моего главного конструктора, не допуская при этом наследуемого базового конструктора без параметров.
Я также считаю, что если вы создаете конструктор и не ставите после него: base(), он не будет вызывать конструктор базового класса. И если вы создадите конструкторы для всех из базового класса и предоставите для них одинаковые точные параметры в основном классе, то он не будет проходить через них. Но это может быть утомительно, если у вас много конструкторов в базовом классе!
Можно создать объект без вызова конструктора без параметров (см. Ответ выше). Но я использую такой код для создания базового класса и унаследованного класса, в котором я могу выбрать, выполнять ли базовый класс init.
public class MyClass_Base
{
public MyClass_Base()
{
/// Don't call the InitClass() when the object is inherited
/// !!! CAUTION: The inherited constructor must call InitClass() itself when init is needed !!!
if (this.GetType().IsSubclassOf(typeof(MyClass_Base)) == false)
{
this.InitClass();
}
}
protected void InitClass()
{
// The init stuff
}
}
public class MyClass : MyClass_Base
{
public MyClass(bool callBaseClassInit)
{
if(callBaseClassInit == true)
base.InitClass();
}
}
Вот мое решение проблемы
using System;
public class Program
{
public static void Main()
{
Console.WriteLine(new Child().Test);
}
public class Child : Parent {
public Child() : base(false) {
//No Parent Constructor called
}
}
public class Parent {
public int Test {get;set;}
public Parent()
{
Test = 5;
}
public Parent(bool NoBase){
//Don't do anything
}
}
}
Простое элегантное решение. Вы можете изменить его в соответствии с вашими потребностями.