Объявление интерфейса для метода базового класса для поддержки IoC
Итак, вот код:
interface A<T>
{
T Save();
}
interface B : A<B>
{
}
class BusinessBase<T>
{
T Save();
}
class D<T, U> : BusinessBase<T>
where T : BusinessBase<T>
where U : B<U>
{
new U Save()
{
base.Save(); // this is where the error is because T can't be converted to U
}
}
class Concrete : D<Concrete , B>, B
{
}
Итак, со всем, что я надеюсь получить, является базовый класс, который определяет все методы A, которые на самом деле просто перенаправляют на методы в C. Но для поддержки IoC и CSLA это должно быть так. Итак, я ищу, чтобы сохранение в D возвращало U, а не T, чтобы соответствовать сигнатуре интерфейса.
Я смотрю на это некоторое время и не могу понять, чего мне не хватает.
2 ответа
Итак, я просто хочу извиниться за плохой код, который был в моем примере. Но, надеюсь, если вы посмотрите на это какое-то время, вы увидите, где это пошло не так. Но вот ответ, который я придумал. Я думаю, что может быть лучший способ преобразования, но я хотел найти решение, которое не требовало бы изменения класса BusinessBase, поскольку это основной компонент CSLA, а не тот, который я хочу изменить. Вот код, который я придумал, который работает:
interface A<T>
{
T Save();
}
interface IConcreteInterface : A<IConcreteInterface>
{
}
class BusinessBase<T>
where T : BusinessBase<T>
{
public T Save()
{
return (T)this;
}
}
class D<T, U> : BusinessBase<T>
where T : BusinessBase<T>, A<U>
where U : A<U>
{
public new U Save()
{
return (U)(object)base.Save();
}
}
class ConcreteClass : D<ConcreteClass, IConcreteInterface>, IConcreteInterface
{
}
Изменения, которые заставили его работать, были следующими: return (U)(object)base.Save();
До того, как меня не поместили в (U) приведение к семплу, потому что он не скомпилировался бы так. Поскольку нет никакой связи между T и U, которая может быть определена. Таким образом, единственный способ обойти это - привести возвращаемое значение T из Save к (объекту), который, конечно, будет способен привести к чему угодно.
Вы заметили, что я также добавил ограничение типа для небольшой дополнительной защиты от ошибок приведения: я проверяю, что T относится к типу A, а U относится к типу A. Это гарантирует, что оба типа имеют одинаковый интерфейс.
Если у кого-то есть что-то красивее, я открыт для предложений. Но пока это работает, и я чувствую себя несколько хорошо об этом. Вы можете сделать то, что я сделал, что, по крайней мере, потребовало T для реализации. Это не красиво, и вы можете применить немного больше
Я думаю, что вам нужно:
class BusinessBase<T> : B
{
T Save();
}
а также:
class D<T, U> : BusinessBase<T>
where T : BusinessBase<T>
where U : B<U>
{
new U Save()
{
return base.Save();
}
}
Я думаю, что ошибка в том, что у вас нет никакой явной или явной связи между BusinessBase<T>.Save()
и B<U>
что ты пытаешься вернуться. Это возможно или это сломает другие интерфейсы?
Вы просматривали Expert C# 2008 Business Objects, который охватывает платформу CSLA?