web-dev-qa-db-ja.com

C#で属性を動的に追加できますか?

実行時に属性を追加したり、実行時に属性の値を変更したりすることは可能ですか?

140
Jon Turner

属性は静的メタデータです。アセンブリ、モジュール、型、メンバー、パラメーター、および戻り値は、C#のファーストクラスオブジェクトではありません(たとえば、System.Typeクラスは単に型の反映された表現です)。型の属性のインスタンスを取得し、書き込み可能なプロパティを変更できますが、属性は型に適用されるため、属性には影響しません。

66
Mark Cidade

これは本当にあなたが何を達成しようとしているかに依存します。

System.ComponentModel.TypeDescriptor stuffは、型、プロパティ、およびオブジェクトインスタンスに属性を追加するために使用できますが、これらのプロパティを取得するためにも使用する必要があるという制限があります。これらの属性を使用するコードを作成していて、それらの制限内で生活できる場合は、間違いなく提案します。

私が知る限り、PropertyGridコントロールとVisual Studioデザインサーフェイスは、TypeDescriptorを使用するBCL内の唯一のものです。実際、それは彼らが本当に必要なことの約半分を行う方法です。

67
Alex Lyman

できません。回避策の1つは、実行時に派生クラスを生成して属性を追加することかもしれませんが、これはおそらく少しやり過ぎです。

10
petr k.

違いますが、Reflection.Emitを使用して参照している記事を見つけました。

ここにリンクがあります: http://www.codeproject.com/KB/cs/dotnetattributes.aspx 、可能なアプローチのため議論されています。

10
torial

いいえ、ちがいます。

属性はメタデータであり、コンパイルされたアセンブリにバイナリ形式で格納されます(これは単純な型のみを使用できる理由でもあります)。

4
Thomas Danecker

私はそうは思わない。私が間違っていたとしても、あなたが期待できる最善の方法は、タイプ全体に追加することであり、タイプのインスタンスではありません。

3
Joel Coehoorn

動的に追加できるものが必要な場合、c#属性は役に立ちません。データをxmlに保存する方法を調べます。私は最近、属性を使用して開始したプロジェクトを行いましたが、最終的にはXMLを使用したシリアル化に移行しました。

3
Darren Kopp

なぜ必要なのですか?属性はリフレクションのための追加情報を提供しますが、必要なプロパティが外部からわかっている場合は必要ありません。

メタデータをデータベースまたはリソースファイルに外部から比較的簡単に保存できます。

3
Keith

System.ComponentModel.TypeDescriptorで非常に一生懸命試しましたが、成功しませんでした。それは機能しないという意味ではありませんが、そのためのコードを見たいです。

カウンターパートでは、いくつかの属性値を変更したかった。その目的のためにうまく機能する2つの機能を実行しました。

        // ************************************************************************
        public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName,  string description)
        {
            PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
            var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
            if (att != null)
            {
                var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
                if (fieldDescription != null)
                {
                    fieldDescription.SetValue(att, description);
                }
            }
        }

        // ************************************************************************
        public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
        {
            PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
            var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
            if (att != null)
            {
                var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
                if (fieldDescription != null)
                {
                    fieldDescription.SetValue(att, isReadOnly);
                }
            }
        }
1
Eric Ouellet