property net custom attribute attrib asp c# custom-attributes

net - ¿Es posible consultar atributos personalizados en C#durante el tiempo de compilación(no en tiempo de ejecución)?



custom property c# (6)

En otras palabras, ¿podría ser posible crear un ensamblaje, que ni siquiera se compile (suponiendo que el código de verificación no se elimine) si cada una de las Clases no tiene ("debe tener") atributos personalizados (por ejemplo, Autor y Versión)?

Aquí está el código que he usado para consultar durante el tiempo de ejecución:

using System; using System.Reflection; using System.Collections.Generic; namespace ForceMetaAttributes { [System.AttributeUsage ( System.AttributeTargets.Method, AllowMultiple = true )] class TodoAttribute : System.Attribute { public TodoAttribute ( string message ) { Message = message; } public readonly string Message; } [System.AttributeUsage ( System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple = true )] public class AttributeClass : System.Attribute { public string Description { get; set; } public string MusHaveVersion { get; set; } public AttributeClass ( string description, string mustHaveVersion ) { Description = description; MusHaveVersion = mustHaveVersion ; } } //eof class [AttributeClass("AuthorName" , "1.0.0")] class ClassToDescribe { [Todo ( " A todo message " )] static void Method () { } } //eof class //how to get this one to fail on compile class AnotherClassToDescribe { } //eof class class QueryApp { public static void Main() { Type type = typeof(ClassToDescribe); AttributeClass objAttributeClass; //Querying Class Attributes foreach (Attribute attr in type.GetCustomAttributes(true)) { objAttributeClass = attr as AttributeClass; if (null != objAttributeClass) { Console.WriteLine("Description of AnyClass:/n{0}", objAttributeClass.Description); } } //Querying Class-Method Attributes foreach(MethodInfo method in type.GetMethods()) { foreach (Attribute attr in method.GetCustomAttributes(true)) { objAttributeClass = attr as AttributeClass; if (null != objAttributeClass) { Console.WriteLine("Description of {0}:/n{1}", method.Name, objAttributeClass.Description); } } } //Querying Class-Field (only public) Attributes foreach(FieldInfo field in type.GetFields()) { foreach (Attribute attr in field.GetCustomAttributes(true)) { objAttributeClass= attr as AttributeClass; if (null != objAttributeClass) { Console.WriteLine("Description of {0}:/n{1}", field.Name,objAttributeClass.Description); } } } Console.WriteLine ( "hit Enter to exit " ); Console.ReadLine (); } //eof Main } //eof class } //eof namespace //uncomment to check whether it works with external namespace //namespace TestNamespace { // class Class1 { } // class Class2 { } //}

Edición: Sólo para justificar mi elección para la respuesta. Creo que CasperOne proporcionó la respuesta correcta de la pregunta.

Sin embargo, las razones para hacer la pregunta parecían ser weak . Probablemente debería comenzar a usar alguna herramienta externa como: FinalBuilder o crear pruebas unitarias para verificar este "requisito", usando Pex, Nunit u otros marcos de pruebas unitarias ...

EDITAR Agregué un pequeño fragmento de código de un programa de consola al final de las respuestas que realiza la verificación ... siéntase libre de comentar, criticar o sugerir mejoras
Una vez más, me di cuenta de que este "requisito" debería implementarse como parte de la prueba de la unidad justo antes del "check in"


Los atributos son tiempo de ejecución solamente. Sin embargo :

Sería posible crear una regla en FXCop (análisis estático) que fallará si el atributo no está definido, y su proceso de creación / registro podría verificar esa regla y fallar adecuadamente.


No conozco ninguna forma de engancharse al proceso de compilación de C #, pero puede adoptar un enfoque diferente y crear una herramienta personalizada lanzada en el evento posterior a la construcción que podría cargar su ensamblaje y reflexionar sobre eso. Dependiendo de lo que devuelva la herramienta, todo el proceso de compilación resultará en un éxito o una falla, por lo que puede devolver un error con su herramienta y hacer que la compilación falle, al tiempo que proporciona más detalles sobre la escritura de fallas en la consola.


No, no es posible enganchar en la compilación del ensamblaje y verificar si existe.

Sin embargo , puede conectarse al proceso de compilación, que se compone de algo más que ejecutar el compilador. Podría crear una tarea MSBUILD personalizada (o NAnt, si está usando eso) que verifica el ensamblaje a través de la reflexión después de que se construye y luego falla la compilación si no tiene los atributos requeridos.

Por supuesto, probablemente debería verificar esto también en el código. Lo que está tratando de hacer no es un buen sustituto para un control de tiempo de ejecución adecuado.


Para mí, esto parece más un problema de prueba que un problema de compilación. Es decir, estás preguntando "¿cómo sé que mi código está escrito correctamente?" donde "escrito correctamente" tiene (entre otras cosas) la connotación de que todas las clases están decoradas con un atributo particular. Consideraría escribir pruebas unitarias que verifiquen que, de hecho, se siguen las reglas de inclusión de atributos. Podría hacer que su proceso de compilación (y / o registro) ejecute este conjunto particular de pruebas después de la compilación (antes del registro) como condición para una compilación exitosa (registro). No romperá la compilación, ya que debe completarse para que se ejecuten las pruebas, pero romperá la compilación, por así decirlo.


Puede ejecutar un paso posterior a la compilación que se refleje en la DLL para hacer lo que desea.

Tendrá que escribir una aplicación de línea de comandos que cargue la DLL y reflexione sobre los tipos. A continuación, ejecuta esa aplicación de línea de comandos como un paso posterior a la compilación. He hecho esto en el pasado. No es terriblemente difícil hacerlo, suponiendo que entiendas la API de reflexión.

PostSharp hace esto para lograr una programación orientada a aspectos. Bastante bien, en realidad.


//PLEASE COMMENT IF YOU FIND BUGS OR SUGGEST IMPROVEMENTS using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace MustHaveAttributes { [AttributeClass ( "Yordan Georgiev", "1.0.0" )] class Program { static void Main ( string [] args ) { bool flagFoundCustomAttrOfTypeAttributeClass = false; Console.WriteLine ( " START " ); // what is in the assembly Assembly a = Assembly.Load ( "MustHaveAttributes" ); Type[] types = a.GetTypes (); foreach (Type t in types) { object[] arrCustomAttributes = t.GetCustomAttributes ( true ); if (arrCustomAttributes == null || arrCustomAttributes.GetLength ( 0 ) == 0) { //DO NOT CHECK IN ExitProgram ( t, "Found class without CustomAttributes" ); } foreach (object objCustomAttribute in arrCustomAttributes) { Console.WriteLine ( "CustomAttribute for type is {0}", t ); if (objCustomAttribute is AttributeClass) flagFoundCustomAttrOfTypeAttributeClass = true; } if (flagFoundCustomAttrOfTypeAttributeClass == false) { //DO NOT CHECK IN ExitProgram ( t, "Did not found custom attribute of type AttributeClass" ); } Console.WriteLine ( "Type is {0}", t ); } Console.WriteLine ("{0} types found", types.Length ); //NOW REQUIREMENTS IS PASSED CHECK IN Console.WriteLine ( " HIT A KEY TO EXIT " ); Console.ReadLine (); Console.WriteLine ( " END " ); } static void ExitProgram ( Type t, string strExitMsg ) { Console.WriteLine ( strExitMsg ); Console.WriteLine ( "Type is {0}", t ); Console.WriteLine ( " HIT A KEY TO EXIT " ); Console.ReadLine (); System.Environment.Exit ( 1 ); } } //eof Program //This will fail even to compile since the constructor requires two params //[AttributeClass("OnlyAuthor")] //class ClassOne //{ //} //eof class ////this will not check in since this class does not have required custom ////attribute //class ClassWithoutAttrbute //{ } [AttributeClass("another author name " , "another version")] class ClassTwo { } //eof class [System.AttributeUsage ( System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple = true )] public class AttributeClass : System.Attribute { public string MustHaveDescription { get; set; } public string MusHaveVersion { get; set; } public AttributeClass ( string mustHaveDescription, string mustHaveVersion ) { MustHaveDescription = mustHaveDescription; MusHaveVersion = mustHaveVersion; } } //eof class

} // eof espacio de nombres