update MEF to preview 9
[mcs.git] / class / System.ComponentModel.Composition / src / ComponentModel / System / ComponentModel / Composition / ReflectionModel / ImportingMember.cs
blob6e5cffe183a045ffe541249f5a1bf4bb913ef81f
1 // -----------------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // -----------------------------------------------------------------------
4 using System;
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);
35 else
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.
47 return false;
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.
54 return false;
57 return true;
60 private void SetSingleMemberValue(object instance, object value)
62 EnsureWritable();
64 try
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(),
198 exception);
201 if (isReadOnly)
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);
219 collection.Clear();
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(),
230 exception);
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(),
248 exception);