DesignerSerializationManager.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. //
  2. // System.ComponentModel.Design.Serialization.DesignerSerializationManager
  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.Collections;
  31. using System.Collections.Generic;
  32. using System.Reflection;
  33. using System.ComponentModel;
  34. using System.ComponentModel.Design;
  35. namespace System.ComponentModel.Design.Serialization
  36. {
  37. public class DesignerSerializationManager : IDesignerSerializationManager, IServiceProvider
  38. {
  39. private class Session : IDisposable
  40. {
  41. private DesignerSerializationManager _manager;
  42. public Session (DesignerSerializationManager manager)
  43. {
  44. _manager = manager;
  45. }
  46. public void Dispose ()
  47. {
  48. _manager.OnSessionDisposed (EventArgs.Empty);
  49. }
  50. }
  51. public DesignerSerializationManager () : this (null)
  52. {
  53. }
  54. // This constructor sets the PreserveNames and ValidateRecycledTypes properties to true.
  55. //
  56. public DesignerSerializationManager (IServiceProvider provider)
  57. {
  58. _serviceProvider = provider;
  59. _preserveNames = true;
  60. _validateRecycledTypes = true;
  61. }
  62. private IServiceProvider _serviceProvider;
  63. private bool _preserveNames = false;
  64. private bool _validateRecycledTypes = false;
  65. private bool _recycleInstances = false;
  66. private IContainer _designerContainer = null;
  67. private object _propertyProvider = null;
  68. private Session _session = null;
  69. private ArrayList _errors = null;
  70. private List <IDesignerSerializationProvider> _serializationProviders;
  71. private Dictionary <Type, object> _serializersCache = null; // componentType - serializer instance
  72. private Dictionary <string, object> _instancesByNameCache = null; // name - instance
  73. private Dictionary <object, string> _instancesByValueCache = null; // instance - name
  74. private ContextStack _contextStack = null;
  75. public bool RecycleInstances {
  76. get { return _recycleInstances; }
  77. set {
  78. VerifyNotInSession ();
  79. _recycleInstances = value;
  80. }
  81. }
  82. public bool PreserveNames {
  83. get { return _preserveNames; }
  84. set {
  85. VerifyNotInSession ();
  86. _preserveNames = value;
  87. }
  88. }
  89. public bool ValidateRecycledTypes {
  90. get { return _validateRecycledTypes; }
  91. set {
  92. VerifyNotInSession ();
  93. _validateRecycledTypes = value;
  94. }
  95. }
  96. public IContainer Container {
  97. get {
  98. if (_designerContainer == null) {
  99. _designerContainer = (this.GetService (typeof (IDesignerHost)) as IDesignerHost).Container;
  100. }
  101. return _designerContainer;
  102. }
  103. set{
  104. VerifyNotInSession ();
  105. _designerContainer = value;
  106. }
  107. }
  108. public object PropertyProvider {
  109. get { return _propertyProvider; }
  110. set { _propertyProvider = value; }
  111. }
  112. public IList Errors {
  113. get { return _errors; }
  114. }
  115. public event EventHandler SessionDisposed;
  116. public event EventHandler SessionCreated;
  117. protected virtual void OnSessionCreated (EventArgs e)
  118. {
  119. if (SessionCreated != null) {
  120. SessionCreated (this, e);
  121. }
  122. }
  123. // For behaviour description:
  124. //
  125. // http://msdn2.microsoft.com/en-us/library/system.componentmodel.design.serialization.designerserializationmanager.validaterecycledtypes.aspx
  126. // http://msdn2.microsoft.com/en-us/library/system.componentmodel.design.serialization.designerserializationmanager.preservenames.aspx
  127. //
  128. protected virtual object CreateInstance (Type type, ICollection arguments, string name, bool addToContainer)
  129. {
  130. VerifyInSession ();
  131. object instance = null;
  132. if (name != null && _recycleInstances) {
  133. _instancesByNameCache.TryGetValue (name, out instance);
  134. if (instance != null && _validateRecycledTypes) {
  135. if (instance.GetType () != type)
  136. instance = null;
  137. }
  138. }
  139. if (instance == null || !_recycleInstances) {
  140. instance = this.CreateInstance (type, arguments);
  141. }
  142. if (addToContainer && instance != null && this.Container != null && typeof (IComponent).IsAssignableFrom (type)) {
  143. if (_preserveNames) {
  144. this.Container.Add ((IComponent) instance, name);
  145. }
  146. else {
  147. if (name != null && this.Container.Components[name] != null) {
  148. this.Container.Add ((IComponent) instance);
  149. }
  150. else {
  151. this.Container.Add ((IComponent) instance, name);
  152. }
  153. }
  154. ISite site = ((IComponent)instance).Site; // get the name from the site in case a name has been generated.
  155. if (site != null)
  156. name = site.Name;
  157. }
  158. if (instance != null && name != null) {
  159. _instancesByNameCache[name] = instance;
  160. _instancesByValueCache[instance] = name;
  161. }
  162. return instance;
  163. }
  164. // Invokes the constructor that matches the arguments
  165. //
  166. private object CreateInstance (Type type, ICollection argsCollection)
  167. {
  168. object instance = null;
  169. object[] arguments = null;
  170. Type[] types = new Type[0];
  171. if (argsCollection != null) {
  172. arguments = new object[argsCollection.Count];
  173. types = new Type[argsCollection.Count];
  174. argsCollection.CopyTo (arguments, 0);
  175. for (int i=0; i < arguments.Length; i++) {
  176. if (arguments[i] == null)
  177. types[i] = null;
  178. else
  179. types[i] = arguments[i].GetType ();
  180. }
  181. }
  182. ConstructorInfo ctor = type.GetConstructor (types);
  183. if (ctor != null) {
  184. instance = ctor.Invoke (arguments);
  185. }
  186. return instance;
  187. }
  188. public object GetSerializer (Type componentType, Type serializerType)
  189. {
  190. VerifyInSession ();
  191. if (serializerType == null)
  192. throw new ArgumentNullException ("serializerType");
  193. object serializer = null;
  194. if (componentType != null) {
  195. // try 1: from cache
  196. //
  197. _serializersCache.TryGetValue (componentType, out serializer);
  198. // check for provider attribute and add it to the list of providers
  199. //
  200. if (serializer != null && !serializerType.IsAssignableFrom (serializer.GetType ()))
  201. serializer = null;
  202. AttributeCollection attributes = TypeDescriptor.GetAttributes (componentType);
  203. DefaultSerializationProviderAttribute providerAttribute = attributes[typeof (DefaultSerializationProviderAttribute)]
  204. as DefaultSerializationProviderAttribute;
  205. if (providerAttribute != null && this.GetType (providerAttribute.ProviderTypeName) == serializerType) {
  206. object provider = Activator.CreateInstance (this.GetType (providerAttribute.ProviderTypeName),
  207. BindingFlags.CreateInstance | BindingFlags.Public | BindingFlags.NonPublic,
  208. null, null, null);
  209. ((IDesignerSerializationManager)this).AddSerializationProvider ((IDesignerSerializationProvider) provider);
  210. }
  211. }
  212. // try 2: DesignerSerializerAttribute
  213. //
  214. if (serializer == null && componentType != null) {
  215. AttributeCollection attributes = TypeDescriptor.GetAttributes (componentType);
  216. DesignerSerializerAttribute serializerAttribute = attributes[typeof (DesignerSerializerAttribute)] as DesignerSerializerAttribute;
  217. if (serializerAttribute != null &&
  218. this.GetType (serializerAttribute.SerializerBaseTypeName) == serializerType) {
  219. serializer = Activator.CreateInstance (this.GetType (serializerAttribute.SerializerTypeName),
  220. BindingFlags.CreateInstance | BindingFlags.Instance |
  221. BindingFlags.Public | BindingFlags.NonPublic,
  222. null, null, null);
  223. }
  224. if (serializer != null)
  225. _serializersCache[componentType] = serializer;
  226. }
  227. // try 3: from provider
  228. //
  229. if (serializer == null) {
  230. foreach (IDesignerSerializationProvider provider in _serializationProviders) {
  231. serializer = provider.GetSerializer (this, null, componentType, serializerType);
  232. if (serializer != null)
  233. break;
  234. }
  235. }
  236. return serializer;
  237. }
  238. private void VerifyInSession ()
  239. {
  240. if (_session == null)
  241. throw new InvalidOperationException ("Not in session.");
  242. }
  243. private void VerifyNotInSession ()
  244. {
  245. if (_session != null)
  246. throw new InvalidOperationException ("In session.");
  247. }
  248. public IDisposable CreateSession ()
  249. {
  250. _errors = new ArrayList ();
  251. _session = new Session (this);
  252. _serializersCache = new Dictionary<System.Type,object> ();
  253. _instancesByNameCache = new Dictionary<string,object> ();
  254. _instancesByValueCache = new Dictionary<object, string> ();
  255. _contextStack = new ContextStack ();
  256. this.OnSessionCreated (EventArgs.Empty);
  257. return _session;
  258. }
  259. protected virtual void OnSessionDisposed (EventArgs e)
  260. {
  261. _errors.Clear ();
  262. _errors = null;
  263. _serializersCache.Clear ();
  264. _serializersCache = null;
  265. _instancesByNameCache.Clear ();
  266. _instancesByNameCache = null;
  267. _instancesByValueCache.Clear ();
  268. _instancesByValueCache = null;
  269. _session = null;
  270. _contextStack = null;
  271. _resolveNameHandler = null;
  272. _serializationCompleteHandler = null;
  273. if (SessionDisposed != null) {
  274. SessionDisposed (this, e);
  275. }
  276. if (_serializationCompleteHandler != null)
  277. _serializationCompleteHandler (this, EventArgs.Empty);
  278. }
  279. protected virtual Type GetType (string name)
  280. {
  281. if (name == null)
  282. throw new ArgumentNullException ("name");
  283. this.VerifyInSession ();
  284. Type result = null;
  285. ITypeResolutionService typeResSvc = this.GetService (typeof (ITypeResolutionService)) as ITypeResolutionService;
  286. if (typeResSvc != null)
  287. result = typeResSvc.GetType (name);
  288. if (result == null)
  289. result = Type.GetType (name);
  290. return result;
  291. }
  292. #region IDesignerSerializationManager implementation
  293. protected virtual void OnResolveName (ResolveNameEventArgs e)
  294. {
  295. if (_resolveNameHandler != null) {
  296. _resolveNameHandler (this, e);
  297. }
  298. }
  299. void IDesignerSerializationManager.AddSerializationProvider (IDesignerSerializationProvider provider)
  300. {
  301. if (_serializationProviders == null)
  302. _serializationProviders = new List <IDesignerSerializationProvider> ();
  303. if (!_serializationProviders.Contains (provider))
  304. _serializationProviders.Add (provider);
  305. }
  306. void IDesignerSerializationManager.RemoveSerializationProvider (IDesignerSerializationProvider provider)
  307. {
  308. if (_serializationProviders != null)
  309. _serializationProviders.Remove (provider);
  310. }
  311. object IDesignerSerializationManager.CreateInstance (Type type, ICollection arguments, string name, bool addToContainer)
  312. {
  313. return this.CreateInstance (type, arguments, name, addToContainer);
  314. }
  315. object IDesignerSerializationManager.GetInstance (string name)
  316. {
  317. if (name == null)
  318. throw new ArgumentNullException ("name");
  319. this.VerifyInSession ();
  320. object instance = null;
  321. _instancesByNameCache.TryGetValue (name, out instance);
  322. if (instance == null && _preserveNames && this.Container != null)
  323. instance = this.Container.Components[name];
  324. if (instance == null)
  325. instance = this.RequestInstance (name);
  326. return instance;
  327. }
  328. private object RequestInstance (string name)
  329. {
  330. ResolveNameEventArgs args = new ResolveNameEventArgs (name);
  331. this.OnResolveName (args);
  332. return args.Value;
  333. }
  334. Type IDesignerSerializationManager.GetType (string name)
  335. {
  336. return this.GetType (name);
  337. }
  338. object IDesignerSerializationManager.GetSerializer (Type type, Type serializerType)
  339. {
  340. return this.GetSerializer (type, serializerType);
  341. }
  342. string IDesignerSerializationManager.GetName (object instance)
  343. {
  344. if (instance == null)
  345. throw new ArgumentNullException ("instance");
  346. this.VerifyInSession ();
  347. string name = null;
  348. if (instance is IComponent) {
  349. ISite site = ((IComponent)instance).Site;
  350. if (site != null && site is INestedSite)
  351. name = ((INestedSite)site).FullName;
  352. else if (site != null)
  353. name = site.Name;
  354. }
  355. if (name == null)
  356. _instancesByValueCache.TryGetValue (instance, out name);
  357. return name;
  358. }
  359. void IDesignerSerializationManager.SetName (object instance, string name)
  360. {
  361. if (instance == null)
  362. throw new ArgumentNullException ("instance");
  363. if (name == null)
  364. throw new ArgumentNullException ("name");
  365. if (_instancesByNameCache.ContainsKey (name))
  366. throw new ArgumentException ("The object specified by instance already has a name, or name is already used by another named object.");
  367. _instancesByNameCache.Add (name, instance);
  368. _instancesByValueCache.Add (instance, name);
  369. }
  370. void IDesignerSerializationManager.ReportError (object error)
  371. {
  372. this.VerifyInSession ();
  373. _errors.Add (error);
  374. }
  375. ContextStack IDesignerSerializationManager.Context {
  376. get { return _contextStack; }
  377. }
  378. PropertyDescriptorCollection IDesignerSerializationManager.Properties {
  379. get {
  380. PropertyDescriptorCollection properties = new PropertyDescriptorCollection (new PropertyDescriptor[0]);
  381. object component = this.PropertyProvider;
  382. if (component != null)
  383. properties = TypeDescriptor.GetProperties (component);
  384. return properties;
  385. }
  386. }
  387. private EventHandler _serializationCompleteHandler;
  388. private ResolveNameEventHandler _resolveNameHandler;
  389. event EventHandler IDesignerSerializationManager.SerializationComplete {
  390. add {
  391. this.VerifyInSession ();
  392. _serializationCompleteHandler = (EventHandler) Delegate.Combine (_serializationCompleteHandler, value);
  393. }
  394. remove {
  395. _serializationCompleteHandler = (EventHandler) Delegate.Remove (_serializationCompleteHandler, value);
  396. }
  397. }
  398. event ResolveNameEventHandler IDesignerSerializationManager.ResolveName {
  399. add {
  400. this.VerifyInSession ();
  401. _resolveNameHandler = (ResolveNameEventHandler) Delegate.Combine (_resolveNameHandler, value);
  402. }
  403. remove {
  404. _resolveNameHandler = (ResolveNameEventHandler) Delegate.Remove (_resolveNameHandler, value);
  405. }
  406. }
  407. #endregion
  408. object IServiceProvider.GetService (Type service)
  409. {
  410. return this.GetService (service);
  411. }
  412. protected virtual object GetService (Type service)
  413. {
  414. object result = null;
  415. if (_serviceProvider != null)
  416. result = _serviceProvider.GetService (service);
  417. return result;
  418. }
  419. }
  420. }
  421. #endif