Can a C# Class Inherit Attributes from Its Interface

Can a C# class inherit attributes from its interface?

No. Whenever implementing an interface or overriding members in a derived class, you need to re-declare the attributes.

If you only care about ComponentModel (not direct reflection), there is a way ([AttributeProvider]) of suggesting attributes from an existing type (to avoid duplication), but it is only valid for property and indexer usage.

As an example:

using System;
using System.ComponentModel;
class Foo {
[AttributeProvider(typeof(IListSource))]
public object Bar { get; set; }

static void Main() {
var bar = TypeDescriptor.GetProperties(typeof(Foo))["Bar"];
foreach (Attribute attrib in bar.Attributes) {
Console.WriteLine(attrib);
}
}
}

outputs:

System.SerializableAttribute
System.ComponentModel.AttributeProviderAttribute
System.ComponentModel.EditorAttribute
System.Runtime.InteropServices.ComVisibleAttribute
System.Runtime.InteropServices.ClassInterfaceAttribute
System.ComponentModel.TypeConverterAttribute
System.ComponentModel.MergablePropertyAttribute

Can an attribute require inheritance or implementation of a class or interface?

Unfortunately, this is not directly supported by the C# language.

However, you can write your own code analysis rule using the .NET Compiler Platform (aka Roslyn) and enforce that condition yourself.

In C#, do attributes defined in an interface apply to implementing classes?

The attributes are queried via reflection and can be accessed in whatever way the developer wants to. To show proof of how this works in your example code, I had a look at the NewtonSoft.Json source to see how it loaded this value.

The way it gets the JsonProperty attribute is by calling the following on a MemberInfo.

JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(member)

The source for this method at the time of this question can be seen here

As you can see on lines 364-376, it loops over the MemberInfo's interfaces, then tries to get the attribute from the interface if it is unable to load the JsonProperty from the class it is being used on.

Using attribute of inherited property from an interface

Child does not have any custom attributes, ITest has them, so you will have to call GetCustomAttributes on the members of ITest.

There is a difference between inheritance and implementation. Inheritance would be fine if Child was derived from some base class that had a y property decorated with My1Attribute.

In your case, Child implements ITest and ITest is a different type, outside of the inheritance hierarchy.

void Main()
{
var my1Attribute = typeof(ITest).GetProperty("y").GetCustomAttribute(typeof(My1Attribute)) as My1Attribute;
Console.WriteLine(my1Attribute.x); // Outputs: 0
}

[AttributeUsage(AttributeTargets.Property, Inherited = true)]
class My1Attribute : Attribute
{
public int x { get; set; }
}

interface ITest
{
[My1]
int y { get; set; }
}

class Child : ITest
{
public Child() { }

public int y { get; set; }
}

C# Inheriting properties from parent interface

It's not possible to do what you intend with interfaces. As you've seen, when a class implements two or more interfaces which themselves inherit a common interface, the common interface is implicitly added, but only once - you don't get a variant of the base interface for each derived interface.

You could try the following (based on the Command pattern):

interface ICommand {
HttpMethod HttpMethod { get; }
string QueryUriSegment { get; }

void Execute();
}

class abstract BaseCommand : ICommand {
public abstract HttMethod { get; }
public abstract string QueryUriSegment { get; }
}

class CreateNodeCommand : ICommand {
public override HttpMethod HttpMethod { get { /* return HttpMethod for "create node" */ } }
public override string QueryUriSegment { get { /* return QueryUriString for "create node" */ } }

public void Execute() { /* Create node... */ }
}

class CreateNodeWithPropertiesCommand : ICommand {
public override HttpMethod HttpMethod { get { /* return HttpMethod for "create node with properties" */} }
public override string QueryUriSegment { get { /* return QueryUriString for "create node with properties" */ } }

public void Execute() { /* Create node with properties ... */ }
}

In your TestImplClass you can have each command as a separate property:

public TestImplClass {
public ICommand CreateNode { get; private set; }
public ICommand CreateNodeWithProperties { get; private set; }

public TestImplClass(ICommand createNode, ICommand createNodeWithProperties) {
this.CreateNode = createNode;
this.CreateNodeWithProperties = createNodeWithProperties;
}
}

Each command then has it's own HttpMethod and QueryUriSegment properties and you can mock each command and pass them into the constructor of TestImplClass when testing.

When it comes to using any of the commands you can just call Execute() on the appropriate property e.g: dataAccess.CreateNode.Execute();.

Attribute on Interface members does not work

Attributes on interface properties doesn't get inherited to the class, you may make your interface an Abstract Class.

Found an answer from Microsoft:

The product team does not want to implement this feature, for two main
reasons:

  • Consistency with DataAnnotations.Validator
  • Consistency with validation behavior in ASP.Net MVC
  • tricky scenario: a class implements two interfaces that have the same property, but with conflicting attributes on them. Which
    attribute would take precedence?


Related Topics



Leave a reply



Submit