PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Xaml/System.Xaml/XamlObjectWriter.cs

https://bitbucket.org/danipen/mono
C# | 626 lines | 475 code | 79 blank | 72 comment | 157 complexity | 65c12a16db7c5a37d5985b90ceede0e4 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // Copyright (C) 2010 Novell Inc. http://novell.com
  3. // Copyright (C) 2012 Xamarin Inc. http://xamarin.com
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining
  6. // a copy of this software and associated documentation files (the
  7. // "Software"), to deal in the Software without restriction, including
  8. // without limitation the rights to use, copy, modify, merge, publish,
  9. // distribute, sublicense, and/or sell copies of the Software, and to
  10. // permit persons to whom the Software is furnished to do so, subject to
  11. // the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be
  14. // included in all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  17. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  19. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  20. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  21. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  22. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. //
  24. using System;
  25. using System.Collections;
  26. using System.Collections.Generic;
  27. using System.ComponentModel;
  28. using System.Globalization;
  29. using System.Linq;
  30. using System.Reflection;
  31. using System.Windows.Markup;
  32. using System.Xaml;
  33. using System.Xaml.Schema;
  34. using System.Xml;
  35. using System.Xml.Serialization;
  36. // To use this under .NET, compile sources as:
  37. //
  38. // dmcs -d:DOTNET -r:System.Xaml -debug System.Xaml/XamlObjectWriter.cs System.Xaml/XamlWriterInternalBase.cs System.Xaml/TypeExtensionMethods.cs System.Xaml/XamlWriterStateManager.cs System.Xaml/XamlNameResolver.cs System.Xaml/PrefixLookup.cs System.Xaml/ValueSerializerContext.cs ../../build/common/MonoTODOAttribute.cs Test/System.Xaml/TestedTypes.cs
  39. /*
  40. State transition:
  41. * StartObject or GetObject
  42. These start a new object instance, either by creating new or getting
  43. from parent.
  44. * Value
  45. This either becomes an entire property value, or an item of current
  46. collection, or a key or a value item of current dictionary, or an
  47. entire object if it is either Initialization.
  48. * EndObject
  49. Almost the same as Value. Though the it is likely already instantiated.
  50. * StartMember
  51. Indicates a new property as current.
  52. * EndMember
  53. It accompanies a property value (might be lacking), or ends a
  54. collection (including those for PositionalParameters), or ends a key
  55. property of a dictionary element (if it is Key), or ends an entire
  56. value of current object if it is Initialization.
  57. */
  58. #if DOTNET
  59. namespace Mono.Xaml
  60. #else
  61. namespace System.Xaml
  62. #endif
  63. {
  64. public class XamlObjectWriter : XamlWriter, IXamlLineInfoConsumer
  65. {
  66. public XamlObjectWriter (XamlSchemaContext schemaContext)
  67. : this (schemaContext, null)
  68. {
  69. }
  70. public XamlObjectWriter (XamlSchemaContext schemaContext, XamlObjectWriterSettings settings)
  71. {
  72. if (schemaContext == null)
  73. throw new ArgumentNullException ("schemaContext");
  74. this.sctx = schemaContext;
  75. this.settings = settings ?? new XamlObjectWriterSettings ();
  76. var manager = new XamlWriterStateManager<XamlObjectWriterException, XamlObjectWriterException> (false);
  77. intl = new XamlObjectWriterInternal (this, sctx, manager);
  78. }
  79. XamlSchemaContext sctx;
  80. XamlObjectWriterSettings settings;
  81. XamlObjectWriterInternal intl;
  82. //int line, column;
  83. bool lineinfo_was_given;
  84. internal XamlObjectWriterSettings Settings {
  85. get { return settings; }
  86. }
  87. public virtual object Result {
  88. get { return intl.Result; }
  89. }
  90. public INameScope RootNameScope {
  91. get { return intl.NameScope; }
  92. }
  93. public override XamlSchemaContext SchemaContext {
  94. get { return sctx; }
  95. }
  96. public bool ShouldProvideLineInfo {
  97. get { return lineinfo_was_given; }
  98. }
  99. public void SetLineInfo (int lineNumber, int linePosition)
  100. {
  101. // line = lineNumber;
  102. // column = linePosition;
  103. lineinfo_was_given = true;
  104. }
  105. public void Clear ()
  106. {
  107. throw new NotImplementedException ();
  108. }
  109. protected override void Dispose (bool disposing)
  110. {
  111. if (!disposing)
  112. return;
  113. intl.CloseAll ();
  114. }
  115. protected internal virtual void OnAfterBeginInit (object value)
  116. {
  117. if (settings.AfterBeginInitHandler != null)
  118. settings.AfterBeginInitHandler (this, new XamlObjectEventArgs (value));
  119. }
  120. protected internal virtual void OnAfterEndInit (object value)
  121. {
  122. if (settings.AfterEndInitHandler != null)
  123. settings.AfterEndInitHandler (this, new XamlObjectEventArgs (value));
  124. }
  125. protected internal virtual void OnAfterProperties (object value)
  126. {
  127. if (settings.AfterPropertiesHandler != null)
  128. settings.AfterPropertiesHandler (this, new XamlObjectEventArgs (value));
  129. }
  130. protected internal virtual void OnBeforeProperties (object value)
  131. {
  132. if (settings.BeforePropertiesHandler != null)
  133. settings.BeforePropertiesHandler (this, new XamlObjectEventArgs (value));
  134. }
  135. protected internal virtual bool OnSetValue (object eventSender, XamlMember member, object value)
  136. {
  137. if (settings.XamlSetValueHandler != null) {
  138. var args = new XamlSetValueEventArgs (member, value);
  139. settings.XamlSetValueHandler (eventSender, args);
  140. return args.Handled;
  141. }
  142. return false;
  143. }
  144. public override void WriteGetObject ()
  145. {
  146. intl.WriteGetObject ();
  147. }
  148. public override void WriteNamespace (NamespaceDeclaration namespaceDeclaration)
  149. {
  150. intl.WriteNamespace (namespaceDeclaration);
  151. }
  152. public override void WriteStartObject (XamlType xamlType)
  153. {
  154. intl.WriteStartObject (xamlType);
  155. }
  156. public override void WriteValue (object value)
  157. {
  158. intl.WriteValue (value);
  159. }
  160. public override void WriteStartMember (XamlMember property)
  161. {
  162. intl.WriteStartMember (property);
  163. }
  164. public override void WriteEndObject ()
  165. {
  166. intl.WriteEndObject ();
  167. }
  168. public override void WriteEndMember ()
  169. {
  170. intl.WriteEndMember ();
  171. }
  172. }
  173. // specific implementation
  174. class XamlObjectWriterInternal : XamlWriterInternalBase
  175. {
  176. const string Xmlns2000Namespace = "http://www.w3.org/2000/xmlns/";
  177. public XamlObjectWriterInternal (XamlObjectWriter source, XamlSchemaContext schemaContext, XamlWriterStateManager manager)
  178. : base (schemaContext, manager)
  179. {
  180. this.source = source;
  181. this.sctx = schemaContext;
  182. var ext = source.Settings.ExternalNameScope;
  183. name_scope = ext != null && source.Settings.RegisterNamesOnExternalNamescope ? ext : new NameScope (ext);
  184. }
  185. XamlObjectWriter source;
  186. XamlSchemaContext sctx;
  187. INameScope name_scope;
  188. List<NameFixupRequired> pending_name_references = new List<NameFixupRequired> ();
  189. AmbientProvider ambient_provider = new AmbientProvider ();
  190. public INameScope NameScope {
  191. get { return name_scope; }
  192. }
  193. public object Result { get; set; }
  194. protected override void OnWriteStartObject ()
  195. {
  196. var state = object_states.Pop ();
  197. if (object_states.Count > 0) {
  198. var pstate = object_states.Peek ();
  199. if (CurrentMemberState.Value != null)
  200. throw new XamlDuplicateMemberException (String.Format ("Member '{0}' is already written to current type '{1}'", CurrentMember, pstate.Type));
  201. } else {
  202. var obj = source.Settings.RootObjectInstance;
  203. if (obj != null) {
  204. if (state.Type.UnderlyingType != null && !state.Type.UnderlyingType.IsAssignableFrom (obj.GetType ()))
  205. throw new XamlObjectWriterException (String.Format ("RootObjectInstance type '{0}' is not assignable to '{1}'", obj.GetType (), state.Type));
  206. state.Value = obj;
  207. state.IsInstantiated = true;
  208. }
  209. root_state = state;
  210. }
  211. object_states.Push (state);
  212. if (!state.Type.IsContentValue (service_provider))
  213. InitializeObjectIfRequired (true);
  214. state.IsXamlWriterCreated = true;
  215. source.OnBeforeProperties (state.Value);
  216. }
  217. protected override void OnWriteGetObject ()
  218. {
  219. var state = object_states.Pop ();
  220. var xm = CurrentMember;
  221. var instance = xm.Invoker.GetValue (object_states.Peek ().Value);
  222. if (instance == null)
  223. throw new XamlObjectWriterException (String.Format ("The value for '{0}' property is null", xm.Name));
  224. state.Value = instance;
  225. state.IsInstantiated = true;
  226. object_states.Push (state);
  227. }
  228. protected override void OnWriteEndObject ()
  229. {
  230. InitializeObjectIfRequired (false); // this is required for such case that there was no StartMember call.
  231. var state = object_states.Pop ();
  232. var obj = state.Value;
  233. if (obj is MarkupExtension) {
  234. try {
  235. obj = ((MarkupExtension) obj).ProvideValue (service_provider);
  236. } catch (XamlObjectWriterException) {
  237. throw;
  238. } catch (Exception ex) {
  239. throw new XamlObjectWriterException ("An error occured on getting provided value", ex);
  240. }
  241. }
  242. // call this (possibly) before the object is added to parent collection. (bug #3003 also expects this)
  243. if (state.IsXamlWriterCreated)
  244. source.OnAfterProperties (obj);
  245. var nfr = obj as NameFixupRequired;
  246. if (nfr != null && object_states.Count > 0) { // IF the root object to be written is x:Reference, then the Result property will become the NameFixupRequired. That's what .NET also does.
  247. // actually .NET seems to seek "parent" object in its own IXamlNameResolver implementation.
  248. var pstate = object_states.Peek ();
  249. nfr.ParentType = pstate.Type;
  250. nfr.ParentMember = CurrentMember; // Note that it is a member of the pstate.
  251. nfr.ParentValue = pstate.Value;
  252. pending_name_references.Add ((NameFixupRequired) obj);
  253. }
  254. else
  255. StoreAppropriatelyTypedValue (obj, state.KeyValue);
  256. if (state.Type.IsAmbient)
  257. ambient_provider.Pop ();
  258. else
  259. HandleEndInit (obj);
  260. object_states.Push (state);
  261. if (object_states.Count == 1) {
  262. Result = obj;
  263. ResolvePendingReferences ();
  264. }
  265. }
  266. Stack<object> escaped_objects = new Stack<object> ();
  267. protected override void OnWriteStartMember (XamlMember property)
  268. {
  269. if (property == XamlLanguage.PositionalParameters ||
  270. property == XamlLanguage.Arguments) {
  271. var state = object_states.Peek ();
  272. escaped_objects.Push (state.Value);
  273. state.Value = new List<object> ();
  274. }
  275. // FIXME: this condition needs to be examined. What is known to be prevented are: PositionalParameters, Initialization and Base (the last one sort of indicates there's a lot more).
  276. else if (!(property is XamlDirective))
  277. InitializeObjectIfRequired (false);
  278. }
  279. static readonly BindingFlags static_flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
  280. protected override void OnWriteEndMember ()
  281. {
  282. var xm = CurrentMember;
  283. var state = object_states.Peek ();
  284. if (xm == XamlLanguage.PositionalParameters) {
  285. var l = (List<object>) state.Value;
  286. state.Value = escaped_objects.Pop ();
  287. state.IsInstantiated = true;
  288. PopulateObject (true, l);
  289. return;
  290. } else if (xm == XamlLanguage.Arguments) {
  291. if (state.FactoryMethod != null) {
  292. var contents = (List<object>) state.Value;
  293. var mi = state.Type.UnderlyingType.GetMethods (static_flags).FirstOrDefault (mii => mii.Name == state.FactoryMethod && mii.GetParameters ().Length == contents.Count);
  294. if (mi == null)
  295. throw new XamlObjectWriterException (String.Format ("Specified static factory method '{0}' for type '{1}' was not found", state.FactoryMethod, state.Type));
  296. state.Value = mi.Invoke (null, contents.ToArray ());
  297. }
  298. else
  299. PopulateObject (false, (List<object>) state.Value);
  300. state.IsInstantiated = true;
  301. escaped_objects.Pop ();
  302. } else if (xm == XamlLanguage.Initialization) {
  303. // ... and no need to do anything. The object value to pop *is* the return value.
  304. } else if (xm == XamlLanguage.Name || xm == state.Type.GetAliasedProperty (XamlLanguage.Name)) {
  305. string name = (string) CurrentMemberState.Value;
  306. name_scope.RegisterName (name, state.Value);
  307. } else {
  308. if (xm.IsEvent)
  309. SetEvent (xm, (string) CurrentMemberState.Value);
  310. else if (!xm.IsReadOnly) // exclude read-only object such as collection item.
  311. SetValue (xm, CurrentMemberState.Value);
  312. }
  313. }
  314. void SetEvent (XamlMember member, string value)
  315. {
  316. if (member.UnderlyingMember == null)
  317. throw new XamlObjectWriterException (String.Format ("Event {0} has no underlying member to attach event", member));
  318. int idx = value.LastIndexOf ('.');
  319. var xt = idx < 0 ? root_state.Type : ResolveTypeFromName (value.Substring (0, idx));
  320. if (xt == null)
  321. throw new XamlObjectWriterException (String.Format ("Referenced type {0} in event {1} was not found", value, member));
  322. if (xt.UnderlyingType == null)
  323. throw new XamlObjectWriterException (String.Format ("Referenced type {0} in event {1} has no underlying type", value, member));
  324. string mn = idx < 0 ? value : value.Substring (idx + 1);
  325. var ev = (EventInfo) member.UnderlyingMember;
  326. // get an appropriate MethodInfo overload whose signature matches the event's handler type.
  327. // FIXME: this may need more strict match. RuntimeBinder may be useful here.
  328. var eventMethodParams = ev.EventHandlerType.GetMethod ("Invoke").GetParameters ();
  329. var target = root_state.Value;
  330. var mi = target.GetType().GetMethod (mn, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, (from pi in eventMethodParams select pi.ParameterType).ToArray (), null);
  331. if (mi == null)
  332. throw new XamlObjectWriterException (String.Format ("Referenced value method {0} in type {1} indicated by event {2} was not found", mn, value, member));
  333. var obj = object_states.Peek ().Value;
  334. ev.AddEventHandler (obj, Delegate.CreateDelegate (ev.EventHandlerType, target, mi));
  335. }
  336. void SetValue (XamlMember member, object value)
  337. {
  338. if (member == XamlLanguage.FactoryMethod)
  339. object_states.Peek ().FactoryMethod = (string) value;
  340. else if (member.IsDirective)
  341. return;
  342. else
  343. SetValue (member, object_states.Peek ().Value, value);
  344. }
  345. void SetValue (XamlMember member, object target, object value)
  346. {
  347. if (!source.OnSetValue (target, member, value))
  348. member.Invoker.SetValue (target, value);
  349. }
  350. void PopulateObject (bool considerPositionalParameters, IList<object> contents)
  351. {
  352. var state = object_states.Peek ();
  353. var args = state.Type.GetSortedConstructorArguments ().ToArray ();
  354. var argt = args != null ? (IList<XamlType>) (from arg in args select arg.Type).ToArray () : considerPositionalParameters ? state.Type.GetPositionalParameters (contents.Count) : null;
  355. var argv = new object [argt.Count];
  356. for (int i = 0; i < argv.Length; i++)
  357. argv [i] = GetCorrectlyTypedValue (args [i], argt [i], contents [i]);
  358. state.Value = state.Type.Invoker.CreateInstance (argv);
  359. state.IsInstantiated = true;
  360. if (state.Type.IsAmbient)
  361. ambient_provider.Push (new AmbientPropertyValue (CurrentMember, state.Value));
  362. HandleBeginInit (state.Value);
  363. }
  364. protected override void OnWriteValue (object value)
  365. {
  366. if (CurrentMemberState.Value != null)
  367. throw new XamlDuplicateMemberException (String.Format ("Member '{0}' is already written to current type '{1}'", CurrentMember, object_states.Peek ().Type));
  368. StoreAppropriatelyTypedValue (value, null);
  369. }
  370. protected override void OnWriteNamespace (NamespaceDeclaration nd)
  371. {
  372. // nothing to do here.
  373. }
  374. void StoreAppropriatelyTypedValue (object obj, object keyObj)
  375. {
  376. var ms = CurrentMemberState; // note that this retrieves parent's current property for EndObject.
  377. if (ms != null) {
  378. var state = object_states.Peek ();
  379. var parent = state.Value;
  380. var xt = state.Type;
  381. var xm = ms.Member;
  382. if (xm == XamlLanguage.Initialization) {
  383. state.Value = GetCorrectlyTypedValue (null, xt, obj);
  384. state.IsInstantiated = true;
  385. } else if (xm.IsEvent) {
  386. ms.Value = (string) obj; // save name of value delegate (method).
  387. state.IsInstantiated = true;
  388. } else if (xm.Type.IsXData) {
  389. var xdata = (XData) obj;
  390. var ixser = xm.Invoker.GetValue (state.Value) as IXmlSerializable;
  391. if (ixser != null)
  392. ixser.ReadXml ((XmlReader) xdata.XmlReader);
  393. }
  394. else if (xm == XamlLanguage.Base)
  395. ms.Value = GetCorrectlyTypedValue (null, xm.Type, obj);
  396. else if (xm == XamlLanguage.Name || xm == xt.GetAliasedProperty (XamlLanguage.Name))
  397. ms.Value = GetCorrectlyTypedValue (xm, XamlLanguage.String, obj);
  398. else if (xm == XamlLanguage.Key)
  399. state.KeyValue = GetCorrectlyTypedValue (null, xt.KeyType, obj);
  400. else {
  401. if (!AddToCollectionIfAppropriate (xt, xm, parent, obj, keyObj)) {
  402. if (!xm.IsReadOnly)
  403. ms.Value = GetCorrectlyTypedValue (xm, xm.Type, obj);
  404. }
  405. }
  406. }
  407. }
  408. bool AddToCollectionIfAppropriate (XamlType xt, XamlMember xm, object parent, object obj, object keyObj)
  409. {
  410. var mt = xm.Type;
  411. if (xm == XamlLanguage.Items ||
  412. xm == XamlLanguage.PositionalParameters ||
  413. xm == XamlLanguage.Arguments) {
  414. if (xt.IsDictionary)
  415. mt.Invoker.AddToDictionary (parent, GetCorrectlyTypedValue (null, xt.KeyType, keyObj), GetCorrectlyTypedValue (null, xt.ItemType, obj));
  416. else // collection. Note that state.Type isn't usable for PositionalParameters to identify collection kind.
  417. mt.Invoker.AddToCollection (parent, GetCorrectlyTypedValue (null, xt.ItemType, obj));
  418. return true;
  419. }
  420. else
  421. return false;
  422. }
  423. object GetCorrectlyTypedValue (XamlMember xm, XamlType xt, object value)
  424. {
  425. try {
  426. return DoGetCorrectlyTypedValue (xm, xt, value);
  427. } catch (XamlObjectWriterException) {
  428. throw;
  429. } catch (Exception ex) {
  430. // For + ex.Message, the runtime should print InnerException message like .NET does.
  431. throw new XamlObjectWriterException (String.Format ("Could not convert object \'{0}' (of type {1}) to {2}: ", value, value != null ? (object) value.GetType () : "(null)", xt) + ex.Message, ex);
  432. }
  433. }
  434. // It expects that it is not invoked when there is no value to
  435. // assign.
  436. // When it is passed null, then it returns a default instance.
  437. // For example, passing null as Int32 results in 0.
  438. // But do not immediately try to instantiate with the type, since the type might be abstract.
  439. object DoGetCorrectlyTypedValue (XamlMember xm, XamlType xt, object value)
  440. {
  441. if (value == null) {
  442. if (xt.IsContentValue (service_provider)) // it is for collection/dictionary key and item
  443. return null;
  444. else
  445. return xt.IsNullable ? null : xt.Invoker.CreateInstance (new object [0]);
  446. }
  447. if (xt == null)
  448. return value;
  449. // Not sure if this is really required though...
  450. var vt = sctx.GetXamlType (value.GetType ());
  451. if (vt.CanAssignTo (xt))
  452. return value;
  453. // FIXME: this could be generalized by some means, but I cannot find any.
  454. if (xt.UnderlyingType == typeof (XamlType) && value is string)
  455. value = ResolveTypeFromName ((string) value);
  456. // FIXME: this could be generalized by some means, but I cannot find any.
  457. if (xt.UnderlyingType == typeof (Type))
  458. value = new TypeExtension ((string) value).ProvideValue (service_provider);
  459. if (xt == XamlLanguage.Type && value is string)
  460. value = new TypeExtension ((string) value);
  461. if (IsAllowedType (xt, value))
  462. return value;
  463. var xtc = (xm != null ? xm.TypeConverter : null) ?? xt.TypeConverter;
  464. if (xtc != null && value != null) {
  465. var tc = xtc.ConverterInstance;
  466. if (tc != null && tc.CanConvertFrom (value.GetType ()))
  467. value = tc.ConvertFrom (value);
  468. return value;
  469. }
  470. throw new XamlObjectWriterException (String.Format ("Value '{0}' (of type {1}) is not of or convertible to type {0} (member {3})", value, value != null ? (object) value.GetType () : "(null)", xt, xm));
  471. }
  472. XamlType ResolveTypeFromName (string name)
  473. {
  474. var nsr = (IXamlNamespaceResolver) service_provider.GetService (typeof (IXamlNamespaceResolver));
  475. return sctx.GetXamlType (XamlTypeName.Parse (name, nsr));
  476. }
  477. bool IsAllowedType (XamlType xt, object value)
  478. {
  479. return xt == null ||
  480. xt.UnderlyingType == null ||
  481. xt.UnderlyingType.IsInstanceOfType (value) ||
  482. value == null && xt == XamlLanguage.Null ||
  483. xt.IsMarkupExtension && IsAllowedType (xt.MarkupExtensionReturnType, value);
  484. }
  485. void InitializeObjectIfRequired (bool waitForParameters)
  486. {
  487. var state = object_states.Peek ();
  488. if (state.IsInstantiated)
  489. return;
  490. if (waitForParameters && (state.Type.ConstructionRequiresArguments || state.Type.HasPositionalParameters (service_provider)))
  491. return;
  492. // FIXME: "The default techniques in absence of a factory method are to attempt to find a default constructor, then attempt to find an identified type converter on type, member, or destination type."
  493. // http://msdn.microsoft.com/en-us/library/system.xaml.xamllanguage.factorymethod%28VS.100%29.aspx
  494. object obj;
  495. if (state.FactoryMethod != null) // FIXME: it must be implemented and verified with tests.
  496. throw new NotImplementedException ();
  497. else
  498. obj = state.Type.Invoker.CreateInstance (null);
  499. state.Value = obj;
  500. state.IsInstantiated = true;
  501. if (state.Type.IsAmbient)
  502. ambient_provider.Push (new AmbientPropertyValue (CurrentMember, obj));
  503. else
  504. HandleBeginInit (obj);
  505. }
  506. internal IXamlNameResolver name_resolver {
  507. get { return (IXamlNameResolver) service_provider.GetService (typeof (IXamlNameResolver)); }
  508. }
  509. internal override IAmbientProvider AmbientProvider {
  510. get { return ambient_provider; }
  511. }
  512. void ResolvePendingReferences ()
  513. {
  514. foreach (var fixup in pending_name_references) {
  515. foreach (var name in fixup.Names) {
  516. bool isFullyInitialized;
  517. // FIXME: sort out relationship between name_scope and name_resolver. (unify to name_resolver, probably)
  518. var obj = name_scope.FindName (name) ?? name_resolver.Resolve (name, out isFullyInitialized);
  519. if (obj == null)
  520. throw new XamlObjectWriterException (String.Format ("Unresolved object reference '{0}' was found", name));
  521. if (!AddToCollectionIfAppropriate (fixup.ParentType, fixup.ParentMember, fixup.ParentValue, obj, null)) // FIXME: is keyObj always null?
  522. SetValue (fixup.ParentMember, fixup.ParentValue, obj);
  523. }
  524. }
  525. }
  526. void HandleBeginInit (object value)
  527. {
  528. var si = value as ISupportInitialize;
  529. if (si == null)
  530. return;
  531. si.BeginInit ();
  532. source.OnAfterBeginInit (value);
  533. }
  534. void HandleEndInit (object value)
  535. {
  536. var si = value as ISupportInitialize;
  537. if (si == null)
  538. return;
  539. si.EndInit ();
  540. source.OnAfterEndInit (value);
  541. }
  542. }
  543. }