换句话说,如果每个类没有(“必须有”)自定义属性(例如作者和版本),是否可以创建甚至无法编译的程序集(假设未删除检查代码)?

这是我在运行时用于查询的代码:

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 { }

//}

编辑:只是为了证明我选择答案的合理性。我认为 casperOne 提供了问题的正确答案。

然而提出这个问题的原因似乎是 虚弱的. 。也许我应该开始使用一些外部工具,例如:最终生成器或使用 Pex 、 Nunit 或其他单元测试框架创建单元测试来检查此“要求”...

编辑我加了一个小 代码片段 执行检查的答案末尾的控制台程序...请随意发表评论、批评或提出改进建议
我再次意识到这个“要求”应该在“签入”之前作为单元测试的一部分来实现

有帮助吗?

解决方案

没有,这是不可能挂接到组件的汇编和检查它是否存在。

然而你可以挂接到生成过程中,它是由不只是运行编译器更的。您可以创建一个自定义的MSBuild任务(或恶性,如果您正在使用),它通过反射检查装配它建成后,然后构建失败,如果它不具备所需的属性。

当然,你或许应该的还是的代码验证这一点。你所要做的是不是一个适当的运行时检查一个很好的替代品。

其他提示

您可以运行一个生成后的步骤,反映了DLL做你想做什么。

您必须编写加载DLL和类型反映了一个命令行应用程序。然后运行该命令行应用程序的生成后步骤。我在过去做到了这一点。它是不是非常困难的事,假设你明白反射API。

PostSharp 这样做是为了实现面向方面的编程。很酷,实际上。

属性仅运行时间。但是:

这将有可能创造的FxCop(静态分析)的规则,如果没有定义的属性,将失败,并且您的构建/签到过程可以检查该规则并不能恰如其分。

我不知道的任何方式挂接到C#编译过程,但你可以采取不同的方法,并创建上可以加载程序集和反映后生成事件展开了自定义工具。根据什么工具返回整个构建过程将导致成功或失败,那么你可能只返回一个错误与您的工具,使构建失败,同时提供关于失效写入到控制台的更多细节。

对我来说这似乎更像是一个测试问题比汇编问题。也就是说,你问“我怎么知道,我的代码编写正确?”其中,“正确地写入”有(其中包括)的内涵,所有的类都具有特定属性的装饰。我会考虑编写单元测试,验证您的属性包含规则,事实上,紧随其后。你可以有你的构建(和/或签)的进程中运行版本(签入前)后,该组特定的测试作为一个成功的构建(签)的条件。它不会打破编译,因为需要为了完成运行测试,但它会打破建立,可以这么说。

//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命名空间

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top