Хорошо, я пытаюсь сделать следующее:
protected bool ValidAdvert(Base item)
{
throw ThisIsAnAbstractClassException();
}
protected bool ValidAdvert(Derived1 item)
{
return ADerived1SpecificPredicate;
}
protected bool ValidAdvert(Derived2 item)
{
return ADerived2SpecificPredicate;
}
И имейте версии Производного класса метода быть названными, когда Базовый класс будет передан методу. Базовый класс абстрактен, таким образом, это, в теории, должно быть возможно?
Прежде чем кто-то скажет что-то о перегрузке метода на самих классах, логика в методах полагается на большое количество различных условий, ни одно из которых не связано, и ни один из который связанный с Основой/Производным классом непосредственно (такой как состояние входа в систему, и т.д.)
Если двойная отправка окажется слишком навязчивой, то можно вызвать метод отражением и динамически разрешить соответствующую перегрузку.
protected bool ValidAdvert(Base item)
{
if (item.GetType() == typeof(Base))
throw new ThisIsAnAbstractClassException();
Type type = typeof(CurrentClass);
MethodInfo method = type.GetMethod("ValidAdvert",
BindingFlags.Instance | BindingFlags.NonPublic,
null,
new Type[] { item.GetType() },
null);
return (bool)method.Invoke(this, new object[] { item });
}
protected bool ValidAdvert(Derived1 item)
{
return ADerived1SpecificPredicate;
}
protected bool ValidAdvert(Derived2 item)
{
return ADerived2SpecificPredicate;
}
Этот паттерн называется MultipleDispatch , хотя вызов метода путем отражения медленнее, чем прямой вызов метода (это не будет перегрузкой, если метод вызывается менее нескольких сотен раз в секунду), его преимущество заключается в том, что он не требует изменения иерархии классов, как в паттерне двойной диспетчеризации.
Это будет еще проще, когда c# 4.0 выйдет с динамическим ключевым словом:
protected bool ValidAdvert(Base item)
{
if (item.GetType() == typeof(Base))
throw new ThisIsAnAbstractClassException();
dynamic dynamicThis = this;
return (bool)dynamicThis.ValidAdvert(item as dynamic);
}
Идеальное место для использования двойной отправки:
class Base
{
public abstract bool IsValid(IAdvertValidator validator);
}
class Derived1 : Base
{
public bool IsValid(IAdvertValidator validator)
{
return validator.ValidAdvert(this);
}
}
class Derived2 : Base
{
public bool IsValid(IAdvertValidator validator)
{
return validator.ValidAdvert(this);
}
}
interface IAdvertValidator
{
bool ValidAdvert(Derived1 d1);
bool ValidAdvert(Derived2 d2);
}
Я не совсем уверен, как у вас когда-либо будет экземпляр базового класса, который на самом деле не является экземпляром производного класса. Поскольку базовый класс является абстрактным, его нельзя создать. Я предполагаю, что он будет соответствовать любому производному классу, у которого нет конкретной сигнатуры, но, похоже, это не то, что вы собираетесь.