Каков правильный подход, когда у меня много классов с одинаковыми свойствами, но они отличаются такими методами, как load и refresh?

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

abstract class Base 
{ 
    public int Property { get; set; }
    public abstract void Load();
}

class A : Base
{
    public override Load(){do stuff that A needs to decide how to set Property}
}

class B : Base
{
    public override Load(){do stuff that B needs to decide how to set Property}
}

Это нормально? Как мне создать список этих разных объектов?

Может быть, Интерфейс поможет вам с вашей проблемой

Henrik Wilshusen 10.08.2018 14:37

На мой взгляд, вам следует создать interface методом void Load(). Затем make Base реализует ваш интерфейс Base : ILoadable и реализует ваш метод как в A, так и в B.

Maxime Recuerda 10.08.2018 14:37

@OndrejTucny Я бы сказал, что довольно ясно, чего хочет достичь OP. И если вы хотите перебрать каждый элемент, я бы сказал, что общий Interface, реализованный каждым классом, будет лучшим вариантом. Затем создайте список типа yourInterface

Ryan Wilson 10.08.2018 14:40

@OndrejTucny Я хотел бы иметь возможность перебирать List, который содержит один экземпляр A, один экземпляр B, один экземпляр C и так далее, чтобы вызвать Load для всех из них

Cencek 10.08.2018 14:42

@ ČeněkSůva Что ж, у вас есть общий предок. Так с какой проблемой вы столкнулись? Идите вперед и покажите соответствующий код.

Ondrej Tucny 10.08.2018 14:43

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

Cencek 10.08.2018 14:50

Ну, вы не предоставили какой, который вы пробовали. Итак, как мы могли узнать, что наше решение лучше или хуже вашего? В любом случае: если вы уже являетесь имеют рабочим решением, вам следует подумать о том, чтобы опубликовать этот вопрос как обзор на codereview.stackexchange.com. Но также мы предполагаем, что вы предоставляете то, что пробовали.

HimBromBeere 10.08.2018 14:57
0
7
60
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Думаю, вы хотите этого добиться:

List<Base> list = new List<Base>();
list.Add(new A());
list.Add(new B());
foreach (var t in list) 
      t.Load();

Эти классы - одиночки. Вы не можете создавать экземпляры синглтонов, поскольку их конструктор обычно является частным.

HimBromBeere 10.08.2018 14:41

Я просто привел пример того, как использовать Abstract или Interface в цикле с подклассами или имплементациями. Он уже должен думать о других шагах, чтобы достичь своей логики. Также он написал «Каждый экземпляр классов A, B»

Simion 10.08.2018 14:43

Также обратите внимание на предупреждение во время компиляции. Если компилятор C# сказал, что член A скрывает другой член B. Не используйте ключевое слово new, чтобы предупреждение исчезло. Вместо этого либо удалите «лишний» член из производного класса, либо, если вам нужны оба члена, выберите другое имя для нового члена, которое не конфликтует с именами, унаследованными от базового класса. Конечно, если вы хотите специализировать поведение унаследованного члена, используйте virtual on base и переопределите.

Gauravsa 10.08.2018 14:46
Ответ принят как подходящий

Сначала вам нужно получить все типы, которые наследуют ваш класс Base, используя отражение:

var types = myAssembly.GetTypes().Where(x => x.BaseType == typeof(Base));

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

var instances = types.GetProperty("Instance").GetValue(null);

Теперь поместите эти экземпляры в список и зациклите их, чтобы вызвать ваш Load-метод. Как вы уже знаете, все типы являются производными от Base, вы можете безопасно преобразовать их в этот класс во время цикла:

foreach(Base instance in instances)
    instance.Load();

Другие вопросы по теме