Как иметь дело с запечатанным классом, когда я хотел наследовать и добавить свойства

В недавнем вопросе на Переполнении стека я спросил, как я мог бы проанализировать через имя файла к дополнительной meta информации о файле.

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

class BackupFileInfo : FileInfo, IEquatable
{
    //Properties and Methods here
}

Идея состояла бы в том, что я сохраню оригинал FileInfo возразите при добавлении метаинформации в свойствах объекта, который реализует FileInfo, такой как IsMainBackup.

Однако FileInfo изолируется, что означает, что другие классы не могут наследоваться ему.

Вместо этого я закончил со следующим:

class BackupFileInfo : IEquatable
{
    public bool IsMainBackup { get; set; }
    public int ImageNumber { get; set; }
    public int IncrementNumber { get; set; }
    public FileInfo FileInfo { get; set; }

    //public BackupFileInfo() //constructor here

    public bool Equals(BackupFileInfo other)
    {
        return (this.FileInfo.Name == other.FileInfo.Name
             && this.FileInfo.Length == other.FileInfo.Length);
    }

}

Я ужасно не взволнован этим решением потому что вместо способности использовать BackupFileInfo.Length, Я оказываюсь перед необходимостью использовать BackupFileInfo.FileInfo.Length. Возможно, это уже - лучшая практика, но что-то не чувствует себя хорошо.

Существует ли лучший способ иметь дело с этой проблемой?

39
задан Community 23 May 2017 в 12:25
поделиться

6 ответов

Это одна из классических композиций вместо примеров наследования, и вы пошли в правильном направлении.

Для решения проблемы с свойствами просто создайте свойство под названием Length , которое делегирует инкапсулированный объект FileInfo .

29
ответ дан 27 November 2019 в 02:44
поделиться

Вы можете просто разоблачить свойства в FileInfo, о которых вы заботитесь. Что-то вроде этого:

public long Length { get { return FileInfo.Length; } }

Очевидно, что это становится менее практичным, если вы хотите делегировать множество свойств FileInfo.

.
11
ответ дан 27 November 2019 в 02:44
поделиться

Pass-thru?

class BackupFileInfo : IEquatable<BackupFileInfo>
{
    public long Length {get {return FileInfo.Length;}}
    //.... [snip]
}

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

4
ответ дан 27 November 2019 в 02:44
поделиться

Вы можете добавить в свой класс оператор имплицитный.

Eg:

class BackupFileInfo .... {
  /* your exiting code */

  public static implicit operator FileInfo( BackupFileInfo self ){
     return self.FileInfo;
  }
}

Затем вы можете обращаться со своим объектом BackupFileInfo как с объектом FileInfo

BackupFileInfo bf = new BackupFileInfo();
...
int mylen = ((FileInfo)bf).Length;
10
ответ дан 27 November 2019 в 02:44
поделиться

При желании вы можете легко обернуть свойства информации о файле в свои собственные свойства.

public long Length
{
    get
    {
       return this.FileInfo.Length;
    }
}
2
ответ дан 27 November 2019 в 02:44
поделиться

Это на самом деле не решает Вашей большой проблемы, но, конечно, Вы можете просто сделать так, чтобы свойства, которые Вы хотите использовать, действовали как прокси-серверы к реальным свойствам, находящимся под ними. Например

public long Length
{
    get {return FileInfo.Length;}
}

(Конечно же, с помощью элементарной нулевой проверки)

.
2
ответ дан 27 November 2019 в 02:44
поделиться