Ограничить метод класса
Допустим, есть такой класс:
public abstract class AbstractClass
{
public abstract bool Send<T>(T msg);
}
Я хочу произвести наследование:
ConcreateClass<T>:AbstractClass
Но так, чтоб T ограничивала возле определения класса, ограничила метод абстрактного класса и туда можно было передавать не все подряд, а то с каким параметром типа будет создан класс.
Я могу это сделать?
Потом я хочу это все добавить в словарь Dictionary<Type,AbstractClass> и определяя тип msg передавать его в конкретный обработчик.
Ответы (2 шт):
А зачем собственно абстрактный класс, суйте интерфейс
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);
}
Инкапсулируй добавление/хранение/извлечение обработчика. Внутри можно хоть в 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());