Ограничить метод класса

Допустим, есть такой класс:

public abstract class AbstractClass
{
  public abstract bool Send<T>(T msg);
}

Я хочу произвести наследование:

ConcreateClass<T>:AbstractClass

Но так, чтоб T ограничивала возле определения класса, ограничила метод абстрактного класса и туда можно было передавать не все подряд, а то с каким параметром типа будет создан класс.

Я могу это сделать?

Потом я хочу это все добавить в словарь Dictionary<Type,AbstractClass> и определяя тип msg передавать его в конкретный обработчик.


Ответы (2 шт):

Автор решения: Aziz Umarov

А зачем собственно абстрактный класс, суйте интерфейс

interface ISender
{
  public bool Send<T>(T msg);
}

ConcreateClass<T>:ISender Where T: ....
{
   public bool Send<T>(T msg)
   {
       // Concreate implementation
   }
}

Выражение where T: Message в определении метода SendMessage говорит, что через универсальный параметр T будут передаваться объекты класса Message и производных классов. Благодаря этому компилятор будет знать, что T будет иметь функционал класса Message, и соответственно мы сможем обратиться к методам и свойствам класса Message внутри метода без проблем.

Пример как говорится на коленках.

static void Main(string[] args)
{
    Dictionary<Type, ISender> dic = new Dictionary<Type, ISender>();

    dic.Add( typeof(Dog) , new Dog());

    dic.Add(typeof(Cat), new Cat());

    foreach (var item in dic)
    {
        if (item.Key == typeof(Dog))
            item.Value.Send(new Dog());
        if (item.Key == typeof(Cat))
            item.Value.Send(new Cat());
    }

    Console.Read();

}

public class Dog : ISender
{
    public bool Send<Dog>(Dog msg)
    {
        Console.WriteLine(msg.GetType());
        return true;
    }
}

public class Cat : ISender
{
    public bool Send<Cat>(Cat msg)
    {
        Console.WriteLine(msg.GetType());

        return true;
    }
}


interface ISender
{
    bool Send<T>(T msg);
}
→ Ссылка
Автор решения: John

Инкапсулируй добавление/хранение/извлечение обработчика. Внутри можно хоть в object хранить.

public abstract class AbstractSender<T>
{
    public abstract bool Send(T msg);
}

public class Sender
{
    private readonly Dictionary<Type, object> _senders = new Dictionary<Type, object>();

    public void AddSender<T>(AbstractSender<T> sender)
    {
        _senders.Add(typeof(T), sender);
    }

    public AbstractSender<T> GetSender<T>()
    {
        if (_senders.TryGetValue(typeof(T), out object sender))
        {
            return sender as AbstractSender<T>;
        }
        else
        {
            throw new Exception("");
        }
    }
}

Тут правильнее на самом деле AbstractSender на интерфейс заменить, но суть та же будет. После просто регистрируешь нужные сендеры и можно их использовать.

public class Cat { }

public class CatSender : AbstractSender<Cat>
{
    public override bool Send(Cat msg)
    {
        Console.WriteLine("Send Cat");
        return true;
    }
}

public class Dog { }

public class DogSender : AbstractSender<Dog>
{
    public override bool Send(Dog msg)
    {
        Console.WriteLine("Send Dog");
        return true;
    }
}


var senders = new Sender();
senders.AddSender(new CatSender());
senders.AddSender(new DogSender());

senders.GetSender<Cat>().Send(new Cat());
→ Ссылка