DesignerSerializationManager.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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. try {
  220. serializer = Activator.CreateInstance (this.GetType (serializerAttribute.SerializerTypeName),
  221. BindingFlags.CreateInstance | BindingFlags.Instance |
  222. BindingFlags.Public | BindingFlags.NonPublic,
  223. null, null, null);
  224. } catch {}
  225. }
  226. if (serializer != null)
  227. _serializersCache[componentType] = serializer;
  228. }
  229. // try 3: from provider
  230. //
  231. if (serializer == null) {
  232. foreach (IDesignerSerializationProvider provider in _serializationProviders) {
  233. serializer = provider.GetSerializer (this, null, componentType, serializerType);
  234. if (serializer != null)
  235. break;
  236. }
  237. }
  238. return serializer;
  239. }
  240. private void VerifyInSession ()
  241. {
  242. if (_session == null)
  243. throw new InvalidOperationException ("Not in session.");
  244. }
  245. private void VerifyNotInSession ()
  246. {
  247. if (_session != null)
  248. throw new InvalidOperationException ("In session.");
  249. }
  250. public IDisposable CreateSession ()
  251. {
  252. _errors = new ArrayList ();
  253. _session = new Session (this);
  254. _serializersCache = new Dictionary<System.Type,object> ();
  255. _instancesByNameCache = new Dictionary<string,object> ();
  256. _instancesByValueCache = new Dictionary<object, string> ();
  257. _contextStack = new ContextStack ();
  258. this.OnSessionCreated (EventArgs.Empty);
  259. return _session;
  260. }
  261. protected virtual void OnSessionDisposed (EventArgs e)
  262. {
  263. _errors.Clear ();
  264. _errors = null;
  265. _serializersCache.Clear ();
  266. _serializersCache = null;
  267. _instancesByNameCache.Clear ();
  268. _instancesByNameCache = null;
  269. _instancesByValueCache.Clear ();
  270. _instancesByValueCache = null;
  271. _session = null;
  272. _contextStack = null;
  273. _resolveNameHandler = null;
  274. _serializationCompleteHandler = null;
  275. if (SessionDisposed != null) {
  276. SessionDisposed (this, e);
  277. }
  278. if (_serializationCompleteHandler != null)
  279. _serializationCompleteHandler (this, EventArgs.Empty);
  280. }
  281. protected virtual Type GetType (string name)
  282. {
  283. if (name == null)
  284. throw new ArgumentNullException ("name");
  285. this.VerifyInSession ();
  286. Type result = null;
  287. ITypeResolutionService typeResSvc = this.GetService (typeof (ITypeResolutionService)) as ITypeResolutionService;
  288. if (typeResSvc != null)
  289. result = typeResSvc.GetType (name);
  290. if (result == null)
  291. result = Type.GetType (name);
  292. return result;
  293. }
  294. #region IDesignerSerializationManager implementation
  295. protected virtual void OnResolveName (ResolveNameEventArgs e)
  296. {
  297. if (_resolveNameHandler != null) {
  298. _resolveNameHandler (this, e);
  299. }
  300. }
  301. void IDesignerSerializationManager.AddSerializationProvider (IDesignerSerializationProvider provider)
  302. {
  303. if (_serializationProviders == null)
  304. _serializationProviders = new List <IDesignerSerializationProvider> ();
  305. if (!_serializationProviders.Contains (provider))
  306. _serializationProviders.Add (provider);
  307. }
  308. void IDesignerSerializationManager.RemoveSerializationProvider (IDesignerSerializationProvider provider)
  309. {
  310. if (_serializationProviders != null)
  311. _serializationProviders.Remove (provider);
  312. }
  313. object IDesignerSerializationManager.CreateInstance (Type type, ICollection arguments, string name, bool addToContainer)
  314. {
  315. return this.CreateInstance (type, arguments, name, addToContainer);
  316. }
  317. object IDesignerSerializationManager.GetInstance (string name)
  318. {
  319. if (name == null)
  320. throw new ArgumentNullException ("name");
  321. this.VerifyInSession ();
  322. object instance = null;
  323. _instancesByNameCache.TryGetValue (name, out instance);
  324. if (instance == null && _preserveNames && this.Container != null)
  325. instance = this.Container.Components[name];
  326. if (instance == null)
  327. instance = this.RequestInstance (name);
  328. return instance;
  329. }
  330. private object RequestInstance (string name)
  331. {
  332. ResolveNameEventArgs args = new ResolveNameEventArgs (name);
  333. this.OnResolveName (args);
  334. return args.Value;
  335. }
  336. Type IDesignerSerializationManager.GetType (string name)
  337. {
  338. return this.GetType (name);
  339. }
  340. object IDesignerSerializationManager.GetSerializer (Type type, Type serializerType)
  341. {
  342. return this.GetSerializer (type, serializerType);
  343. }
  344. string IDesignerSerializationManager.GetName (object instance)
  345. {
  346. if (instance == null)
  347. throw new ArgumentNullException ("instance");
  348. this.VerifyInSession ();
  349. string name = null;
  350. if (instance is IComponent) {
  351. ISite site = ((IComponent)instance).Site;
  352. if (site != null && site is INestedSite)
  353. name = ((INestedSite)site).FullName;
  354. else if (site != null)
  355. name = site.Name;
  356. }
  357. if (name == null)
  358. _instancesByValueCache.TryGetValue (instance, out name);
  359. return name;
  360. }
  361. void IDesignerSerializationManager.SetName (object instance, string name)
  362. {
  363. if (instance == null)
  364. throw new ArgumentNullException ("instance");
  365. if (name == null)
  366. throw new ArgumentNullException ("name");
  367. if (_instancesByNameCache.ContainsKey (name))
  368. throw new ArgumentException ("The object specified by instance already has a name, or name is already used by another named object.");
  369. _instancesByNameCache.Add (name, instance);
  370. _instancesByValueCache.Add (instance, name);
  371. }
  372. void IDesignerSerializationManager.ReportError (object error)
  373. {
  374. this.VerifyInSession ();
  375. _errors.Add (error);
  376. }
  377. ContextStack IDesignerSerializationManager.Context {
  378. get { return _contextStack; }
  379. }
  380. PropertyDescriptorCollection IDesignerSerializationManager.Properties {
  381. get {
  382. PropertyDescriptorCollection properties = new PropertyDescriptorCollection (new PropertyDescriptor[0]);
  383. object component = this.PropertyProvider;
  384. if (component != null)
  385. properties = TypeDescriptor.GetProperties (component);
  386. return properties;
  387. }
  388. }
  389. private EventHandler _serializationCompleteHandler;
  390. private ResolveNameEventHandler _resolveNameHandler;
  391. event EventHandler IDesignerSerializationManager.SerializationComplete {
  392. add {
  393. this.VerifyInSession ();
  394. _serializationCompleteHandler = (EventHandler) Delegate.Combine (_serializationCompleteHandler, value);
  395. }
  396. remove {
  397. _serializationCompleteHandler = (EventHandler) Delegate.Remove (_serializationCompleteHandler, value);
  398. }
  399. }
  400. event ResolveNameEventHandler IDesignerSerializationManager.ResolveName {
  401. add {
  402. this.VerifyInSession ();
  403. _resolveNameHandler = (ResolveNameEventHandler) Delegate.Combine (_resolveNameHandler, value);
  404. }
  405. remove {
  406. _resolveNameHandler = (ResolveNameEventHandler) Delegate.Remove (_resolveNameHandler, value);
  407. }
  408. }
  409. #endregion
  410. object IServiceProvider.GetService (Type service)
  411. {
  412. return this.GetService (service);
  413. }
  414. protected virtual object GetService (Type service)
  415. {
  416. object result = null;
  417. if (_serviceProvider != null)
  418. result = _serviceProvider.GetService (service);
  419. return result;
  420. }
  421. }
  422. }
  423. #endif