Is it possible to query custom Attributes in C# during compile time ( not run-time )

主宰稳场 提交于 2019-11-30 04:54:59

No, it is not possible to hook into the compilation of the assembly and check if it exists.

However you can hook into the build process, which is made up of more than just running the compiler. You could create a custom MSBUILD task (or NAnt, if you are using that) which checks the assembly through reflection after it is built and then fail the build if it doesn't have the required attributes.

Of course, you should probably still verify this in code as well. What you are trying to do is not a good substitute for a proper runtime check.

You can run a post-build step that reflects on the DLL to do what you want.

You will have to write a command-line app that loads the DLL and reflects on the types. You then run that command-line app as a post-build step. I have done this in the past. It is not terribly difficult to do, assuming you understand the reflection API.

PostSharp does this to achieve aspect oriented programming. Pretty cool, actually.

Attributes are run time only. However :

It would be possible to create a rule in FXCop (static analysis) that will fail if the attribute is not defined, and your build/checkin process could check that rule and fail appropriately.

I'm not aware of any way to hook into the C# compilation process, but you may take a different approach and create a custom tool launched on the post build event which could load your assembly and reflects on that. Depending on what the tool returns the whole build process will result in a success or a failure, so you may just return an error with your tool and make the build fail, while providing more details about the failure writing to console.

To me this seems more like a testing problem than a compilation problem. That is, you're asking "how do I know that my code is written correctly?" where "written correctly" has (among other things) the connotation that all classes are decorated with a particular attribute. I would consider writing unit tests that verify that your attribute inclusion rules are, in fact, followed. You could have your build (and/or checkin) process run this particular set of tests after the build (before the checkin) as a condition of a successful build (checkin). It won't break the compile, since that needs to complete in order for the tests to run, but it will break the build, so to speak.

YordanGeorgiev
//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 namespace

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!