У меня есть интерфейс, который расширяет некоторый другой интерфейс, например:С в качестве параметра делегат, который принимает базовый интерфейс
interface IBase
{
int Id { get; set; }
string Name { get; set; }
}
interface IExtended : IBase
{
bool IsChecked { get; set; }
}
Затем я использую базовый интерфейс в качестве параметра в функции делегата, который также параметр конструктора класса, например:
public class SomeClass
{
private IBase _model;
private Func<IBase, string> _handler;
public SomeClass(IBase model, Func<IBase, string> handler)
{
_model = model;
_handler = handler;
}
public string ExecuteHandler()
{
return _handler(model);
}
}
реализации интерфейса:
public class BaseImplementation : IBase
{
int Id { get; set; }
string Name { get; set; }
public BaseImplementation(int id, string name)
{
Id = id;
Name = name;
}
}
public class ExtendedImplementation : IExtended
{
int Id { get; set; }
string Name { get; set; }
bool IsChecked { get; set; }
public BaseImplementation(int id, string name, bool isChecked)
{
Id = id;
Name = name;
IsChecked = isChecked;
}
}
Целевое назначение:
BaseImplemetation baseModel = new BaseImplementation(1, "base");
ExtendedImplemetation extendedModel = new ExtendedImplementation(2, "extended", true);
SomeClass someClass1 = new SomeClass(baseModel, (IBase arg) => {
Console.Write("Remember, " + arg.name + ", YOLO!");
});
SomeClass someClass2 = new SomeClass(extendedModel, (IExtended arg) => {
Console.Write(arg.name + ", YOLO! You're " + (arg.IsChecked) ? "checked!" : "not checked!");
});
string res1 = someClass1.ExecuteHandler();
string res2 = someClass2.ExecuteHandler();
Но это (не работает, даже если реализация IExtended обязательно реализовать все, что определяется с помощью интерфейса IBase. Почему это так, и как бы я обойти это и получить результат, который я хочу?
EDIT:
Я думаю, что я получил его.
Я думал, что Func<IBase, string>
равно Func<IExtended, string>
потому IExtended конечно реализует все, что IBase делает, поэтому не должно быть никаких проблем, не так ли? Реализация, поскольку я хотел, чтобы она была и указана в моем примере, конечно, будет работать нормально.
НО! Проблема заключается в том, что someClass2 не может быть построена так, потому что, как уже упоминалось @Servy, функция делегат может сделать что-то вроде этого:
SomeClass someClassWrong = new SomeClass(baseModel, (IExtended arg) => {
if (arg.IsChecked) {
// gotcha, baseModel doesn't have IsChecked property!
}
});
EDIT 2:
Спасибо всем вам за помощью и извините за постоянное редактирование и дает неправильный пример SOF, что я хочу: D
Делегат должен всегда использовать только методы, определенные в IBase (так в этом примере IBase.SomeMethod()) внутри SomeClass. Другие методы, определенные в IExtended, используются в других частях приложения, но в этом конкретном случае я хотел бы использовать существующий делегат с реализациями IExtended. – DekiChan
@DekiChan Как я уже сказал, либо фактические объекты, которые вы передаете делегату при его вызове, всегда являются экземплярами «IExtended», и в этом случае вам нужно изменить делегат, который вы принимаете, или нет, и код предоставляя делегату, не может предположить, что они являются экземплярами «IExtended». Вы не можете предоставить объекты 'IBase', которые не являются' IExtended', и получить поведение 'IExtended'. – Servy
Я расширил свой вопрос, надеюсь, более ясное объяснение того, что я хотел бы сделать. – DekiChan