Force a class implementing interface A to also inherit from a type derived from interface B

StackOverflow https://stackoverflow.com/questions/23647864

  •  22-07-2023
  •  | 
  •  

Question

what I want is that if class A implements my interface (B) I also want A being forced to implement an interface/type derived from type C.

In code, the result would look like this:

public interface SomeInterface
{
    // implementing this interface forces the implementing class to also implement
    // a derived interface/type of SomeBaseInterface 
    void SomeMethod();
}

public interface SomeBaseInterface
{
    void SomeBaseMethod();
}

public interface SomeOtherInterface : SomeBaseInterface
{
    void SomeOtherMethod();
}

public class ImplementingClass : SomeInterface, SomeOtherInterface // <- if not
 // implementing an interface/type derived from SomeBaseInterface
 // this should not compile
{
    public void SomeMethod()
    {
    }

    public void SomeOtherMethod()
    {
    }

    public void SomeBaseMethod()
    {
    }
}

*edit it would also work to 'mark' SomeBaseInterface as not inheritable by a class. Meaning that only another interface/abstract class can inherit from it. not possible, see C# Interfaces- only implement an interface in other interfaces

Was it helpful?

Solution

I don't think you can force the use of one interface when using another, unless you derive one interface from the other. However, you could use attributes and set up a unit test that would check your code for you.

[MyInterfaceCheck(typeof(IMyBaseInterface))]
public interface IMyInterfaceA {...}

public interface IMyBaseInterface {...}

public interface IMyInterfaceB : IMyBaseInterface {...}

public class MyClass : IMyInterfaceA, IMyInterfaceB {...}

The attribute would be defined simply as:

public class MyInterfaceCheckAttribute : Attribute
{
    public MyInterfaceCheckAttribute(Type typeThatShouldAlsoBeInherited)
    {
        if (!typeThatShouldAlsoBeInherited.IsInterface)
        {
            throw new ArgumentException("Incorrect type being used with MyInterfaceCheckAttribute.");
        }
        TypeThatShouldBeInherited = typeThatShouldAlsoBeInherited;
    }

    public Type TypeThatShouldBeInherited { get; private set; }
}

And the Unit Test:

[TestMethod]
public void CheckInterfaceInheritenceTest()
{
    Dictionary<Type, MyInterfaceCheckAttribute> typesToCheck = new Dictionary<Type, MyInterfaceCheckAttribute>();
    foreach (Type typeToCheck in Assembly.GetExecutingAssembly().GetTypes())
    {
        MyInterfaceCheckAttribute myAtt = typeToCheck.GetCustomAttribute(typeof(MyInterfaceCheckAttribute), true) as MyInterfaceCheckAttribute;
        if (myAtt != null)
        {
            typesToCheck.Add(typeToCheck, myAtt);
        }
    }

    foreach (Type typeToCheck in Assembly.GetExecutingAssembly().GetTypes())
    {
        Type[] interfaces = typeToCheck.GetInterfaces();

        foreach (KeyValuePair<Type, MyInterfaceCheckAttribute> kvp in typesToCheck)
        {
            if (interfaces.Contains(kvp.Key) && !interfaces.Contains(kvp.Value.TypeThatShouldBeInherited))
            {
                Assert.Fail("The type " + typeToCheck.Name + " should inherit the interface " + kvp.Value.TypeThatShouldBeInherited.Name);
            }
        }
    }
}

OTHER TIPS

The obvious way would be to have SomeInterface : SomeBaseInterface and have ImplementingClass : SomeInterface, SomeOtherInterface. Can you clarify why it is not a possibility? This forces the class implementing SomeInterface to at least inherit from SomeBaseInterface and this can be extended by additionally by inheriting from SomeOtherInterface.

The only difference is that it's possible to no inherit SomeOtherInterface, but for all you know that interface could contain nothing anyway.

EmptyInterface:

interface SomeOtherOtherInterface : SomeBaseInterface {
}

I would suggest if your wanting to allow the class to inherit from the above interface and not SomeBaseInterface you're doing something wrong. Also the implication is that your specifying for the existence of more unknown methods, which also is a touch suspicious.

Is it that there are things you should have put in SomeBaseInterface but didn't? Is there, for example, a void SendEmail in one derived interface and a void SendFax in another when clearly something like SendMessage should have been in SomeBaseInterface all along?

But obviously, if you want to proceed anyway use the unit testing approach.

Just to make it clear about inheritance and interfaces. Let's assume that we have interfaces IAnimal and IFeline:

interface IAnimal
{
    void Eat();
}

interface IFeline: IAnimal
{
    void Purr();
}

Now let's define class Cat and require it to implement interface IFeline:

class Cat: IFeline
{

}

Compiling the code:

'Cat' does not implement interface member 'IFeline.Purr()'
'Cat' does not implement interface member 'IAnimal.Eat()'

And now it is clear that compiler expects us to implement both interfaces IAnimal and IFeline in class Cat.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top