Производный родовой класс не видит переменные родителя - PullRequest
0 голосов
/ 16 мая 2019

Я пытаюсь изолировать классы от других, которые устанавливают или изменяют данные в классе. Я решил использовать абстрактный базовый класс с именем Parent, а затем два производных абстрактных класса с именами DerivedA и DerivedB. Затем, используя Assembly, я получаю производные абстрактные классы от Parent. Затем я использую дженерики для получения конкретного класса ConcreteGeneric, чтобы, надеюсь, заполнить значения абстрактных классов.

Проблема, с которой я сталкиваюсь, заключается в том, что когда я попадаю в свой конкретный класс, у меня нет доступа (см.) К элементам / свойствам родительского класса. Может быть, это неправильный дизайн, но это идеальный способ, которым я хотел бы решить его. Любая помощь будет с благодарностью ... и сохранить волосы, которые падают с моей головы. ;)

Код прилагается.

Я задокументировал то, что хотел бы в коде. Чтобы иметь возможность доступа и просмотра открытых переменных в родительских классах.

using System;
using System.Linq;
using System.Reflection;

public abstract class Parent
{
    public string Name { get; set; }
    public string Comment { get; set; }
}

public abstract class DerivedA : Parent
{
    public string DerivedAString { get; set; }
}

public abstract class DerivedB : Parent
{
    public string DerivedBString { get; set; }
}

public class DerivedFromA : DerivedA
{
    public string DerivedFromAString { get; set; }
}

public class ConcreteGeneric<T> where T : Parent
{
    private string _jsonString = "";
    public string HeaderString
    {
        get
        {
            return _jsonString;
        }
        set
        {
            /// I want to be able to see the Derived classes parameters 
            /// here.  Like   'DerivedB.DerivedBString'  if T is type DerivedB 
            _jsonString = value;
        }
    }
}

public class RunItClass
{
    public static void Main()
    {
        Type[] types = Assembly.GetAssembly(typeof(Parent)).GetTypes();
        foreach (Type type in Assembly.GetAssembly(typeof(Parent)).GetTypes()
            .Where(myType => myType.IsAbstract && myType.IsSubclassOf(typeof(Parent))))
        {
            var genType = typeof(ConcreteGeneric<>).MakeGenericType(type);
            Type genericType = (Type)genType;

            object genericInstance = Activator.CreateInstance(genericType);
            dynamic dynamicObj = Convert.ChangeType(genericInstance, genericType);

            /// Note that when I drop into the 'set' method on this dynamic object, I cannot see the 
            /// paramters of the parent class, which is 'DerivedA' on the first item in this loop. 
            dynamicObj.HeaderString = "Testing";

            // Testing here
            if (genericType == typeof(ConcreteGeneric<DerivedA>))
            {
                // ?? I CANNOT see all of the variables in 'DerivedA' ??
                ConcreteGeneric<DerivedA> da = (ConcreteGeneric<DerivedA>)genericInstance;

                /// I CAN see all of the variables in 'DerivedA' and also 'Parent'.  This is what I
                /// am after, but I want to be able to use the ConcreteGeneric<![CDATA[>]]> to accomplish this.
                /// Please help.  :)
                DerivedFromA dfa = new DerivedFromA();

                Console.WriteLine();
            }
        }
    }
}

1 Ответ

1 голос
/ 16 мая 2019

Код внутри вашего ConcreteGeneric<T> класса должен работать с любым T, который вы можете решить передать. Поскольку вы ограничили T до Parent, это означает, что вы можете получить доступ к любому из Parent's свойств.

Вы можете сказать: " Я хочу, чтобы здесь можно было видеть параметры производных классов ", но что если вы создали ConcreteGeneric<DerivedA>? Тогда у вас не будет DerivedBString собственности для вас.

Что вы могли бы сделать, это выставить свой T прямо внутри ConcreteGeneric<T>:

public T Item { get; }

Тогда вы сможете наложить genericType на ConcreteGeneric<DerivedA> и получить доступ к .Item:

var concreteDerivedA = (ConcreteGeneric<DerivedA>)genericType;
string s = conceteDerivedA.Item.DerivedAString;

Это ставит вас перед вопросом о том, как установить Item. Если вы обязуетесь иметь конструктор без параметров, вы можете сделать это:

public class ConcreteGeneric<T> where T : Parent, new()
{
    public T Item { get; } = new T();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...