Une classe C # peut-elle hériter des atsortingbuts de son interface?

Cela semblerait impliquer “non”. Ce qui est regrettable

[AtsortingbuteUsage(AtsortingbuteTargets.Interface | AtsortingbuteTargets.Class, AllowMultiple = true, Inherited = true)] public class CustomDescriptionAtsortingbute : Atsortingbute { public ssortingng Description { get; private set; } public CustomDescriptionAtsortingbute(ssortingng description) { Description = description; } } [CustomDescription("IProjectController")] public interface IProjectController { void Create(ssortingng projectName); } internal class ProjectController : IProjectController { public void Create(ssortingng projectName) { } } [TestFixture] public class CustomDescriptionAtsortingbuteTests { [Test] public void ProjectController_ShouldHaveCustomDescriptionAtsortingbute() { Type type = typeof(ProjectController); object[] atsortingbutes = type.GetCustomAtsortingbutes( typeof(CustomDescriptionAtsortingbute), true); // NUnit.Framework.AssertionException: Expected: 1 But was: 0 Assert.AreEqual(1, atsortingbutes.Length); } } 

Une classe peut-elle hériter des atsortingbuts d’une interface? Ou suis-je en train d’aboyer le mauvais arbre ici?

Non. Lorsque vous implémentez une interface ou que vous remplacez des membres dans une classe dérivée, vous devez déclarer à nouveau les atsortingbuts.

Si vous ne vous souciez que de ComponentModel (pas de reflection directe), il existe un moyen ( [AtsortingbuteProvider] ) de suggérer des atsortingbuts à partir d’un type existant (pour éviter la duplication), mais uniquement pour les propriétés et les indexeurs.

Par exemple:

 using System; using System.ComponentModel; class Foo { [AtsortingbuteProvider(typeof(IListSource))] public object Bar { get; set; } static void Main() { var bar = TypeDescriptor.GetProperties(typeof(Foo))["Bar"]; foreach (Atsortingbute atsortingb in bar.Atsortingbutes) { Console.WriteLine(atsortingb); } } } 

les sorties:

 System.SerializableAtsortingbute System.ComponentModel.AtsortingbuteProviderAtsortingbute System.ComponentModel.EditorAtsortingbute System.Runtime.InteropServices.ComVisibleAtsortingbute System.Runtime.InteropServices.ClassInterfaceAtsortingbute System.ComponentModel.TypeConverterAtsortingbute System.ComponentModel.MergablePropertyAtsortingbute 

Vous pouvez définir une méthode d’extension utile …

 Type type = typeof(ProjectController); var atsortingbutes = type.GetCustomAtsortingbutes( true ); 

Voici la méthode d’extension:

 /// Searches and returns atsortingbutes. The inheritance chain is not used to find the atsortingbutes. /// The type of atsortingbute to search for. /// The type which is searched for the atsortingbutes. /// Returns all atsortingbutes. public static T[] GetCustomAtsortingbutes( this Type type ) where T : Atsortingbute { return GetCustomAtsortingbutes( type, typeof( T ), false ).Select( arg => (T)arg ).ToArray(); } /// Searches and returns atsortingbutes. /// The type of atsortingbute to search for. /// The type which is searched for the atsortingbutes. /// Specifies whether to search this member's inheritance chain to find the atsortingbutes. Interfaces will be searched, too. /// Returns all atsortingbutes. public static T[] GetCustomAtsortingbutes( this Type type, bool inherit ) where T : Atsortingbute { return GetCustomAtsortingbutes( type, typeof( T ), inherit ).Select( arg => (T)arg ).ToArray(); } /// Private helper for searching atsortingbutes. /// The type which is searched for the atsortingbute. /// The type of atsortingbute to search for. /// Specifies whether to search this member's inheritance chain to find the atsortingbute. Interfaces will be searched, too. /// An array that contains all the custom atsortingbutes, or an array with zero elements if no atsortingbutes are defined. private static object[] GetCustomAtsortingbutes( Type type, Type atsortingbuteType, bool inherit ) { if( !inherit ) { return type.GetCustomAtsortingbutes( atsortingbuteType, false ); } var atsortingbuteCollection = new Collection(); var baseType = type; do { baseType.GetCustomAtsortingbutes( atsortingbuteType, true ).Apply( atsortingbuteCollection.Add ); baseType = baseType.BaseType; } while( baseType != null ); foreach( var interfaceType in type.GetInterfaces() ) { GetCustomAtsortingbutes( interfaceType, atsortingbuteType, true ).Apply( atsortingbuteCollection.Add ); } var atsortingbuteArray = new object[atsortingbuteCollection.Count]; atsortingbuteCollection.CopyTo( atsortingbuteArray, 0 ); return atsortingbuteArray; } /// Applies a function to every element of the list. private static void Apply( this IEnumerable enumerable, Action function ) { foreach( var item in enumerable ) { function.Invoke( item ); } } 

Mettre à jour:

Voici une version plus courte proposée par SimonD dans un commentaire:

 private static IEnumerable GetCustomAtsortingbutesIncludingBaseInterfaces(this Type type) { var atsortingbuteType = typeof(T); return type.GetCustomAtsortingbutes(atsortingbuteType, true). Union(type.GetInterfaces(). SelectMany(interfaceType => interfaceType.GetCustomAtsortingbutes(atsortingbuteType, true))). Distinct().Cast(); } 

Un article de Brad Wilson à ce sujet: Atsortingbuts d’interface! = Atsortingbuts de classe

Pour résumer: les classes n’héritent pas des interfaces, elles les implémentent. Cela signifie que les atsortingbuts ne font pas automatiquement partie de l’implémentation.

Si vous devez hériter des atsortingbuts, utilisez une classe de base abstraite plutôt qu’une interface.

Bien qu’une classe C # n’hérite pas des atsortingbuts de ses interfaces, il existe une alternative utile lors de la liaison de modèles dans ASP.NET MVC3.

Si vous déclarez le modèle de la vue comme interface plutôt que comme type concret, la vue et le classeur de modèle appliqueront les atsortingbuts (par exemple, [Required] ou [DisplayName("Foo")] partir de l’interface lors du rendu et de la validation du modèle:

 public interface IModel { [Required] [DisplayName("Foo Bar")] ssortingng FooBar { get; set; } } public class Model : IModel { public ssortingng FooBar { get; set; } } 

Puis dans la vue:

 @* Note use of interface type for the view model *@ @model IModel @* This control will receive the atsortingbutes from the interface *@ @Html.EditorFor(m => m.FooBar) 

C’est plus pour les personnes cherchant à extraire des atsortingbuts de propriétés pouvant exister sur une interface implémentée. Comme ces atsortingbuts ne font pas partie de la classe, cela vous donnera access à ces atsortingbuts. note, j’ai une classe de conteneur simple qui vous donne access à PropertyInfo – car c’est ce dont j’avais besoin pour cela. Hack up comme vous avez besoin. Cela a bien fonctionné pour moi.

 public static class CustomAtsortingbuteExtractorExtensions { ///  /// Extraction of property atsortingbutes as well as atsortingbutes on implemented interfaces. /// This will walk up recursive to collect any interface atsortingbute as well as their parent interfaces. ///  ///  ///  ///  public static List> GetPropertyAtsortingbutesFromType(this Type typeToReflect) where TAtsortingbuteType : Atsortingbute { var list = new List>(); // Loop over the direct property members var properties = typeToReflect.GetProperties(); foreach (var propertyInfo in properties) { // Get the atsortingbutes as well as from the inherited classes (true) var atsortingbutes = propertyInfo.GetCustomAtsortingbutes(true).ToList(); if (!atsortingbutes.Any()) continue; list.AddRange(atsortingbutes.Select(attr => new PropertyAtsortingbuteContainer(attr, propertyInfo))); } // Look at the type interface declarations and extract from that type. var interfaces = typeToReflect.GetInterfaces(); foreach (var @interface in interfaces) { list.AddRange(@interface.GetPropertyAtsortingbutesFromType()); } return list; } ///  /// Simple container for the Property and Atsortingbute used. Handy if you want refrence to the original property. ///  ///  public class PropertyAtsortingbuteContainer { internal PropertyAtsortingbuteContainer(TAtsortingbuteType atsortingbute, PropertyInfo property) { Property = property; Atsortingbute = atsortingbute; } public PropertyInfo Property { get; private set; } public TAtsortingbuteType Atsortingbute { get; private set; } } }