K
K
Kalantyr2011-07-01 15:23:32
OOP
Kalantyr, 2011-07-01 15:23:32

Multiple inheritance in C# for properties (or function parameters)

Such a situation: several interfaces are defined (for example: IMyInterface1, IMyInterface2, ...). The class MyClasshas a property IMyInterface MyProperty { get; set; }.

I would like the property to implement two or three interfaces at once (just like a class can do it) without losing strong typing.

As far as I know, the C# syntax does not allow this. I don't want to create a separate type for each bunch of interfaces (too many combinations will turn out). Creating a bunch of properties, each of which implements a separate interface, is also somehow crooked.

I suggest not discussing interface inheritance, as it is not good (inheritance is just a spectacular way to avoid code duplication). Interfaces are independent.

What are the suggestions?



  interface IClickableButton
  {
    event Action Click;
  }

  interface IColorButton
  {
    Color Color { get; set; }
  }

  class MyForm
  {
    public IClickableButton ClickableButton { get; set; }
    public IColorButton ColorButton { get; set; }
    public <IClickableButton, IColorButton> ClickableColorButton { get; set; }
  }


There are two interfaces: "PressableButton" and "ColoredButton". I want the "PressableColorButton" property of the "MyForm" class to somehow implement both of these interfaces at once.

Now I have to make two separate properties. How to combine them into one? (the code <IColorButton, IColorButton> ClickableColorButton { get; set; }will not work, I wrote this for clarity)

PPS:

In the end, we came to the question " why might this be necessary? " I agree - the task is rarely encountered. And the goal is the same - reducing the relationship of code blocks.

Let's say we create controller classes that manage user interface forms. Controllers do not work directly with classes, but through an interface. In most cases, it is enough for the controller to subscribe to the "PressableButton" event and process it. But in one of the twenty controllers, for example, not only processes the click, but also has to change the color of this button. And a couple of controllers, in addition to clicking, should change the text on the button. Of course, you can create an interface with "click", "color" and "text" at once. But after all, most of the controllers do not need other properties at all - they only need a click. So the problem arises - how to transfer the "color" or "text" properties only in those rare cases when they are really needed.

And one more thing - if the code is covered by unit tests - it may be necessary to slip mocks as experimental objects. The simpler the interfaces, the easier it is to create these mock objects.

Probably, someone will say that this is already an excessive abstraction, too detailed - perhaps ... But I'm interested here - is there a possibility. To what extent it is used is another question.

PPPS: the solution suitable for me is described here: habrahabr.ru/blogs/net/123229 While writing the topic, the user tenbits suggested exactly the same solution.

Answer the question

In order to leave comments, you need to log in

9 answer(s)
I
int02h, 2011-07-01
@int02h


interface IMyInterface1
{
    string Prop1 {get;set;}
    string Prop2 {get;set;}
}

interface IMyInterface2
{
    string Prop1 {get;set;}
    string Prop3 {get;set;}
}

class MyClass : IMyInterface1, IMyInterface2
{
    string Prop1 {get; set } // Общее свойство
    string Prop2 {get; set }
    string Prop3 {get; set }
}

Do you mean such a situation? If yes, then you can do it. The Prop1 property will implement 2 interfaces at once.

I
int02h, 2011-07-01
@int02h

After clarifying the question, it became somewhat clearer. Try using dynamic to do:


public dynamic ClickableColorButton { get; set; }

Thus, you can put the object you need in ClickableColorButton, and then call methods from different interfaces at runtime.

A
Anatoly, 2011-07-01
@taliban

Alas, it won't work, as far as I know.

D
dewevle, 2011-07-01
@dewevle

I understand that you may be aware, but just in case.
Maybe Explicit Interface Inheritance is right for you?
interface IMyInterface1
{
string Prop1 {get;set;}
string Prop2 {get;set;}
}
interface IMyInterface2
{
string Prop1 {get;set;}
string Prop3 {get;set;}
}
class MyClass : IMyInterface1, IMyInterface2
{
string IMyInterface1.Prop1 {get; set }
string IMyInterface2.Prop1 {get; set }
string Prop2 {get; set }
string Prop3 {get; set }
}

B
bleykher, 2011-07-01
@bleykher

Perhaps something like this will suit you: you cannot return a link to 2 interfaces at once, because a class may have different implementations of the same methods for different interfaces, in which case it will not be clear which method should be executed.
class MyForm
{
public IClickableButton ClickableButton { get{return ClikableColorButton; }}
public IColorButton ColorButton { get {return ClickableColorButton; }}
public ClickableColorButton ClickableColorButton { get; set; }
}

S
Shedal, 2011-07-01
@Shedal

I don't think you've thought about how you want to use it. You still have to create a class object that inherits both interfaces, and, therefore, create the ColorClickableButton class: IClickableButton, IColorButton.
In any case, a construct like this might help you:

public class MyForm<T> where T : IClickableButton, IColorButton
{
    T Button { get; set; }
}

A
Alexander Keith, 2011-07-01
@tenbits

And you can use the dump:

        private static readonly Dictionary<Type, Object> Dump = new Dictionary<Type, object>();
        public T Get<T>() where T : class
        {
            return Dump.ContainsKey(typeof(T)) ? Dump[typeof(T)] as T : default(T);
        }
        public void Set<T>(T value) where T : class
        {
            Dump[typeof(T)] = value;
        }

P
PashaPash, 2011-07-01
@PashaPash

In the current version of C#, with the preservation of strong typing, no way. C# does not allow you to inherit from generic parameters. Something like interface IDoubleInterface<I1, I2>: I1, I2 {} won't work. Without generics, there will be no strict typing.
I'm not sure how vital the situation from PPS is, but in it the connectivity problem needs to be solved at a different level.
IMO, you should not even think about segregating the interfaces of individual controls if each controller receives a form with 50 fields, and can do anything with all its elements. Try to extract interfaces from the form itself - perhaps many controllers do not overlap at all in terms of the properties used.

P
PashaPash, 2011-07-02
@PashaPash

The DB example is not very obvious without code. It is not clear why it was necessary to enumerate interfaces in the business logic. Surely you could try something like IoC / DI and reflection to register all interfaces in the IoC container.
The Tuples solution is a good one. But I would like to understand what specific architectural problem it solves better than other methods.
I suggest waiting for comments in the habratopic.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question