[reflection] Coop handles icalls in System.Reflection and System.RuntimeTypeHandle...
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Base / Core / Metadata / AttributeTableBuilder.cs
1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4
5 namespace System.Activities.Presentation.Metadata 
6 {
7
8     using System.Activities.Presentation.Internal.Metadata;
9     using System;
10     using System.Collections;
11     using System.Collections.Generic;
12     using System.ComponentModel;
13     using System.Reflection;
14     using System.Windows;
15     using System.Activities.Presentation;
16
17     // <summary>
18     // An attribute table is a read only blob of data.  How
19     // do you create one?  We will have a class called an
20     // Attribute Builder that can be used to create an attribute
21     // table.  Attribute builders have methods you can call to
22     // add metadata.  When you�re finished, you can produce an
23     // attribute table from the builder.  Builder methods also
24     // support callback delegates so the entire process can be
25     // deferred until needed.
26     // </summary>
27     public class AttributeTableBuilder 
28     {
29
30         private MutableAttributeTable _table = new MutableAttributeTable();
31         private bool _cloneOnUse;
32
33         //
34         // Returns an attribute table we can make changes to
35         //
36         private MutableAttributeTable MutableTable 
37         {
38             get {
39                 if (_cloneOnUse) 
40                 {
41                     MutableAttributeTable clone = new MutableAttributeTable();
42                     clone.AddTable(_table);
43                     _table = clone;
44                     _cloneOnUse = false;
45                 }
46
47                 return _table;
48             }
49         }
50
51         // <summary>
52         // Adds a callback that will be invoked when metadata for the
53         // given type is needed.  The callback can add metadata to
54         // to the attribute table on demand, which is much more efficient
55         // than adding metadata up front.
56         // </summary>
57         // <param name="type"></param>
58         // <param name="callback"></param>
59         public void AddCallback(Type type, AttributeCallback callback) 
60         {
61             if (type == null) 
62             {
63                 throw FxTrace.Exception.ArgumentNull("type");
64             }
65             if (callback == null) 
66             {
67                 throw FxTrace.Exception.ArgumentNull("callback");
68             }
69             MutableTable.AddCallback(type, callback);
70         }
71
72         // <summary>
73         // Adds the contents of the provided attributes to this builder.
74         // Conflicts are resolved with a last-in-wins strategy.  When
75         // building a large attribute table it is best to use AddCallback
76         // to defer the work of creating attributes until they are needed.
77         // </summary>
78         // <param name="type">The type to add class-level attributes to.</param>
79         // <param name="attributes">
80         // The new attributes to add.
81         // </param>
82         // <exception cref="ArgumentNullException">if type or attributes is null</exception>
83         public void AddCustomAttributes(Type type, params Attribute[] attributes) {
84             if (type == null) 
85             {
86                 throw FxTrace.Exception.ArgumentNull("type");
87             }
88             if (attributes == null) 
89             {
90                 throw FxTrace.Exception.ArgumentNull("attributes");
91             }
92             MutableTable.AddCustomAttributes(type, attributes);
93         }
94
95         // <summary>
96         // Adds the contents of the provided attributes to this builder.
97         // Conflicts are resolved with a last-in-wins strategy.  When
98         // building a large attribute table it is best to use AddCallback
99         // to defer the work of creating attributes until they are needed.
100         // </summary>
101         // <param name="ownerType">
102         // The type the member lives on.
103         // </param>
104         // <param name="descriptor">An event or property descriptor to add attributes to.</param>
105         // <param name="attributes">
106         // The new attributes to add.
107         // </param>
108         // <exception cref="ArgumentNullException">if descriptor or attributes is null</exception>
109         public void AddCustomAttributes(Type ownerType, MemberDescriptor descriptor, params Attribute[] attributes) {
110             if (ownerType == null) 
111             {
112                 throw FxTrace.Exception.ArgumentNull("ownerType");
113             }
114             if (descriptor == null) 
115             {
116                 throw FxTrace.Exception.ArgumentNull("descriptor");
117             }
118             if (attributes == null) 
119             {
120                 throw FxTrace.Exception.ArgumentNull("attributes");
121             }
122             MutableTable.AddCustomAttributes(ownerType, descriptor, attributes);
123         }
124
125         // <summary>
126         // Adds the contents of the provided attributes to this builder.
127         // Conflicts are resolved with a last-in-wins strategy.  When
128         // building a large attribute table it is best to use AddCallback
129         // to defer the work of creating attributes until they are needed.
130         // </summary>
131         // <param name="ownerType">
132         // The type the member lives on.
133         // </param>
134         // <param name="member">An event or property info to add attributes to.</param>
135         // <param name="attributes">
136         // The new attributes to add.
137         // </param>
138         // <exception cref="ArgumentNullException">if member or attributes is null</exception>
139         public void AddCustomAttributes(Type ownerType, MemberInfo member, params Attribute[] attributes) {
140             if (ownerType == null) 
141             {
142                 throw FxTrace.Exception.ArgumentNull("ownerType");
143             }
144             if (member == null) 
145             {
146                 throw FxTrace.Exception.ArgumentNull("member");
147             }
148             if (attributes == null) 
149             {
150                 throw FxTrace.Exception.ArgumentNull("attributes");
151             }
152             MutableTable.AddCustomAttributes(ownerType, member, attributes);
153         }
154
155         // <summary>
156         // Adds attributes to the member with the given name.  The member can be a property
157         // or an event.  The member is evaluated on demand when the user queries
158         // attributes on a given property or event.
159         // </summary>
160         // <param name="ownerType">
161         // The type the member lives on.
162         // </param>
163         // <param name="memberName">
164         // The member to add attributes for.  Only property and event members are supported;
165         // all others will be ignored.
166         // </param>
167         // <param name="attributes">
168         // The new attributes to add.
169         // </param>
170         public void AddCustomAttributes(Type ownerType, string memberName, params Attribute[] attributes) {
171             if (ownerType == null) 
172             {
173                 throw FxTrace.Exception.ArgumentNull("ownerType");
174             }
175             if (memberName == null) 
176             {
177                 throw FxTrace.Exception.ArgumentNull("memberName");
178             }
179             MutableTable.AddCustomAttributes(ownerType, memberName, attributes);
180         }
181
182         // <summary>
183         // Adds the contents of the provided attributes to this builder.
184         // Conflicts are resolved with a last-in-wins strategy.  When
185         // building a large attribute table it is best to use AddCallback
186         // to defer the work of creating attributes until they are needed.
187         // </summary>
188         // <param name="ownerType">
189         // The type that owns the dependency property.
190         // </param>
191         // <param name="dp">A dependency property to add attributes to.</param>
192         // <param name="attributes">
193         // The new attributes to add.
194         // </param>
195         // <exception cref="ArgumentNullException">if dp, ownerType or attributes is null</exception>
196         public void AddCustomAttributes(Type ownerType, DependencyProperty dp, params Attribute[] attributes) {
197             if (ownerType == null) 
198             {
199                 throw FxTrace.Exception.ArgumentNull("ownerType");
200             }
201             if (dp == null) 
202             {
203                 throw FxTrace.Exception.ArgumentNull("dp");
204             }
205             if (attributes == null) 
206             {
207                 throw FxTrace.Exception.ArgumentNull("attributes");
208             }
209             MutableTable.AddCustomAttributes(ownerType, dp, attributes);
210         }
211
212         // <summary>
213         // Adds the contents of the provided attribute table to
214         // this builder.  Conflicts are resolved with a last-in-wins
215         // strategy.
216         // </summary>
217         // <param name="table">An existing attribute table.</param>
218         // <exception cref="ArgumentNullException">if table is null</exception>
219         public void AddTable(AttributeTable table) 
220         {
221             if (table == null) 
222             {
223                 throw FxTrace.Exception.ArgumentNull("table");
224             }
225             MutableTable.AddTable(table.MutableTable);
226         }
227
228         // <summary>
229         // Creates an attribute table that contains all of the attribute
230         // definitions provided through AddAttribute calls.  The table is
231         // a snapshot of the current state of the attribute builder; any
232         // subsequent AddAttribute calls are not included in the table.
233         //
234         // If callback methods were used to declare attributes, those methods
235         // will not be evaluated during CreateTable.  Instead, the table will
236         // contain those callbacks and will evaluate them as needed.
237         // </summary>
238         // <returns>
239         // An attribute table that can be passed to the metadata store.
240         // </returns>
241         public AttributeTable CreateTable() 
242         {
243             _cloneOnUse = true;
244             return new AttributeTable(_table);
245         }
246
247         // <summary>
248         // This method can be used to verify that the attribute table
249         // that is being built contains valid attribute information.
250         // Some overrides of AddCustomAttributes cannot validate that
251         // values passed to their prameters represent valid members on
252         // classes.  Therefore, incorrect information passed to
253         // AddCustomAttributes may go undetected.  ValidateTable will
254         // run through the contents of the AttributeTableBuilder and
255         // verify that all custom attribute information matches up with
256         // physical members.  Note:  calling this method can be very
257         // costly so you should only do it when validation is absolutely
258         // needed.
259         // </summary>
260         // <exception cref="AttributeTableValidationException">if the state of the table is invalid.</exception>
261         public void ValidateTable() 
262         {
263             MutableTable.ValidateTable();
264         }
265     }
266 }