Топик родился из вопроса Множественное наследование в C# для свойств (или параметров функций). Прочитав по совету shedal статью, придумал способ как в C# в качестве типа указать несколько интерфейсов.
В C# можно сделать так, чтобы класс реализовывал несколько интерфейсов. А если нужно чтобы несколько интерфейсов реализовывало свойство? Не создавать же каждый раз для этого новый тип?
Итак, группировать интерфейсы будем при помощи кортежа, появившегося в dotNET 4 (класс Tuple<>). В 3 версии dotNET кортеж можно изготовить самостоятельно — это несложно.
На словах: есть три интерфейса, описывающих свойства кнопки: «КликабельнаяКнопка», «Цветная кнопка» и «КнопкаСТекстом». Нужно так абстрагироваться, чтобы в методы
При помощи класса Tuple<> группируем нужные интерфейсы — готово! Теперь к свойствам можно обращаться через
Если у кого-то есть решение красивее — давайте пробовать!
В C# можно сделать так, чтобы класс реализовывал несколько интерфейсов. А если нужно чтобы несколько интерфейсов реализовывало свойство? Не создавать же каждый раз для этого новый тип?
Итак, группировать интерфейсы будем при помощи кортежа, появившегося в dotNET 4 (класс Tuple<>). В 3 версии dotNET кортеж можно изготовить самостоятельно — это несложно.
interface IClickableButton
{
event Action Click;
}
interface IColorButton
{
Color Color { get; set; }
}
interface IButtonWithText
{
string Text { get; set; }
}
interface IMyForm1
{
Tuple<IClickableButton, IColorButton> Button { get; }
}
interface IMyForm2
{
Tuple<IClickableButton, IButtonWithText> Button { get; }
}
interface IMyForm3
{
Tuple<IClickableButton, IColorButton, IButtonWithText> Button { get; }
}
public class Button : IClickableButton, IColorButton, IButtonWithText
{
public event Action Click;
public Color Color { get; set; }
public string Text { get; set; }
}
class MyForm1 : IMyForm1
{
private readonly Button _button = new Button();
public Tuple<IClickableButton, IColorButton> Button
{
get { return new Tuple<IClickableButton, IColorButton>(_button, _button); }
}
}
class MyForm2 : IMyForm2
{
private readonly Button _button = new Button();
public Tuple<IClickableButton, IButtonWithText> Button
{
get { return new Tuple<IClickableButton, IButtonWithText>(_button, _button); }
}
}
class MyForm3 : IMyForm3
{
private readonly Button _button = new Button();
public Tuple<IClickableButton, IColorButton, IButtonWithText> Button
{
get { return new Tuple<IClickableButton, IColorButton, IButtonWithText>(_button, _button, _button); }
}
}
class UsageExample
{
void Example1(IMyForm1 form)
{
form.Button.Item1.Click += () => { };
form.Button.Item2.Color = Colors.Red;
}
void Example2(IMyForm2 form)
{
form.Button.Item1.Click += () => { };
form.Button.Item2.Text = "Hello, World!";
}
void Example2(IMyForm3 form)
{
form.Button.Item1.Click += () => { };
form.Button.Item2.Color = Colors.Red;
form.Button.Item3.Text = "Hello, World!";
}
}
На словах: есть три интерфейса, описывающих свойства кнопки: «КликабельнаяКнопка», «Цветная кнопка» и «КнопкаСТекстом». Нужно так абстрагироваться, чтобы в методы
Example1, Example2
и Example3
передавался лишь минимальный необходимый набор свойств. При этом должна сохраниться строгая типизация.При помощи класса Tuple<> группируем нужные интерфейсы — готово! Теперь к свойствам можно обращаться через
Item1, Item2, Item3
и т. д. При помощи кортежа можно объединить хоть десяток интерфейсов.Если у кого-то есть решение красивее — давайте пробовать!