Как определить, какой класс наследования использует методы абстрактного класса - PullRequest
4 голосов
/ 18 апреля 2010

В моем консольном приложении есть абстрактный класс Factory "Listener", который содержит код для прослушивания и принятия соединений, а также порождения клиентских классов. Этот класс наследуется еще двумя классами (WorldListener и MasterListener), которые содержат более специфичные для протокола переопределения и функции.

У меня также есть вспомогательный класс (ConsoleWrapper), который инкапсулирует и расширяет System.Console, содержащий методы для записи в консоль информации о том, что происходит с экземплярами WorldListener и MasterListener.

Мне нужен способ определить в абстрактном ListenerClass, какой класс Inheriting вызывает его методы.

Любая помощь с этой проблемой будет принята с благодарностью! Я в тупике: X

Упрощенный пример того, что я пытаюсь сделать.

abstract class Listener
{
   public void DoSomething()
   {
      if(inheriting class == WorldListener)
      ConsoleWrapper.WorldWrite("Did something!");
      if(inheriting class == MasterListener)
      ConsoleWrapper.MasterWrite("Did something!");
   }
}

public static ConsoleWrapper
{
   public void WorldWrite(string input)
   {
       System.Console.WriteLine("[World] {0}", input);
   }
}

public class WorldListener : Listener
{
   public void DoSomethingSpecific()
   {
       ConsoleWrapper.WorldWrite("I did something specific!");
   }
}

public void Main()
{
   new WorldListener();
   new MasterListener();
}

Ожидаемый результат

[Мир] Что-то сделал!
[Мир] Я сделал что-то конкретное!
[Мастер] Сделал что-то!
[Мир] Я сделал что-то конкретное!

Ответы [ 3 ]

4 голосов
/ 18 апреля 2010

Если вы знаете каждый из типов, с которыми хотите сравнить, используйте оператор is:

if (this is WorldListener)
{
 // ...
}
else if (this is MasterListener)
{
 // ...
}

В качестве альтернативы, вы можете использовать GetType, если хотите немного большей гибкости:

var type = GetType();
// Do some logic on the type to determine what to do next.

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

Вы можете применить полиморфизм примерно так:

static class Program
{
    static void Main(string[] args)
    {
        Listener listener = new WorldListener();
        listener.DoSomething();
    }
}

abstract class Listener
{
    public void DoSomething()
    {
        var output = Decorate("Did something!");
        ConsoleWrapper.WriteLine(output);
    }

    protected abstract string Decorate(string input);
}

class WorldListener : Listener
{
    protected override string Decorate(string input)
    {
        return string.Format("[World] {0}", input);
    }
}

class MasterListener : Listener
{
    protected override string Decorate(string input)
    {
        return string.Format("[Master] {0}", input);
    }
}

Это приведет к выводу [World] Did something!. Преимущество этого подхода состоит в том, что если вы когда-нибудь захотите добавить другой тип слушателя, это просто вопрос определения нового класса для него с помощью соответствующего метода Decorate; нет необходимости изменять Listener сам.

2 голосов
/ 18 апреля 2010

Вы можете использовать

if (this is WorldListener)

вместо вашего псевдокода

if (inheriting class == WorldListener) 

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

2 голосов
/ 18 апреля 2010

Хм .. Ну, в вашем упрощенном примере вы не вызываете DoSomething () и DoSomethingSpecific (), и для MasterListener нет реализации ... Кроме того, если я правильно понимаю, в вашем ожидаемом результате ваш MasterListener.DoSomethingSpecific () запускает ConsoleWrapper.WorldWrite .. Вы, вероятно, имеете в виду MasterWrite?

В любом случае .. Вот рабочий пример, который делает то, что вы хотите (по крайней мере, так, как я понял ваш запрос: P)

Результат печати:

[World] Did something
[World] I did sth specific!
[Master] Did something
[Master] I did sth specific!

код:

    void Main()
{
    var wl = new WorldListener();
    wl.DoSomething();
    wl.DoSpecific();
    var ml = new MasterListener();
    ml.DoSomething();
    ml.DoSpecific();
}

public abstract class Listener
{
    public abstract string Category { get; }
    public void DoSomething()
    {
        ConsoleWrapper.Write(Category, "Did something");
    }
}

public static class ConsoleWrapper
{
    public static void Write(string category, string input)
    {
        Console.WriteLine("[{0}] {1}", category, input);
    }
}

public class WorldListener : Listener
{
    public override string Category { get { return "World"; } }
    public void DoSpecific()
    {
        ConsoleWrapper.Write(Category, "I did sth specific!");
    }
}

public class MasterListener : Listener
{
    public override string Category { get { return "Master"; } }
    public void DoSpecific()
    {
        ConsoleWrapper.Write(Category, "I did sth specific!");
    }
}
...