Передайте текущий тип объекта в основной вызов конструктора

Как я захватываю Type из наследованного класса и передачи это в основного конструктора класса, также наследованного? См. пример кода ниже:

// VeryBaseClass is in an external assembly
public abstract class VeryBaseClass
{
    public VeryBaseClass(string className, MyObject myObject)
    {

    }
}

// BaseClass and InheritedClass are in my assembly
public abstract class BaseClass : VeryBaseClass
{
    public BaseClass(MyObject myObject) :
        base(this.GetType().Name, myObject) // can't reference "this" (Type expected)
    {

    }
}

public class InheritedClass : BaseClass
{
    public InheritedClass(MyObject myObject)
    {

    }
}

Строка base(typeof(this).Name, myObject) не работает, потому что я не могу сослаться this все же, поскольку объект не закончил создавать и поэтому не существует.

Действительно ли возможно захватить Type из в настоящее время создающего объекта?

Править:

Исправленный образец как orsogufo предложенный, но все еще не работает, как this не определено.

РЕДАКТИРОВАНИЕ 2:

Просто для уточнения я хочу закончить с "InheritedClass" быть переданным в VeryBaseClass(string className, MyObject myObject) конструктор.

9
задан Community 23 May 2017 в 11:45
поделиться

6 ответов

А Ха! Я нашел решение. Вы можете сделать это с помощью дженериков:

public abstract class VeryBaseClass
{
    public VeryBaseClass(string className, MyObject myObject)
    {
        this.ClassName = className;
    }

    public string ClassName{ get; set; }
}
public abstract class BaseClass<T> : VeryBaseClass
{
    public BaseClass(MyObject myObject)
        : base(typeof(T).Name, myObject)
    {
    }
}

public class InheritedClass : BaseClass<InheritedClass>
{
    public InheritedClass(MyObject myObject) 
        : base(myObject)
    {

    }
}
18
ответ дан 4 December 2019 в 06:56
поделиться

GetType (). Name не работает?

3
ответ дан 4 December 2019 в 06:56
поделиться

Возможное решение:

class VeryBase {
    public VeryBase(string name) {
        Console.WriteLine(name);
    }
}

class Base<T> : VeryBase where T : Base<T> {
    protected Base()
        : base(typeof(T).Name) {
    }
}

class Derived : Base<Derived> {
    public Derived() {
    }
}

class Program {
    public static void Main(params string[] args) {
        Derived d = new Derived();
    }
}
3
ответ дан 4 December 2019 в 06:56
поделиться

Не сдавайтесь. Оружие, которое вы можете использовать, чтобы убедить ваших клиентов в негодности. Если вы можете восстановить пароли пользователей с помощью любого механизма, вы предоставили их клиентам законный механизм отказа от регистрации, и они могут отказаться от любой транзакции, которая зависит от этого пароля, потому что нет пути, что поставщик может доказать, что они не восстановили пароль и провести транзакцию через себя. Если пароли правильно хранятся в виде дайджестов, а не шифротекста, это невозможно, эрго либо конечный клиент выполнил транзакцию сам, либо нарушил свою обязанность по уходу w.r.t. пароль. В любом случае, что оставляет ответственность прямо с ним. Я работал над случаями, когда это составляло бы сотни миллионов долларов. Не то, что ты хочешь ошибиться.

-121--1751563-

См. этот связанный вопрос . Необходимо нарисовать собственный прямоугольник на CGPath с некоторыми скругленными углами, добавить CGPath в CGContext и затем подрезать его с помощью CGConTextClip .

Можно также нарисовать округленную прямую с альфа-значениями для изображения, а затем использовать это изображение для создания нового слоя, который был задан как свойство mask слоя ( см. документацию Apple ).

-121--2039011-

Я испытывал такую же боль в Google Wave Robot .NET API , где я хотел, чтобы конструктор передавал некоторые значения на основе атрибутов. Можно просмотреть мое решение в коде для производного типа и базового типа . В основном я передаю делегата базовому конструктору, а затем вызываю делегата, проходящего «это». Так что в вашем случае у вас было бы:

public VeryBaseClass(Func<VeryBaseClass, string> classNameProvider)
{
    this.name = classNameProvider(this);
}

и

public BaseClass() : base(FindClassName)
{
}

private static string FindClassName(VeryBaseClass @this)
{
    return @this.GetType().Name;
}

Это действительно уродливо, но это работает.

EDIT: Этот подход работает только в том случае, если можно изменить конструктор базового класса, как показано на рисунке; если вы не можете, я не уверен, что это вообще возможно: (

6
ответ дан 4 December 2019 в 06:56
поделиться

Еще один вариант ...

// VeryBaseClass is in an external assembly
public abstract class VeryBaseClass
{
    public VeryBaseClass(string className)
    {
        Console.WriteLine(className);
    }
}

// BaseClass and InheritedClass are in my assembly
public abstract class BaseClass : VeryBaseClass
{
    public BaseClass(string className)
        :
        base(className)
    {

    }
}

public class InheritedClass : BaseClass
{
    public InheritedClass()
        : base(typeof(InheritedClass).Name)
    {
    }
}
0
ответ дан 4 December 2019 в 06:56
поделиться

Если способность определять тип унаследованного класса во время выполнения более важна, чем производительность, вы можете взглянуть на StackTrace, чтобы увидеть, где вызывается конструктор из. При вызове GetInheritedClassName в этом примере вам может потребоваться ввести больше допущений:

public abstract class BaseClass : VeryBaseClass
{
    private static string GetInheritedClassName
    {
        get
        {
            // Get the current Stack
            StackTrace currentStack = new StackTrace();
            MethodBase method = currentStack.GetFrame(1).GetMethod();

            // 1st frame should be the constructor calling
            if (method.Name != ".ctor")
                return null;

            method = currentStack.GetFrame(2).GetMethod();

            // 2nd frame should be the constructor of the inherited class
            if (method.Name != ".ctor")
                return null;

            // return the type of the inherited class
            return method.ReflectedType.Name;
        }
    }

    public BaseClass(MyObject myObject) :
        base(GetInheritedClassName, myObject)
    {

    }
}

Я не могу придумать отличный способ динамического получения имени унаследованного класса без последствий для производительности. Я понимаю, что это то, чего вы хотели избежать, но если бы мне нужно было вызвать стороннюю сборку с этими требованиями, я бы просто потребовал, чтобы каждый класс указывал свой собственный тип:

public abstract class BaseClass : VeryBaseClass
{
    public BaseClass(string className, MyObject myObject) :
        base(className, myObject)
    {

    }
}

public class InheritedClass : BaseClass
{
    public InheritedClass(MyObject myObject) : base("InheritedClass", myObject)
    {

    }
}
3
ответ дан 4 December 2019 в 06:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: