24

つまり、クラスのそれぞれにカスタム属性 (たとえば、 Author および Version ) がない (「必須」) 場合、コンパイルさえしない (チェック コードが削除されていないと仮定して) アセンブリを作成することは可能でしょうか?

実行時にクエリを実行するために使用したコードは次のとおりです。

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 が質問の正しい答えを提供したと思います。

しかし、質問をする理由は弱いようでした。おそらく、 FinalBuilderなどの外部ツールの使用を開始するか 、 Pex 、 Nunit またはその他の単体テストフレームワークを使用して、この「要件」をチェックする単体テストを作成する必要があります...

EDITチェックを実行する回答の最後にコンソールプログラム の小さなコードスニペットを追加しました...コメント、批判、または改善の提案をお気軽にどうぞ
もう一度、この「要件」をユニットの一部として実装する必要があることに気付きました「チェックイン」直前のテスト

4

7 に答える 7

9

いいえ、アセンブリのコンパイルにフックして存在するかどうかを確認することはできません。

ただし、ビルド プロセスにフックすることはできます。ビルド プロセスは、コンパイラを実行するだけではありません。ビルド後にリフレクションを介してアセンブリをチェックし、必要な属性がない場合はビルドに失敗するカスタム MSBUILD タスク (またはそれを使用している場合は NAnt) を作成できます。

もちろん、コードでもこれを確認する必要があります。あなたがやろうとしていることは、適切な実行時チェックの代わりにはなりません。

于 2009-04-15T19:12:58.023 に答える
4

DLLに反映するビルド後の手順を実行して、必要な処理を実行できます。

DLLをロードし、タイプを反映するコマンドラインアプリを作成する必要があります。次に、そのコマンドラインアプリをビルド後の手順として実行します。私は過去にこれを行いました。リフレクションAPIを理解していれば、それを行うのはそれほど難しくありません。

PostSharpは、アスペクト指向プログラミングを実現するためにこれを行います。実はかなりかっこいい。

于 2009-04-15T19:17:03.850 に答える
1

属性は実行時のみです。でも :

FXCop(静的分析)で属性が定義されていない場合に失敗するルールを作成することが可能であり、ビルド/チェックインプロセスがそのルールをチェックして適切に失敗する可能性があります。

于 2009-04-15T19:13:56.370 に答える
1

C#コンパイルプロセスにフックする方法はわかりませんが、別のアプローチを取り、ビルド後のイベントで起動されるカスタムツールを作成して、アセンブリをロードして反映することができます。ツールが返すものに応じて、ビルドプロセス全体が成功または失敗するため、コンソールへの書き込みの失敗に関する詳細を提供しながら、ツールでエラーを返し、ビルドを失敗させることができます。

于 2009-04-15T19:14:09.393 に答える
1

私には、これはコンパイルの問題というよりもテストの問題のように思えます。つまり、「自分のコードが正しく記述されていることをどのように確認できますか?」ということです。ここで、「正しく書かれている」とは、(とりわけ) すべてのクラスが特定の属性で装飾されていることを意味します。属性の包含ルールが実際に守られていることを確認する単体テストを作成することを検討します。ビルド (および/またはチェックイン) プロセスで、ビルド (チェックイン) が成功する条件として、ビルド後 (チェックイン前) にこの特定の一連のテストを実行することができます。テストを実行するにはコンパイルを完了する必要があるため、コンパイルが中断されることはありませんが、いわばビルドが中断されます。

于 2009-04-15T19:22:56.673 に答える