Actions persistence working.
1.1 --- a/Server/ConsumerElectronicControl.cs Sat Jul 23 19:22:56 2016 +0200
1.2 +++ b/Server/ConsumerElectronicControl.cs Sun Jul 24 13:30:08 2016 +0200
1.3 @@ -93,7 +93,7 @@
1.4
1.5 private void OnMonitorPowerOn()
1.6 {
1.7 - EventActionManager.Current.GetEvent<EventMonitorPowerOn>().Trigger();
1.8 + ManagerEventAction.Current.GetEvent<EventMonitorPowerOn>().Trigger();
1.9
1.10 Console.WriteLine("OnMonitorPowerOn");
1.11
1.12 @@ -112,7 +112,7 @@
1.13
1.14 private void OnMonitorPowerOff()
1.15 {
1.16 - EventActionManager.Current.GetEvent<EventMonitorPowerOff>().Trigger();
1.17 + ManagerEventAction.Current.GetEvent<EventMonitorPowerOff>().Trigger();
1.18
1.19 Console.WriteLine("OnMonitorPowerOff");
1.20
2.1 --- a/Server/DisplaySettings.cs Sat Jul 23 19:22:56 2016 +0200
2.2 +++ b/Server/DisplaySettings.cs Sun Jul 24 13:30:08 2016 +0200
2.3 @@ -28,6 +28,7 @@
2.4 using System.Runtime.Serialization.Json;
2.5 using System.IO;
2.6 using System.Drawing;
2.7 +using SharpLib.Utils;
2.8
2.9 namespace SharpDisplayManager
2.10 {
2.11 @@ -114,10 +115,12 @@
2.12 /// <summary>
2.13 /// Contain settings for each of our display type.
2.14 /// </summary>
2.15 - [TypeConverter(typeof(DisplaySettingsConverter))]
2.16 + [TypeConverter(typeof(TypeConverterJson<DisplaysSettings>))]
2.17 [DataContract]
2.18 public class DisplaysSettings
2.19 {
2.20 + private List<DisplaySettings> iDisplays;
2.21 +
2.22 public DisplaysSettings()
2.23 {
2.24 Init();
2.25 @@ -125,9 +128,9 @@
2.26
2.27 public void Init()
2.28 {
2.29 - if (Displays == null)
2.30 + if (iDisplays == null)
2.31 {
2.32 - Displays = new List<DisplaySettings>();
2.33 + iDisplays = new List<DisplaySettings>();
2.34 }
2.35 }
2.36
2.37 @@ -135,50 +138,9 @@
2.38 //public int CurrentSettingsIndex { get; set; }
2.39
2.40 [DataMember]
2.41 - public List<DisplaySettings> Displays { get; set; }
2.42 + public List<DisplaySettings> Displays { get { Init(); return iDisplays; } private set { iDisplays = value; } }
2.43
2.44 - public override string ToString()
2.45 - {
2.46 - //Save settings into JSON string
2.47 - MemoryStream stream = new MemoryStream();
2.48 - DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(DisplaysSettings));
2.49 - ser.WriteObject(stream, this);
2.50 - // convert stream to string
2.51 - stream.Position = 0;
2.52 - StreamReader reader = new StreamReader(stream);
2.53 - string text = reader.ReadToEnd();
2.54 - return text;
2.55 - }
2.56 +
2.57 }
2.58 -
2.59 - public class DisplaySettingsConverter : TypeConverter
2.60 - {
2.61 - public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
2.62 - {
2.63 - if (sourceType == typeof(string))
2.64 - return true;
2.65 - else
2.66 - return base.CanConvertFrom(context, sourceType);
2.67 - }
2.68 -
2.69 - public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
2.70 - {
2.71 - string stringValue = value as string;
2.72 - if (stringValue != null)
2.73 - {
2.74 - //Load settings form JSON string
2.75 - byte[] byteArray = Encoding.UTF8.GetBytes(stringValue);
2.76 - MemoryStream stream = new MemoryStream(byteArray);
2.77 - DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(DisplaysSettings));
2.78 - DisplaysSettings settings = (DisplaysSettings)ser.ReadObject(stream);
2.79 - settings.Init();
2.80 - return settings;
2.81 - }
2.82 - else
2.83 - return base.ConvertFrom(context, culture, value);
2.84 - }
2.85 - };
2.86 -
2.87 -
2.88 }
2.89
3.1 --- a/Server/FormEditAction.cs Sat Jul 23 19:22:56 2016 +0200
3.2 +++ b/Server/FormEditAction.cs Sun Jul 24 13:30:08 2016 +0200
3.3 @@ -23,9 +23,9 @@
3.4 private void FormEditAction_Load(object sender, EventArgs e)
3.5 {
3.6 //Populate registered actions
3.7 - foreach (string key in EventActionManager.Current.ActionTypes.Keys)
3.8 + foreach (string key in ManagerEventAction.Current.ActionTypes.Keys)
3.9 {
3.10 - Type t = EventActionManager.Current.ActionTypes[key];
3.11 + Type t = ManagerEventAction.Current.ActionTypes[key];
3.12 comboBoxActionType.Items.Add(t);
3.13 }
3.14
4.1 --- a/Server/MainForm.cs Sat Jul 23 19:22:56 2016 +0200
4.2 +++ b/Server/MainForm.cs Sun Jul 24 13:30:08 2016 +0200
4.3 @@ -70,7 +70,7 @@
4.4 [System.ComponentModel.DesignerCategory("Form")]
4.5 public partial class MainForm : MainFormHid, IMMNotificationClient
4.6 {
4.7 - public EventActionManager iManager = new EventActionManager();
4.8 + //public ManagerEventAction iManager = new ManagerEventAction();
4.9 DateTime LastTickTime;
4.10 Display iDisplay;
4.11 System.Drawing.Bitmap iBmp;
4.12 @@ -131,7 +131,19 @@
4.13
4.14 public MainForm()
4.15 {
4.16 - EventActionManager.Current = iManager;
4.17 + ManagerEventAction.Current = Properties.Settings.Default.Actions;
4.18 + if (ManagerEventAction.Current == null)
4.19 + {
4.20 + //No actions in our settings yet
4.21 + ManagerEventAction.Current = new ManagerEventAction();
4.22 + Properties.Settings.Default.Actions = ManagerEventAction.Current;
4.23 + }
4.24 + else
4.25 + {
4.26 + //We loaded actions from our settings
4.27 + //We need to hook them with corresponding events
4.28 + ManagerEventAction.Current.Init();
4.29 + }
4.30 iSkipFrameRendering = false;
4.31 iClosing = false;
4.32 iCurrentClientSessionId = "";
4.33 @@ -295,9 +307,9 @@
4.34 //Reset our tree
4.35 iTreeViewEvents.Nodes.Clear();
4.36 //Populate registered events
4.37 - foreach (string key in EventActionManager.Current.Events.Keys)
4.38 + foreach (string key in ManagerEventAction.Current.Events.Keys)
4.39 {
4.40 - Event e = EventActionManager.Current.Events[key];
4.41 + Event e = ManagerEventAction.Current.Events[key];
4.42 TreeNode eventNode = iTreeViewEvents.Nodes.Add(key,e.Name);
4.43 eventNode.Tag = e;
4.44 eventNode.Nodes.Add(key + ".Description", e.Description);
4.45 @@ -2654,8 +2666,13 @@
4.46
4.47 private void buttonAddAction_Click(object sender, EventArgs e)
4.48 {
4.49 - Event ear = (Event)iTreeViewEvents.SelectedNode.Tag;
4.50 - if (ear == null)
4.51 + if (iTreeViewEvents.SelectedNode==null)
4.52 + {
4.53 + return;
4.54 + }
4.55 +
4.56 + Event earEvent = (Event)iTreeViewEvents.SelectedNode.Tag;
4.57 + if (earEvent == null)
4.58 {
4.59 //Must select event node
4.60 return;
4.61 @@ -2665,7 +2682,9 @@
4.62 DialogResult res = CodeProject.Dialog.DlgBox.ShowDialog(ea);
4.63 if (res == DialogResult.OK)
4.64 {
4.65 - ear.Actions.Add(ea.Action);
4.66 + earEvent.Actions.Add(ea.Action);
4.67 + Properties.Settings.Default.Actions = ManagerEventAction.Current;
4.68 + Properties.Settings.Default.Save();
4.69 SetupEvents();
4.70 }
4.71 }
5.1 --- a/Server/Properties/Settings.Designer.cs Sat Jul 23 19:22:56 2016 +0200
5.2 +++ b/Server/Properties/Settings.Designer.cs Sun Jul 24 13:30:08 2016 +0200
5.3 @@ -189,5 +189,16 @@
5.4 this["CecReconnectToPowerTv"] = value;
5.5 }
5.6 }
5.7 +
5.8 + [global::System.Configuration.UserScopedSettingAttribute()]
5.9 + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
5.10 + public global::SharpLib.Ear.ManagerEventAction Actions {
5.11 + get {
5.12 + return ((global::SharpLib.Ear.ManagerEventAction)(this["Actions"]));
5.13 + }
5.14 + set {
5.15 + this["Actions"] = value;
5.16 + }
5.17 + }
5.18 }
5.19 }
6.1 --- a/Server/Properties/Settings.settings Sat Jul 23 19:22:56 2016 +0200
6.2 +++ b/Server/Properties/Settings.settings Sun Jul 24 13:30:08 2016 +0200
6.3 @@ -44,5 +44,8 @@
6.4 <Setting Name="CecReconnectToPowerTv" Type="System.Boolean" Scope="User">
6.5 <Value Profile="(Default)">False</Value>
6.6 </Setting>
6.7 + <Setting Name="Actions" Type="SharpLib.Ear.ManagerEventAction" Scope="User">
6.8 + <Value Profile="(Default)" />
6.9 + </Setting>
6.10 </Settings>
6.11 </SettingsFile>
6.12 \ No newline at end of file
7.1 --- a/Server/SharpDisplayManager.csproj Sat Jul 23 19:22:56 2016 +0200
7.2 +++ b/Server/SharpDisplayManager.csproj Sun Jul 24 13:30:08 2016 +0200
7.3 @@ -34,7 +34,7 @@
7.4 <WebPage>index.htm</WebPage>
7.5 <OpenBrowserOnPublish>false</OpenBrowserOnPublish>
7.6 <ApplicationRevision>0</ApplicationRevision>
7.7 - <ApplicationVersion>0.9.3.0</ApplicationVersion>
7.8 + <ApplicationVersion>0.9.4.0</ApplicationVersion>
7.9 <UseApplicationTrust>false</UseApplicationTrust>
7.10 <CreateDesktopShortcut>true</CreateDesktopShortcut>
7.11 <PublishWizardCompleted>true</PublishWizardCompleted>
7.12 @@ -221,7 +221,9 @@
7.13 <DependentUpon>Resources.resx</DependentUpon>
7.14 <DesignTime>True</DesignTime>
7.15 </Compile>
7.16 - <None Include="App.config" />
7.17 + <None Include="App.config">
7.18 + <SubType>Designer</SubType>
7.19 + </None>
7.20 <None Include="app.manifest" />
7.21 <None Include="packages.config" />
7.22 <None Include="Properties\Settings.settings">
8.1 --- a/SharpLibEar/Action.cs Sat Jul 23 19:22:56 2016 +0200
8.2 +++ b/SharpLibEar/Action.cs Sun Jul 24 13:30:08 2016 +0200
8.3 @@ -2,12 +2,14 @@
8.4
8.5
8.6 using System;
8.7 +using System.Collections.Generic;
8.8 using System.Runtime.Serialization;
8.9 using System.Threading;
8.10
8.11 namespace SharpLib.Ear
8.12 {
8.13 [DataContract]
8.14 + [KnownType("DerivedTypes")]
8.15 public abstract class Action: IComparable
8.16 {
8.17 public abstract void Execute();
8.18 @@ -23,6 +25,12 @@
8.19 //Sort by action name
8.20 return Utils.Reflection.GetAttribute<AttributeAction>(GetType()).Name.CompareTo(obj.GetType());
8.21 }
8.22 +
8.23 + private static IEnumerable<Type> DerivedTypes()
8.24 + {
8.25 + return SharpLib.Utils.Reflection.GetDerivedTypes<Action>();
8.26 + }
8.27 +
8.28 }
8.29
8.30
9.1 --- a/SharpLibEar/ActionSleep.cs Sat Jul 23 19:22:56 2016 +0200
9.2 +++ b/SharpLibEar/ActionSleep.cs Sun Jul 24 13:30:08 2016 +0200
9.3 @@ -13,6 +13,7 @@
9.4 [AttributeAction(Id = "Thread.Sleep", Name = "Sleep", Description = "Have the current thread sleep for the specified amount of milliseconds.")]
9.5 public class ActionSleep : Action
9.6 {
9.7 + [DataMember]
9.8 private readonly int iMillisecondsTimeout;
9.9
9.10 public ActionSleep()
10.1 --- a/SharpLibEar/Event.cs Sat Jul 23 19:22:56 2016 +0200
10.2 +++ b/SharpLibEar/Event.cs Sun Jul 24 13:30:08 2016 +0200
10.3 @@ -10,10 +10,7 @@
10.4 [DataContract]
10.5 public abstract class MEvent
10.6 {
10.7 - [DataMember]
10.8 public string Name { get; protected set; }
10.9 -
10.10 - [DataMember]
10.11 public string Description { get; protected set; }
10.12
10.13 public abstract void Trigger();
10.14 @@ -22,11 +19,12 @@
10.15 [DataContract]
10.16 public abstract class Event : MEvent
10.17 {
10.18 - public List<Action> Actions;
10.19 + [DataMember]
10.20 + public List<Action> Actions = new List<Action>();
10.21
10.22 protected Event()
10.23 {
10.24 - Actions = new List<Action>();
10.25 +
10.26 }
10.27
10.28 public override void Trigger()
11.1 --- a/SharpLibEar/EventActionManager.cs Sat Jul 23 19:22:56 2016 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,31 +0,0 @@
11.4 -//
11.5 -
11.6 -
11.7 -using System;
11.8 -using System.Collections.Generic;
11.9 -using System.Linq;
11.10 -using System.Reflection;
11.11 -using System.Runtime.Serialization;
11.12 -
11.13 -namespace SharpLib.Ear
11.14 -{
11.15 - [DataContract]
11.16 - public class EventActionManager
11.17 - {
11.18 - public static EventActionManager Current = null;
11.19 - public IDictionary<string, Type> ActionTypes;
11.20 - public readonly IDictionary<string, Event> Events;
11.21 -
11.22 - public EventActionManager()
11.23 - {
11.24 - ActionTypes = Utils.Reflection.GetConcreteClassesDerivedFromByName<Action>();
11.25 - Events = Utils.Reflection.GetConcreteClassesInstanceDerivedFromByName<Event>();
11.26 - }
11.27 -
11.28 - public Event GetEvent<T>() where T : class
11.29 - {
11.30 - return Events[typeof(T).Name];
11.31 - }
11.32 -
11.33 - }
11.34 -}
11.35 \ No newline at end of file
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/SharpLibEar/ManagerEventAction.cs Sun Jul 24 13:30:08 2016 +0200
12.3 @@ -0,0 +1,70 @@
12.4 +//
12.5 +
12.6 +
12.7 +using System;
12.8 +using System.Collections.Generic;
12.9 +using System.ComponentModel;
12.10 +using System.Linq;
12.11 +using System.Reflection;
12.12 +using System.Runtime.Serialization;
12.13 +using SharpLib.Utils;
12.14 +
12.15 +namespace SharpLib.Ear
12.16 +{
12.17 + [TypeConverter(typeof(TypeConverterJson<ManagerEventAction>))]
12.18 + [DataContract]
12.19 + public class ManagerEventAction
12.20 + {
12.21 + public static ManagerEventAction Current = null;
12.22 + public IDictionary<string, Type> ActionTypes;
12.23 + public IDictionary<string, Event> Events;
12.24 + [DataMember]
12.25 + public Dictionary<string, List<Action>> ActionsByEvents = new Dictionary<string, List<Action>>();
12.26 +
12.27 +
12.28 + public ManagerEventAction()
12.29 + {
12.30 + Init();
12.31 + }
12.32 +
12.33 + /// <summary>
12.34 + ///
12.35 + /// </summary>
12.36 + public void Init()
12.37 + {
12.38 + //Create our list of supported actions
12.39 + ActionTypes = Utils.Reflection.GetConcreteClassesDerivedFromByName<Action>();
12.40 + //Create our list or support events
12.41 + Events = Utils.Reflection.GetConcreteClassesInstanceDerivedFromByName<Event>();
12.42 +
12.43 + if (ActionsByEvents == null)
12.44 + {
12.45 +
12.46 + ActionsByEvents = new Dictionary<string, List<Action>>();
12.47 + }
12.48 +
12.49 + //Hook in loaded actions with corresponding events
12.50 + foreach (string key in Events.Keys)
12.51 + {
12.52 + Event e = Events[key];
12.53 + if (ActionsByEvents.ContainsKey(key))
12.54 + {
12.55 + //We have actions for that event, hook them in then
12.56 + e.Actions = ActionsByEvents[key];
12.57 + }
12.58 + else
12.59 + {
12.60 + //We do not have actions for that event yet, create empty action list
12.61 + e.Actions = new List<Action>();
12.62 + ActionsByEvents[key] = e.Actions;
12.63 + }
12.64 + }
12.65 + }
12.66 +
12.67 + public Event GetEvent<T>() where T : class
12.68 + {
12.69 + return Events[typeof(T).Name];
12.70 + }
12.71 +
12.72 + }
12.73 +}
12.74 \ No newline at end of file
13.1 --- a/SharpLibEar/SharpLibEar.csproj Sat Jul 23 19:22:56 2016 +0200
13.2 +++ b/SharpLibEar/SharpLibEar.csproj Sun Jul 24 13:30:08 2016 +0200
13.3 @@ -7,7 +7,7 @@
13.4 <ProjectGuid>{84A9ED37-E6EA-4CBD-B995-B713F46EAAB0}</ProjectGuid>
13.5 <OutputType>Library</OutputType>
13.6 <AppDesignerFolder>Properties</AppDesignerFolder>
13.7 - <RootNamespace>SharpLibEar</RootNamespace>
13.8 + <RootNamespace>SharpLib.Ear</RootNamespace>
13.9 <AssemblyName>SharpLibEar</AssemblyName>
13.10 <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
13.11 <FileAlignment>512</FileAlignment>
13.12 @@ -49,7 +49,7 @@
13.13 <Compile Include="Event.cs" />
13.14 <Compile Include="EventMonitorPowerOff.cs" />
13.15 <Compile Include="EventMonitorPowerOn.cs" />
13.16 - <Compile Include="EventActionManager.cs" />
13.17 + <Compile Include="ManagerEventAction.cs" />
13.18 <Compile Include="Properties\AssemblyInfo.cs" />
13.19 </ItemGroup>
13.20 <ItemGroup>
14.1 --- a/SharpLibUtils/Reflection.cs Sat Jul 23 19:22:56 2016 +0200
14.2 +++ b/SharpLibUtils/Reflection.cs Sun Jul 24 13:30:08 2016 +0200
14.3 @@ -113,6 +113,21 @@
14.4 return null;
14.5 }
14.6
14.7 + /// <summary>
14.8 + ///
14.9 + /// </summary>
14.10 + /// <param name="baseType"></param>
14.11 + /// <param name="assembly"></param>
14.12 + /// <returns></returns>
14.13 + public static IEnumerable<Type> GetDerivedTypes<T>() where T: class
14.14 + {
14.15 + var types = from t in Assembly.GetAssembly(typeof(T)).GetTypes()
14.16 + where t.IsSubclassOf(typeof(T))
14.17 + select t;
14.18 +
14.19 + return types;
14.20 + }
14.21 +
14.22 }
14.23
14.24 }
15.1 --- a/SharpLibUtils/SharpLibUtils.csproj Sat Jul 23 19:22:56 2016 +0200
15.2 +++ b/SharpLibUtils/SharpLibUtils.csproj Sun Jul 24 13:30:08 2016 +0200
15.3 @@ -7,7 +7,7 @@
15.4 <ProjectGuid>{AE897704-461D-4018-8336-2517988BF7AD}</ProjectGuid>
15.5 <OutputType>Library</OutputType>
15.6 <AppDesignerFolder>Properties</AppDesignerFolder>
15.7 - <RootNamespace>SharpLibUtils</RootNamespace>
15.8 + <RootNamespace>SharpLib.Utils</RootNamespace>
15.9 <AssemblyName>SharpLibUtils</AssemblyName>
15.10 <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
15.11 <FileAlignment>512</FileAlignment>
15.12 @@ -32,6 +32,7 @@
15.13 <ItemGroup>
15.14 <Reference Include="System" />
15.15 <Reference Include="System.Core" />
15.16 + <Reference Include="System.Runtime.Serialization" />
15.17 <Reference Include="System.Xml.Linq" />
15.18 <Reference Include="System.Data.DataSetExtensions" />
15.19 <Reference Include="Microsoft.CSharp" />
15.20 @@ -42,6 +43,7 @@
15.21 <ItemGroup>
15.22 <Compile Include="Properties\AssemblyInfo.cs" />
15.23 <Compile Include="Reflection.cs" />
15.24 + <Compile Include="TypeConverterJson.cs" />
15.25 </ItemGroup>
15.26 <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
15.27 <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/SharpLibUtils/TypeConverterJson.cs Sun Jul 24 13:30:08 2016 +0200
16.3 @@ -0,0 +1,92 @@
16.4 +using System;
16.5 +using System.Collections.Generic;
16.6 +using System.ComponentModel;
16.7 +using System.IO;
16.8 +using System.Linq;
16.9 +using System.Text;
16.10 +using System.Threading.Tasks;
16.11 +using System.Runtime.Serialization;
16.12 +using System.Runtime.Serialization.Json;
16.13 +using System.Globalization;
16.14 +
16.15 +namespace SharpLib.Utils
16.16 +{
16.17 + /// <summary>
16.18 + /// Allow serialization into JSON.
16.19 + /// Most useful to be able to save complex settings for instance.
16.20 + /// Usage:
16.21 + /// ...
16.22 + /// [TypeConverter(typeof(TypeConverterJson<PersistantObject>))]
16.23 + /// [DataContract]
16.24 + /// public class PersistantObject
16.25 + /// ...
16.26 + /// </summary>
16.27 + /// <typeparam name="T"></typeparam>
16.28 + public class TypeConverterJson<T> : TypeConverter where T : class
16.29 + {
16.30 + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
16.31 + {
16.32 + if (sourceType == typeof(string))
16.33 + return true;
16.34 + else
16.35 + return base.CanConvertFrom(context, sourceType);
16.36 + }
16.37 +
16.38 + /// <summary>
16.39 + ///
16.40 + /// </summary>
16.41 + /// <param name="context"></param>
16.42 + /// <param name="culture"></param>
16.43 + /// <param name="value"></param>
16.44 + /// <returns></returns>
16.45 + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
16.46 + {
16.47 + string stringValue = value as string;
16.48 + if (stringValue != null)
16.49 + {
16.50 + //Load object form JSON string
16.51 + byte[] byteArray = Encoding.UTF8.GetBytes(stringValue);
16.52 + MemoryStream stream = new MemoryStream(byteArray);
16.53 + DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings()
16.54 + {
16.55 + UseSimpleDictionaryFormat = true
16.56 + });
16.57 + T settings = (T)ser.ReadObject(stream);
16.58 + return settings;
16.59 + }
16.60 + else
16.61 + return base.ConvertFrom(context, culture, value);
16.62 + }
16.63 +
16.64 + /// <summary>
16.65 + ///
16.66 + /// </summary>
16.67 + /// <param name="context"></param>
16.68 + /// <param name="culture"></param>
16.69 + /// <param name="value"></param>
16.70 + /// <param name="destinationType"></param>
16.71 + /// <returns></returns>
16.72 + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
16.73 + {
16.74 + if (destinationType == typeof(string))
16.75 + {
16.76 + //Save settings into JSON string
16.77 + MemoryStream stream = new MemoryStream();
16.78 + DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T), new DataContractJsonSerializerSettings()
16.79 + {
16.80 + UseSimpleDictionaryFormat = true
16.81 + });
16.82 + ser.WriteObject(stream, value);
16.83 + // convert stream to string
16.84 + stream.Position = 0;
16.85 + StreamReader reader = new StreamReader(stream);
16.86 + string text = reader.ReadToEnd();
16.87 + return text;
16.88 + }
16.89 + else
16.90 + {
16.91 + return base.ConvertTo(context,culture,value,destinationType);
16.92 + }
16.93 + }
16.94 + }
16.95 +}
16.96 \ No newline at end of file