получить доступ к наследуемым свойствам класса из базового класса - PullRequest
3 голосов
/ 28 июня 2011

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

public abstract class ClientEngine
{
        public void SaveFile(string fileName);
        {
            //Not implemented, I get error here because I don't know how to access Inherited class properties
            if (FileStorage != null))
                File.WriteAllBytes(fileName, FileStorage);
        }
}

    public interface IEngineEntity
    {
        byte[] FileStorage { get; set; }
    }

public class MyEntity1 : ClientEngine, IEngineEntity
{

public string MyProperty1 {get; set;}
public string MyProperty2 {get; set;}

public byte[] FileStorage { get; set; }
}

public class MyEntity2 : ClientEngine, IEngineEntity
{

public string MyProperty3 {get; set;}
public string MyProperty4 {get; set;}

public byte[] FileStorage { get; set; }
}

Ответы [ 3 ]

4 голосов
/ 28 июня 2011

Если вам нужен доступ к свойству из базового класса, вы делаете что-то не так. Имейте это в виду для ваших будущих проектов.

Вы должны объявить FileStorage в базовом классе, так как он есть у обоих унаследованных классов.

Если вы не хотите определять конкретный тип FileStorage (скажем, byte[]), вы можете определить его как более общий тип, например IEnumerable<byte>. В качестве альтернативы вы можете объявить FileStorage как интерфейс, который обеспечивает любое поведение, к которому вам нужно обращаться из базового класса.

Обновление

Замечательное замечание @ghimireniraj: вы также должны попытаться извлечь ClientEngine из IEngineEntity. Одним из основных моментов проектирования ОО является то, что если вы реплицируете поведение во всех унаследованных классах, оно должно быть в базовом классе.

Но вы действительно хотите получить доступ к некоторому коду из базового класса? Ты не должен. Но если вам действительно нужно, вы всегда можете разыграть:

public abstract class ClientEngine
{
    public void SaveFile(string fileName);
    {
        byte[] fileStorage = null;
        if (this is MyEntity1)
        {
            MyEntity1 me1 = (MyEntity1)this;
            fileStorage = me1.FileStorage;
        }
        else if (this is MyEntity2)
        {
            MyEntity2 me2 = (MyEntity2)this;
            fileStorage = me2.FileStorage;
        }
        if (fileStorage != null))
            File.WriteAllBytes(fileName, fileStorage);
    }
}

Противно, верно? Но это должно выглядеть грязно, потому что мы пытаемся сломать ОО дизайн.

Update

Другой путь идет по предложению Марка Гравелла. Вместо приведения к типам приведите к интерфейсу. Но все это по-прежнему плохо пахнет для меня: я твердо верю, что вы можете улучшить свой дизайн.

3 голосов
/ 28 июня 2011

Способ сделать это - сделать его абстрактным членом в базовом классе и переопределить в производном; другой подход, который вы могли бы использовать, это попытаться привести this к IEngineEntity - если это удастся, используйте его через интерфейс, т.е.

var engine = this as IEngineEntity;
if(engine == null) throw new InvalidOperationException(
   "All engine implementations must provide an IEngineEntity implementation");
var bytes = engine.FileStorage;

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

0 голосов
/ 05 декабря 2017

Еще одна функциональная альтернатива:

var derivedType = Type.GetType(this.GetType().FullName);
var FileStorage = derivedType.GetProperty("FileStorage", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic).GetValue(this) as byte[];
if (FileStorage != null) 
{
    ...
}
...