Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.ComponentModel.Composition / src / ComponentModel / System / ComponentModel / Composition / ReflectionModel / ExportingMember.cs
1 // -----------------------------------------------------------------------\r
2 // Copyright (c) Microsoft Corporation.  All rights reserved.\r
3 // -----------------------------------------------------------------------\r
4 using System;\r
5 using System.ComponentModel.Composition.Hosting;\r
6 using System.ComponentModel.Composition.Primitives;\r
7 using System.Globalization;\r
8 using System.Reflection;\r
9 using Microsoft.Internal;\r
10 using System.Threading;\r
11 \r
12 namespace System.ComponentModel.Composition.ReflectionModel\r
13 {\r
14     internal class ExportingMember\r
15     {\r
16         private readonly ExportDefinition _definition;\r
17         private readonly ReflectionMember _member;\r
18         private object _cachedValue = null;\r
19         private volatile bool _isValueCached = false;\r
20 \r
21         public ExportingMember(ExportDefinition definition, ReflectionMember member)\r
22         {\r
23             Assumes.NotNull(definition, member);\r
24 \r
25             this._definition = definition;\r
26             this._member = member;\r
27         }\r
28 \r
29         public bool RequiresInstance\r
30         {\r
31             get { return _member.RequiresInstance; }\r
32         }\r
33 \r
34         public ExportDefinition Definition\r
35         {\r
36             get { return _definition; }\r
37         }\r
38 \r
39         public object GetExportedValue(object instance, object @lock)\r
40         {\r
41             this.EnsureReadable();\r
42 \r
43             if (!this._isValueCached)\r
44             {\r
45                 object exportedValue;\r
46                 try\r
47                 {\r
48                     exportedValue = this._member.GetValue(instance);\r
49                 }\r
50                 catch (TargetInvocationException exception)\r
51                 {   // Member threw an exception. Avoid letting this \r
52                     // leak out as a 'raw' unhandled exception, instead,\r
53                     // we'll add some context and rethrow.\r
54 \r
55                     throw new ComposablePartException(\r
56                         CompositionErrorId.ReflectionModel_ExportThrewException,\r
57                         String.Format(CultureInfo.CurrentCulture,\r
58                             Strings.ReflectionModel_ExportThrewException,\r
59                             this._member.GetDisplayName()),\r
60                         Definition.ToElement(),\r
61                         exception.InnerException);\r
62                 }\r
63 \r
64                 lock (@lock)\r
65                 {\r
66                     if (!this._isValueCached)\r
67                     {\r
68                         this._cachedValue = exportedValue;\r
69                         Thread.MemoryBarrier();\r
70 \r
71                         this._isValueCached = true;\r
72                     }\r
73                 }\r
74             }\r
75 \r
76             return this._cachedValue;\r
77         }\r
78 \r
79         private void EnsureReadable()\r
80         {\r
81             if (!this._member.CanRead)\r
82             {   // Property does not have a getter\r
83 \r
84                 throw new ComposablePartException(\r
85                     CompositionErrorId.ReflectionModel_ExportNotReadable,\r
86                     String.Format(CultureInfo.CurrentCulture, \r
87                         Strings.ReflectionModel_ExportNotReadable,\r
88                         this._member.GetDisplayName()),\r
89                     Definition.ToElement());\r
90             }\r
91         }\r
92     }\r
93 }\r