1
// -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
5 using System
.Collections
;
6 using System
.ComponentModel
.Composition
.Hosting
;
7 using System
.ComponentModel
.Composition
.Primitives
;
8 using System
.Collections
.Generic
;
9 using System
.Diagnostics
.CodeAnalysis
;
10 using System
.Globalization
;
11 using System
.Reflection
;
12 using Microsoft
.Internal
;
13 using Microsoft
.Internal
.Collections
;
15 namespace System
.ComponentModel
.Composition
.ReflectionModel
17 internal class ImportingMember
: ImportingItem
19 private readonly ReflectionWritableMember _member
;
21 public ImportingMember(ContractBasedImportDefinition definition
, ReflectionWritableMember member
, ImportType importType
)
22 : base(definition
, importType
)
24 Assumes
.NotNull(definition
, member
);
26 this._member
= member
;
29 public void SetExportedValue(object instance
, object value)
31 if (RequiresCollectionNormalization())
33 this.SetCollectionMemberValue(instance
, (IEnumerable
)value);
37 this.SetSingleMemberValue(instance
, value);
41 private bool RequiresCollectionNormalization()
43 if (this.Definition
.Cardinality
!= ImportCardinality
.ZeroOrMore
)
44 { // If we're not looking at a collection import, then don't
45 // 'normalize' the collection.
50 if (this._member
.CanWrite
&& this.ImportType
.IsAssignableCollectionType
)
51 { // If we can simply replace the entire value of the property/field, then
52 // we don't need to 'normalize' the collection.
60 private void SetSingleMemberValue(object instance
, object value)
66 this._member
.SetValue(instance
, value);
68 catch (TargetInvocationException exception
)
69 { // Member threw an exception. Avoid letting this
70 // leak out as a 'raw' unhandled exception, instead,
71 // we'll add some context and rethrow.
73 throw new ComposablePartException(
74 CompositionErrorId
.ReflectionModel_ImportThrewException
,
75 String
.Format(CultureInfo
.CurrentCulture
,
76 Strings
.ReflectionModel_ImportThrewException
,
77 this._member
.GetDisplayName()),
78 Definition
.ToElement(),
79 exception
.InnerException
);
83 private void EnsureWritable()
85 if (!this._member
.CanWrite
)
86 { // Property does not have a setter, or
87 // field is marked as read-only.
89 throw new ComposablePartException(
90 CompositionErrorId
.ReflectionModel_ImportNotWritable
,
91 String
.Format(CultureInfo
.CurrentCulture
,
92 Strings
.ReflectionModel_ImportNotWritable
,
93 this._member
.GetDisplayName()),
94 Definition
.ToElement());
98 private void SetCollectionMemberValue(object instance
, IEnumerable values
)
100 Assumes
.NotNull(values
);
102 ICollection
<object> collection
= null;
103 Type itemType
= CollectionServices
.GetCollectionElementType(this.ImportType
.ActualType
);
104 if (itemType
!= null)
106 collection
= GetNormalizedCollection(itemType
, instance
);
109 EnsureCollectionIsWritable(collection
);
110 PopulateCollection(collection
, values
);
113 private ICollection
<object> GetNormalizedCollection(Type itemType
, object instance
)
115 Assumes
.NotNull(itemType
);
117 object collectionObject
= null;
119 if (this._member
.CanRead
)
123 collectionObject
= this._member
.GetValue(instance
);
125 catch (TargetInvocationException exception
)
127 throw new ComposablePartException(
128 CompositionErrorId
.ReflectionModel_ImportCollectionGetThrewException
,
129 String
.Format(CultureInfo
.CurrentCulture
,
130 Strings
.ReflectionModel_ImportCollectionGetThrewException
,
131 this._member
.GetDisplayName()),
132 this.Definition
.ToElement(),
133 exception
.InnerException
);
137 if (collectionObject
== null)
139 ConstructorInfo constructor
= this.ImportType
.ActualType
.GetConstructor(Type
.EmptyTypes
);
141 // If it contains a default public constructor create a new instance.
142 if (constructor
!= null)
146 collectionObject
= constructor
.SafeInvoke();
148 catch (TargetInvocationException exception
)
150 throw new ComposablePartException(
151 CompositionErrorId
.ReflectionModel_ImportCollectionConstructionThrewException
,
152 String
.Format(CultureInfo
.CurrentCulture
,
153 Strings
.ReflectionModel_ImportCollectionConstructionThrewException
,
154 this._member
.GetDisplayName(),
155 this.ImportType
.ActualType
.FullName
),
156 this.Definition
.ToElement(),
157 exception
.InnerException
);
160 SetSingleMemberValue(instance
, collectionObject
);
164 if (collectionObject
== null)
166 throw new ComposablePartException(
167 CompositionErrorId
.ReflectionModel_ImportCollectionNull
,
168 String
.Format(CultureInfo
.CurrentCulture
,
169 Strings
.ReflectionModel_ImportCollectionNull
,
170 this._member
.GetDisplayName()),
171 this.Definition
.ToElement());
174 return CollectionServices
.GetCollectionWrapper(itemType
, collectionObject
);
177 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
178 private void EnsureCollectionIsWritable(ICollection
<object> collection
)
180 bool isReadOnly
= true;
184 if (collection
!= null)
186 isReadOnly
= collection
.IsReadOnly
;
189 catch (Exception exception
)
191 throw new ComposablePartException(
192 CompositionErrorId
.ReflectionModel_ImportCollectionIsReadOnlyThrewException
,
193 String
.Format(CultureInfo
.CurrentCulture
,
194 Strings
.ReflectionModel_ImportCollectionIsReadOnlyThrewException
,
195 this._member
.GetDisplayName(),
196 collection
.GetType().FullName
),
197 this.Definition
.ToElement(),
203 throw new ComposablePartException(
204 CompositionErrorId
.ReflectionModel_ImportCollectionNotWritable
,
205 String
.Format(CultureInfo
.CurrentCulture
,
206 Strings
.ReflectionModel_ImportCollectionNotWritable
,
207 this._member
.GetDisplayName()),
208 this.Definition
.ToElement());
212 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
213 private void PopulateCollection(ICollection
<object> collection
, IEnumerable values
)
215 Assumes
.NotNull(collection
, values
);
221 catch (Exception exception
)
223 throw new ComposablePartException(
224 CompositionErrorId
.ReflectionModel_ImportCollectionClearThrewException
,
225 String
.Format(CultureInfo
.CurrentCulture
,
226 Strings
.ReflectionModel_ImportCollectionClearThrewException
,
227 this._member
.GetDisplayName(),
228 collection
.GetType().FullName
),
229 this.Definition
.ToElement(),
233 foreach (object value in values
)
237 collection
.Add(value);
239 catch (Exception exception
)
241 throw new ComposablePartException(
242 CompositionErrorId
.ReflectionModel_ImportCollectionAddThrewException
,
243 String
.Format(CultureInfo
.CurrentCulture
,
244 Strings
.ReflectionModel_ImportCollectionAddThrewException
,
245 this._member
.GetDisplayName(),
246 collection
.GetType().FullName
),
247 this.Definition
.ToElement(),