ApplicationSettingsBase.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. // Permission is hereby granted, free of charge, to any person obtaining
  2. // a copy of this software and associated documentation files (the
  3. // "Software"), to deal in the Software without restriction, including
  4. // without limitation the rights to use, copy, modify, merge, publish,
  5. // distribute, sublicense, and/or sell copies of the Software, and to
  6. // permit persons to whom the Software is furnished to do so, subject to
  7. // the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be
  10. // included in all copies or substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  13. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  14. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  15. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  16. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  17. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  18. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. //
  20. // Copyright (C) 2005, 2006 Novell, Inc (http://www.novell.com)
  21. //
  22. #if CONFIGURATION_DEP && !TARGET_JVM
  23. extern alias PrebuiltSystem;
  24. using NameValueCollection = PrebuiltSystem.System.Collections.Specialized.NameValueCollection;
  25. #endif
  26. #if CONFIGURATION_DEP
  27. using System.IO;
  28. using System.Xml.Serialization;
  29. #endif
  30. using System.ComponentModel;
  31. using System.Reflection;
  32. using System.Threading;
  33. using System.Collections.Specialized;
  34. namespace System.Configuration {
  35. public abstract class ApplicationSettingsBase : SettingsBase, INotifyPropertyChanged
  36. {
  37. protected ApplicationSettingsBase ()
  38. {
  39. Initialize (Context, Properties, Providers);
  40. }
  41. protected ApplicationSettingsBase (IComponent owner)
  42. : this (owner, String.Empty)
  43. {
  44. }
  45. protected ApplicationSettingsBase (string settingsKey)
  46. {
  47. this.settingsKey = settingsKey;
  48. Initialize (Context, Properties, Providers);
  49. }
  50. protected ApplicationSettingsBase (IComponent owner,
  51. string settingsKey)
  52. {
  53. if (owner == null)
  54. throw new ArgumentNullException ();
  55. #if (CONFIGURATION_DEP)
  56. providerService = (ISettingsProviderService)owner.Site.GetService(typeof (ISettingsProviderService));
  57. #endif
  58. this.settingsKey = settingsKey;
  59. Initialize (Context, Properties, Providers);
  60. }
  61. public event PropertyChangedEventHandler PropertyChanged;
  62. public event SettingChangingEventHandler SettingChanging;
  63. public event SettingsLoadedEventHandler SettingsLoaded;
  64. public event SettingsSavingEventHandler SettingsSaving;
  65. public object GetPreviousVersion (string propertyName)
  66. {
  67. throw new NotImplementedException ();
  68. }
  69. public void Reload ()
  70. {
  71. #if (CONFIGURATION_DEP)
  72. foreach (SettingsProvider provider in Providers) {
  73. // IApplicationSettingsProvider iasp = provider as IApplicationSettingsProvider;
  74. CacheValuesByProvider(provider);
  75. }
  76. #endif
  77. }
  78. public void Reset()
  79. {
  80. #if (CONFIGURATION_DEP)
  81. Reload ();
  82. foreach (SettingsPropertyValue pv in PropertyValues)
  83. pv.PropertyValue = pv.Reset();
  84. #endif
  85. }
  86. public override void Save()
  87. {
  88. #if (CONFIGURATION_DEP)
  89. Context.CurrentSettings = this;
  90. /* ew.. this needs to be more efficient */
  91. foreach (SettingsProvider provider in Providers) {
  92. SettingsPropertyValueCollection cache = new SettingsPropertyValueCollection ();
  93. foreach (SettingsPropertyValue val in PropertyValues) {
  94. if (val.Property.Provider == provider)
  95. cache.Add (val);
  96. }
  97. if (cache.Count > 0)
  98. provider.SetPropertyValues (Context, cache);
  99. }
  100. Context.CurrentSettings = null;
  101. #endif
  102. }
  103. public virtual void Upgrade()
  104. {
  105. }
  106. protected virtual void OnPropertyChanged (object sender,
  107. PropertyChangedEventArgs e)
  108. {
  109. if (PropertyChanged != null)
  110. PropertyChanged (sender, e);
  111. }
  112. protected virtual void OnSettingChanging (object sender,
  113. SettingChangingEventArgs e)
  114. {
  115. if (SettingChanging != null)
  116. SettingChanging (sender, e);
  117. }
  118. protected virtual void OnSettingsLoaded (object sender,
  119. SettingsLoadedEventArgs e)
  120. {
  121. if (SettingsLoaded != null)
  122. SettingsLoaded (sender, e);
  123. }
  124. protected virtual void OnSettingsSaving (object sender,
  125. CancelEventArgs e)
  126. {
  127. if (SettingsSaving != null)
  128. SettingsSaving (sender, e);
  129. }
  130. [Browsable (false)]
  131. public override SettingsContext Context {
  132. get {
  133. if (IsSynchronized)
  134. Monitor.Enter (this);
  135. try {
  136. if (context == null) {
  137. context = new SettingsContext ();
  138. context ["SettingsKey"] = "";
  139. Type type = GetType ();
  140. context ["GroupName"] = type.FullName;
  141. context ["SettingsClassType"] = type;
  142. }
  143. return context;
  144. } finally {
  145. if (IsSynchronized)
  146. Monitor.Exit (this);
  147. }
  148. }
  149. }
  150. void CacheValuesByProvider (SettingsProvider provider)
  151. {
  152. SettingsPropertyCollection col = new SettingsPropertyCollection ();
  153. foreach (SettingsProperty p in Properties) {
  154. if (p.Provider == provider)
  155. col.Add (p);
  156. }
  157. if (col.Count > 0) {
  158. SettingsPropertyValueCollection vals = provider.GetPropertyValues (Context, col);
  159. foreach (SettingsPropertyValue prop in vals) {
  160. if (PropertyValues [prop.Name] != null)
  161. PropertyValues [prop.Name].PropertyValue = prop.PropertyValue;
  162. else
  163. PropertyValues.Add (prop);
  164. }
  165. }
  166. OnSettingsLoaded (this, new SettingsLoadedEventArgs (provider));
  167. }
  168. void InitializeSettings (SettingsPropertyCollection settings)
  169. {
  170. }
  171. object GetPropertyValue (string propertyName)
  172. {
  173. SettingsProperty prop = Properties [ propertyName ];
  174. if (prop == null)
  175. throw new SettingsPropertyNotFoundException (propertyName);
  176. if (propertyValues == null)
  177. InitializeSettings (Properties);
  178. if (PropertyValues [ propertyName ] == null)
  179. CacheValuesByProvider (prop.Provider);
  180. return PropertyValues [ propertyName ].PropertyValue;
  181. }
  182. [MonoTODO]
  183. public override object this [ string propertyName ] {
  184. get {
  185. if (IsSynchronized) {
  186. lock (this) {
  187. return GetPropertyValue (propertyName);
  188. }
  189. }
  190. return GetPropertyValue (propertyName);
  191. }
  192. set {
  193. SettingsProperty prop = Properties [ propertyName ];
  194. if (prop == null)
  195. throw new SettingsPropertyNotFoundException (propertyName);
  196. if (prop.IsReadOnly)
  197. throw new SettingsPropertyIsReadOnlyException (propertyName);
  198. /* XXX check the type of the property vs the type of @value */
  199. if (value != null &&
  200. !prop.PropertyType.IsAssignableFrom (value.GetType()))
  201. throw new SettingsPropertyWrongTypeException (propertyName);
  202. if (PropertyValues [ propertyName ] == null)
  203. CacheValuesByProvider (prop.Provider);
  204. SettingChangingEventArgs changing_args = new SettingChangingEventArgs (propertyName,
  205. GetType().FullName,
  206. settingsKey,
  207. value,
  208. false);
  209. OnSettingChanging (this, changing_args);
  210. if (changing_args.Cancel == false) {
  211. /* actually set the value */
  212. PropertyValues [ propertyName ].PropertyValue = value;
  213. /* then emit PropertyChanged */
  214. OnPropertyChanged (this, new PropertyChangedEventArgs (propertyName));
  215. }
  216. }
  217. }
  218. #if (CONFIGURATION_DEP)
  219. [Browsable (false)]
  220. public override SettingsPropertyCollection Properties {
  221. get {
  222. if (IsSynchronized)
  223. Monitor.Enter (this);
  224. try {
  225. if (properties == null) {
  226. SettingsProvider local_provider = null;
  227. properties = new SettingsPropertyCollection ();
  228. Type this_type = GetType();
  229. SettingsProviderAttribute[] provider_attrs = (SettingsProviderAttribute[])this_type.GetCustomAttributes (typeof (SettingsProviderAttribute), false);;
  230. if (provider_attrs != null && provider_attrs.Length != 0) {
  231. Type provider_type = Type.GetType (provider_attrs[0].ProviderTypeName);
  232. SettingsProvider provider = (SettingsProvider) Activator.CreateInstance (provider_type);
  233. provider.Initialize (null, null);
  234. if (provider != null && Providers [provider.Name] == null) {
  235. Providers.Add (provider);
  236. local_provider = provider;
  237. }
  238. }
  239. PropertyInfo[] type_props = this_type.GetProperties ();
  240. foreach (PropertyInfo prop in type_props) { // only public properties
  241. SettingAttribute[] setting_attrs = (SettingAttribute[])prop.GetCustomAttributes (typeof (SettingAttribute), false);
  242. if (setting_attrs == null || setting_attrs.Length == 0)
  243. continue;
  244. CreateSettingsProperty (prop, properties, ref local_provider);
  245. }
  246. }
  247. return properties;
  248. } finally {
  249. if (IsSynchronized)
  250. Monitor.Exit (this);
  251. }
  252. }
  253. }
  254. void CreateSettingsProperty (PropertyInfo prop, SettingsPropertyCollection properties, ref SettingsProvider local_provider)
  255. {
  256. SettingsAttributeDictionary dict = new SettingsAttributeDictionary ();
  257. SettingsProvider provider = null;
  258. object defaultValue = null;
  259. SettingsSerializeAs serializeAs = SettingsSerializeAs.String;
  260. bool explicitSerializeAs = false;
  261. foreach (Attribute a in prop.GetCustomAttributes (false)) {
  262. /* the attributes we handle natively here */
  263. if (a is SettingsProviderAttribute) {
  264. Type provider_type = Type.GetType (((SettingsProviderAttribute)a).ProviderTypeName);
  265. provider = (SettingsProvider) Activator.CreateInstance (provider_type);
  266. provider.Initialize (null, null);
  267. }
  268. else if (a is DefaultSettingValueAttribute) {
  269. defaultValue = ((DefaultSettingValueAttribute)a).Value;
  270. }
  271. else if (a is SettingsSerializeAsAttribute) {
  272. serializeAs = ((SettingsSerializeAsAttribute)a).SerializeAs;
  273. explicitSerializeAs = true;
  274. }
  275. else if (a is ApplicationScopedSettingAttribute ||
  276. a is UserScopedSettingAttribute) {
  277. dict.Add (a.GetType(), a);
  278. }
  279. else {
  280. dict.Add (a.GetType(), a);
  281. }
  282. }
  283. if (!explicitSerializeAs) {
  284. // DefaultValue is a string and if we can't convert from string to the
  285. // property type then the only other option left is for the string to
  286. // be XML.
  287. //
  288. TypeConverter converter = TypeDescriptor.GetConverter (prop.PropertyType);
  289. if (converter != null &&
  290. (!converter.CanConvertFrom (typeof (string)) ||
  291. !converter.CanConvertTo (typeof (string))))
  292. serializeAs = SettingsSerializeAs.Xml;
  293. }
  294. SettingsProperty setting =
  295. new SettingsProperty (prop.Name, prop.PropertyType, provider, false /* XXX */,
  296. defaultValue /* XXX always a string? */, serializeAs, dict,
  297. false, false);
  298. if (providerService != null)
  299. setting.Provider = providerService.GetSettingsProvider (setting);
  300. if (provider == null) {
  301. if (local_provider == null) {
  302. local_provider = new LocalFileSettingsProvider () as SettingsProvider;
  303. local_provider.Initialize (null, null);
  304. }
  305. setting.Provider = local_provider;
  306. // .NET ends up to set this to providers.
  307. provider = local_provider;
  308. }
  309. if (provider != null) {
  310. /* make sure we're using the same instance of a
  311. given provider across multiple properties */
  312. SettingsProvider p = Providers[provider.Name];
  313. if (p != null)
  314. setting.Provider = p;
  315. }
  316. properties.Add (setting);
  317. if (setting.Provider != null && Providers [setting.Provider.Name] == null)
  318. Providers.Add (setting.Provider);
  319. }
  320. #endif
  321. [Browsable (false)]
  322. public override SettingsPropertyValueCollection PropertyValues {
  323. get {
  324. if (IsSynchronized)
  325. Monitor.Enter (this);
  326. try {
  327. if (propertyValues == null) {
  328. propertyValues = new SettingsPropertyValueCollection ();
  329. }
  330. return propertyValues;
  331. } finally {
  332. if (IsSynchronized)
  333. Monitor.Exit (this);
  334. }
  335. }
  336. }
  337. [Browsable (false)]
  338. public override SettingsProviderCollection Providers {
  339. get {
  340. if (IsSynchronized)
  341. Monitor.Enter (this);
  342. try {
  343. if (providers == null)
  344. providers = new SettingsProviderCollection ();
  345. return providers;
  346. } finally {
  347. if (IsSynchronized)
  348. Monitor.Exit (this);
  349. }
  350. }
  351. }
  352. [Browsable (false)]
  353. public string SettingsKey {
  354. get {
  355. return settingsKey;
  356. }
  357. set {
  358. settingsKey = value;
  359. }
  360. }
  361. string settingsKey;
  362. SettingsContext context;
  363. #if (CONFIGURATION_DEP)
  364. SettingsPropertyCollection properties;
  365. ISettingsProviderService providerService;
  366. #endif
  367. SettingsPropertyValueCollection propertyValues;
  368. SettingsProviderCollection providers;
  369. }
  370. }