PageRenderTime 49ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Design/System.ComponentModel.Design.Serialization/CodeDomComponentSerializationService.cs

https://bitbucket.org/danipen/mono
C# | 589 lines | 461 code | 84 blank | 44 comment | 88 complexity | 5181726906b2b899f33582a18814750d 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. // System.ComponentModel.Design.Serialization.CodeDomComponentSerializationService
  3. //
  4. // Authors:
  5. // Ivan N. Zlatev (contact@i-nZ.net)
  6. //
  7. // (C) 2007 Ivan N. Zlatev
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining
  10. // a copy of this software and associated documentation files (the
  11. // "Software"), to deal in the Software without restriction, including
  12. // without limitation the rights to use, copy, modify, merge, publish,
  13. // distribute, sublicense, and/or sell copies of the Software, and to
  14. // permit persons to whom the Software is furnished to do so, subject to
  15. // the following conditions:
  16. //
  17. // The above copyright notice and this permission notice shall be
  18. // included in all copies or substantial portions of the Software.
  19. //
  20. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  21. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  22. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. //
  28. #if NET_2_0
  29. using System;
  30. using System.Runtime.Serialization;
  31. using System.Runtime.Serialization.Formatters.Binary;
  32. using System.ComponentModel;
  33. using System.ComponentModel.Design.Serialization;
  34. using System.Collections;
  35. using System.Collections.Generic;
  36. using System.IO;
  37. namespace System.ComponentModel.Design.Serialization
  38. {
  39. // A ComponentSerializationService that uses a CodeDomSerializationStore
  40. // to serialize Components and MemberDescriptors to CodeStatement and CodeStatementCollection
  41. //
  42. public sealed class CodeDomComponentSerializationService : ComponentSerializationService
  43. {
  44. [Serializable]
  45. private class CodeDomSerializationStore : SerializationStore, ISerializable
  46. {
  47. [Serializable]
  48. private class Entry
  49. {
  50. private bool _isSerialized;
  51. private object _serialized;
  52. private bool _absolute;
  53. private string _name;
  54. protected Entry ()
  55. {
  56. }
  57. public Entry (string name)
  58. {
  59. if (name == null)
  60. throw new ArgumentNullException ("name");
  61. _name = name;
  62. _isSerialized = false;
  63. _absolute = false;
  64. }
  65. public bool IsSerialized {
  66. get { return _isSerialized; }
  67. set { _isSerialized = value; }
  68. }
  69. public object Serialized {
  70. get { return _serialized; }
  71. set {
  72. _serialized = value;
  73. _isSerialized = true;
  74. }
  75. }
  76. public bool Absolute {
  77. get { return _absolute; }
  78. set { _absolute = value; }
  79. }
  80. public string Name {
  81. get { return _name; }
  82. set { _name = value; }
  83. }
  84. }
  85. [Serializable]
  86. private class MemberEntry : Entry
  87. {
  88. private MemberDescriptor _descriptor;
  89. protected MemberEntry ()
  90. {
  91. }
  92. public MemberEntry (MemberDescriptor descriptor)
  93. {
  94. if (descriptor == null)
  95. throw new ArgumentNullException ("descriptor");
  96. _descriptor = descriptor;
  97. base.Name = descriptor.Name;
  98. }
  99. public MemberDescriptor Descriptor {
  100. get { return _descriptor; }
  101. set { _descriptor = value; }
  102. }
  103. }
  104. [Serializable]
  105. private class ObjectEntry : Entry
  106. {
  107. private Type _type;
  108. [NonSerialized]
  109. private object _instance;
  110. private Dictionary<string,MemberEntry> _members;
  111. private bool _entireObject;
  112. protected ObjectEntry ()
  113. {
  114. }
  115. public ObjectEntry (object instance, string name) : base (name)
  116. {
  117. if (instance == null)
  118. throw new ArgumentNullException ("instance");
  119. _instance = instance;
  120. _type = instance.GetType ();
  121. _entireObject = false;
  122. }
  123. public Type Type {
  124. get { return _type; }
  125. }
  126. public object Instance {
  127. get { return _instance; }
  128. set {
  129. _instance = value;
  130. if (value != null)
  131. _type = value.GetType ();
  132. }
  133. }
  134. public Dictionary<string,MemberEntry> Members {
  135. get {
  136. if (_members == null)
  137. _members = new Dictionary <string, MemberEntry> ();
  138. return _members;
  139. }
  140. set { _members = value; }
  141. }
  142. public bool IsEntireObject {
  143. get { return _entireObject; }
  144. set { _entireObject = value; }
  145. }
  146. }
  147. // When e.g Copy->Pasting a component will not be preserved, but the serialized
  148. // data will contain references to the original component name. We handle this
  149. // here by checking whether CreateInstance returns a component with a different
  150. // name and we map the old name to the new one so that GetInstance will return
  151. // a reference to the new component.
  152. //
  153. private class InstanceRedirectorDesignerSerializationManager : IDesignerSerializationManager, IServiceProvider
  154. {
  155. DesignerSerializationManager _manager;
  156. private Dictionary <string, string> _nameMap;
  157. public InstanceRedirectorDesignerSerializationManager (IServiceProvider provider, IContainer container,
  158. bool validateRecycledTypes)
  159. {
  160. if (provider == null)
  161. throw new ArgumentNullException ("provider");
  162. DesignerSerializationManager manager = new DesignerSerializationManager (provider);
  163. manager.PreserveNames = false;
  164. if (container != null)
  165. manager.Container = container;
  166. manager.ValidateRecycledTypes = validateRecycledTypes;
  167. _manager = manager;
  168. }
  169. public IDisposable CreateSession ()
  170. {
  171. return _manager.CreateSession ();
  172. }
  173. public IList Errors {
  174. get { return _manager.Errors; }
  175. }
  176. object IServiceProvider.GetService (Type service)
  177. {
  178. return ((IServiceProvider)_manager).GetService (service);
  179. }
  180. #region IDesignerSerializationManager Wrapper Implementation
  181. void IDesignerSerializationManager.AddSerializationProvider (IDesignerSerializationProvider provider)
  182. {
  183. ((IDesignerSerializationManager)_manager).AddSerializationProvider (provider);
  184. }
  185. void IDesignerSerializationManager.RemoveSerializationProvider (IDesignerSerializationProvider provider)
  186. {
  187. ((IDesignerSerializationManager)_manager).RemoveSerializationProvider (provider);
  188. }
  189. object IDesignerSerializationManager.CreateInstance (Type type, ICollection arguments, string name, bool addToContainer)
  190. {
  191. object instance = ((IDesignerSerializationManager)_manager).CreateInstance (type, arguments, name, addToContainer);
  192. string newName = ((IDesignerSerializationManager)_manager).GetName (instance);
  193. if (newName != name) {
  194. if (_nameMap == null)
  195. _nameMap = new Dictionary<string, string> ();
  196. _nameMap[name] = newName;
  197. }
  198. return instance;
  199. }
  200. object IDesignerSerializationManager.GetInstance (string name)
  201. {
  202. if (_nameMap != null && _nameMap.ContainsKey (name))
  203. return ((IDesignerSerializationManager)_manager).GetInstance (_nameMap[name]);
  204. return ((IDesignerSerializationManager)_manager).GetInstance (name);
  205. }
  206. Type IDesignerSerializationManager.GetType (string name)
  207. {
  208. return ((IDesignerSerializationManager)_manager).GetType (name);
  209. }
  210. object IDesignerSerializationManager.GetSerializer (Type type, Type serializerType)
  211. {
  212. return ((IDesignerSerializationManager)_manager).GetSerializer (type, serializerType);
  213. }
  214. string IDesignerSerializationManager.GetName (object instance)
  215. {
  216. return ((IDesignerSerializationManager)_manager).GetName (instance);
  217. }
  218. void IDesignerSerializationManager.SetName (object instance, string name)
  219. {
  220. ((IDesignerSerializationManager)_manager).SetName (instance, name);
  221. }
  222. void IDesignerSerializationManager.ReportError (object error)
  223. {
  224. ((IDesignerSerializationManager)_manager).ReportError (error);
  225. }
  226. ContextStack IDesignerSerializationManager.Context {
  227. get { return ((IDesignerSerializationManager)_manager).Context; }
  228. }
  229. PropertyDescriptorCollection IDesignerSerializationManager.Properties {
  230. get { return ((IDesignerSerializationManager)_manager).Properties; }
  231. }
  232. event EventHandler IDesignerSerializationManager.SerializationComplete {
  233. add { ((IDesignerSerializationManager)_manager).SerializationComplete += value; }
  234. remove { ((IDesignerSerializationManager)_manager).SerializationComplete -= value; }
  235. }
  236. event ResolveNameEventHandler IDesignerSerializationManager.ResolveName {
  237. add { ((IDesignerSerializationManager)_manager).ResolveName += value; }
  238. remove { ((IDesignerSerializationManager)_manager).ResolveName -= value; }
  239. }
  240. #endregion
  241. } // InstanceRedirectorDesignerSerializationManager
  242. private bool _closed;
  243. private Dictionary <string, ObjectEntry> _objects;
  244. private IServiceProvider _provider;
  245. private ICollection _errors;
  246. internal CodeDomSerializationStore () : this (null)
  247. {
  248. }
  249. internal CodeDomSerializationStore (IServiceProvider provider)
  250. {
  251. _provider = provider;
  252. }
  253. private CodeDomSerializationStore (SerializationInfo info, StreamingContext context)
  254. {
  255. _objects = (Dictionary<string, ObjectEntry>) info.GetValue ("objects", typeof (Dictionary<string, ObjectEntry>));
  256. _closed = (bool) info.GetValue ("closed", typeof (bool));
  257. }
  258. void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
  259. {
  260. info.AddValue ("objects", _objects);
  261. info.AddValue ("closed", _closed);
  262. }
  263. public override void Close ()
  264. {
  265. if (!_closed) {
  266. Serialize (_provider);
  267. _closed = true;
  268. }
  269. }
  270. internal static CodeDomSerializationStore Load (Stream stream)
  271. {
  272. return new BinaryFormatter ().Deserialize (stream) as CodeDomSerializationStore;
  273. }
  274. public override void Save (Stream stream)
  275. {
  276. Close ();
  277. new BinaryFormatter ().Serialize (stream, this);
  278. }
  279. private void Serialize (IServiceProvider provider)
  280. {
  281. if (provider == null || _objects == null)
  282. return;
  283. // Use a new serialization manager to prevent from "deadlocking" the surface one
  284. // by trying to create new session when one currently exists
  285. //
  286. InstanceRedirectorDesignerSerializationManager manager =
  287. new InstanceRedirectorDesignerSerializationManager (provider, null, false);
  288. ((IDesignerSerializationManager)manager).AddSerializationProvider (CodeDomSerializationProvider.Instance);
  289. IDisposable session = manager.CreateSession ();
  290. foreach (ObjectEntry objectEntry in _objects.Values) {
  291. if (objectEntry.IsEntireObject) {
  292. CodeDomSerializer serializer = (CodeDomSerializer) ((IDesignerSerializationManager)manager).GetSerializer (objectEntry.Type,
  293. typeof (CodeDomSerializer));
  294. if (serializer != null) {
  295. object serialized = null;
  296. if (objectEntry.Absolute)
  297. serialized = serializer.SerializeAbsolute (manager,
  298. objectEntry.Instance);
  299. else
  300. serialized = serializer.Serialize (manager, objectEntry.Instance);
  301. objectEntry.Serialized = serialized;
  302. }
  303. } else {
  304. foreach (MemberEntry memberEntry in objectEntry.Members.Values) {
  305. CodeDomSerializer serializer = (CodeDomSerializer) ((IDesignerSerializationManager)manager).GetSerializer (
  306. objectEntry.Type, typeof (CodeDomSerializer));
  307. if (serializer != null) {
  308. object serialized = null;
  309. if (memberEntry.Absolute) {
  310. serialized = serializer.SerializeMemberAbsolute (manager,
  311. objectEntry.Instance,
  312. memberEntry.Descriptor);
  313. } else {
  314. serialized = serializer.SerializeMember (manager,
  315. objectEntry.Instance,
  316. memberEntry.Descriptor);
  317. }
  318. memberEntry.Serialized = serialized;
  319. }
  320. }
  321. }
  322. }
  323. _errors = manager.Errors;
  324. session.Dispose ();
  325. }
  326. internal void AddObject (object instance, bool absolute)
  327. {
  328. if (_closed)
  329. throw new InvalidOperationException ("store is closed");
  330. if (_objects == null)
  331. _objects = new Dictionary <string, ObjectEntry> ();
  332. string objectName = GetName (instance);
  333. if (!_objects.ContainsKey (objectName)) {
  334. ObjectEntry objectEntry = new ObjectEntry (instance, objectName);
  335. objectEntry.Absolute = absolute;
  336. objectEntry.IsEntireObject = true;
  337. _objects[objectName] = objectEntry;
  338. }
  339. }
  340. internal void AddMember (object owner, MemberDescriptor member, bool absolute)
  341. {
  342. if (_closed)
  343. throw new InvalidOperationException ("store is closed");
  344. if (member == null)
  345. throw new ArgumentNullException ("member");
  346. if (owner == null)
  347. throw new ArgumentNullException ("owner");
  348. if (_objects == null)
  349. _objects = new Dictionary <string, ObjectEntry> ();
  350. string objectName = GetName (owner);
  351. if (!_objects.ContainsKey (objectName))
  352. _objects.Add (objectName, new ObjectEntry (owner, objectName));
  353. MemberEntry memberEntry = new MemberEntry (member);
  354. memberEntry.Absolute = absolute;
  355. _objects[objectName].Members[member.Name] = memberEntry;
  356. }
  357. private string GetName (object value)
  358. {
  359. if (value == null)
  360. throw new ArgumentNullException ("value");
  361. string name = null;
  362. IComponent component = value as IComponent;
  363. if (component != null && component.Site != null) {
  364. if (component.Site is INestedSite)
  365. name = ((INestedSite)component.Site).FullName;
  366. else
  367. name = component.Site != null ? component.Site.Name : null;
  368. } else if (value is MemberDescriptor) {
  369. name = ((MemberDescriptor) value).Name;
  370. } else {
  371. name = value.GetHashCode ().ToString ();
  372. }
  373. return name;
  374. }
  375. internal ICollection Deserialize (IServiceProvider provider, IContainer container,
  376. bool validateRecycledTypes, bool applyDefaults)
  377. {
  378. List<object> objectInstances = new List<object> ();
  379. if (provider == null || _objects == null)
  380. return objectInstances;
  381. _provider = provider;
  382. // Use a new serialization manager to prevent from "deadlocking" the surface one
  383. // by trying to create new session when one currently exists
  384. //
  385. InstanceRedirectorDesignerSerializationManager manager =
  386. new InstanceRedirectorDesignerSerializationManager (provider, container, validateRecycledTypes);
  387. ((IDesignerSerializationManager)manager).AddSerializationProvider (CodeDomSerializationProvider.Instance);
  388. IDisposable session = manager.CreateSession ();
  389. foreach (ObjectEntry entry in _objects.Values)
  390. objectInstances.Add (DeserializeEntry (manager, entry));
  391. _errors = manager.Errors;
  392. session.Dispose ();
  393. return objectInstances;
  394. }
  395. private object DeserializeEntry (IDesignerSerializationManager manager, ObjectEntry objectEntry)
  396. {
  397. object deserialized = null;
  398. if (objectEntry.IsEntireObject) {
  399. CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
  400. typeof (CodeDomSerializer));
  401. if (serializer != null) {
  402. deserialized = serializer.Deserialize (manager, objectEntry.Serialized);
  403. // check if the name of the object has changed
  404. // (if it e.g clashes with another name)
  405. string newName = manager.GetName (deserialized);
  406. if (newName != objectEntry.Name)
  407. objectEntry.Name = newName;
  408. }
  409. } else {
  410. foreach (MemberEntry memberEntry in objectEntry.Members.Values) {
  411. CodeDomSerializer serializer = (CodeDomSerializer) manager.GetSerializer (objectEntry.Type,
  412. typeof (CodeDomSerializer));
  413. if (serializer != null)
  414. serializer.Deserialize (manager, memberEntry.Serialized);
  415. }
  416. }
  417. return deserialized;
  418. }
  419. public override ICollection Errors {
  420. get {
  421. if (_errors == null)
  422. _errors = new object[0];
  423. return _errors;
  424. }
  425. }
  426. } // CodeDomSerializationStore
  427. private IServiceProvider _provider;
  428. public CodeDomComponentSerializationService () : this (null)
  429. {
  430. }
  431. public CodeDomComponentSerializationService (IServiceProvider provider)
  432. {
  433. _provider = provider;
  434. }
  435. public override SerializationStore CreateStore ()
  436. {
  437. return new CodeDomSerializationStore (_provider);
  438. }
  439. public override SerializationStore LoadStore (Stream stream)
  440. {
  441. return CodeDomSerializationStore.Load (stream);
  442. }
  443. public override ICollection Deserialize (SerializationStore store)
  444. {
  445. return this.Deserialize (store, null);
  446. }
  447. public override ICollection Deserialize (SerializationStore store, IContainer container)
  448. {
  449. return DeserializeCore (store, container, true, true);
  450. }
  451. public override void DeserializeTo (SerializationStore store, IContainer container, bool validateRecycledTypes, bool applyDefaults)
  452. {
  453. DeserializeCore (store, container, validateRecycledTypes, applyDefaults);
  454. }
  455. private ICollection DeserializeCore (SerializationStore store, IContainer container, bool validateRecycledTypes,
  456. bool applyDefaults)
  457. {
  458. CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
  459. if (codeDomStore == null)
  460. throw new InvalidOperationException ("store type unsupported");
  461. return codeDomStore.Deserialize (_provider, container, validateRecycledTypes, applyDefaults);
  462. }
  463. public override void Serialize (SerializationStore store, object value)
  464. {
  465. SerializeCore (store, value, false);
  466. }
  467. public override void SerializeAbsolute (SerializationStore store, object value)
  468. {
  469. SerializeCore (store, value, true);
  470. }
  471. public override void SerializeMember (SerializationStore store, object owningObject, MemberDescriptor member)
  472. {
  473. SerializeMemberCore (store, owningObject, member, false);
  474. }
  475. public override void SerializeMemberAbsolute (SerializationStore store, object owningObject, MemberDescriptor member)
  476. {
  477. SerializeMemberCore (store, owningObject, member, true);
  478. }
  479. private void SerializeCore (SerializationStore store, object value, bool absolute)
  480. {
  481. if (value == null)
  482. throw new ArgumentNullException ("value");
  483. if (store == null)
  484. throw new ArgumentNullException ("store");
  485. CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
  486. if (store == null)
  487. throw new InvalidOperationException ("store type unsupported");
  488. codeDomStore.AddObject (value, absolute);
  489. }
  490. private void SerializeMemberCore (SerializationStore store, object owningObject, MemberDescriptor member, bool absolute)
  491. {
  492. if (member == null)
  493. throw new ArgumentNullException ("member");
  494. if (owningObject == null)
  495. throw new ArgumentNullException ("owningObject");
  496. if (store == null)
  497. throw new ArgumentNullException ("store");
  498. CodeDomSerializationStore codeDomStore = store as CodeDomSerializationStore;
  499. if (codeDomStore == null)
  500. throw new InvalidOperationException ("store type unsupported");
  501. codeDomStore.AddMember (owningObject, member, absolute);
  502. }
  503. }
  504. }
  505. #endif