aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs22
-rw-r--r--Software/Visual_Studio/Tango.Core/Tango.Core.csproj7
-rw-r--r--Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs77
-rw-r--r--Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs156
-rw-r--r--Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs47
-rw-r--r--Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs87
-rw-r--r--Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs6
-rw-r--r--Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs66
-rw-r--r--Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj64
-rw-r--r--Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs161
-rw-r--r--Software/Visual_Studio/Tango.Serialization/packages.config5
-rw-r--r--Software/Visual_Studio/Tango.Settings/DataBase.cs19
-rw-r--r--Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs6
-rw-r--r--Software/Visual_Studio/Tango.Settings/SettingsCollection.cs24
-rw-r--r--Software/Visual_Studio/Tango.Settings/SettingsManager.cs145
-rw-r--r--Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj66
-rw-r--r--Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs3
-rw-r--r--Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj4
-rw-r--r--Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs5
-rw-r--r--Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs3
-rw-r--r--Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj4
-rw-r--r--Software/Visual_Studio/Tango.sln28
22 files changed, 1001 insertions, 4 deletions
diff --git a/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs
new file mode 100644
index 000000000..978b14f30
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Core/ExtensionMethods/ObjectExtensions.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Serialization;
+
+
+public static class ObjectExtensions
+{
+ public static T DeepClone<T>(this T obj) where T : class
+ {
+ XmlDataSerializer serializer = new XmlDataSerializer();
+ using (MemoryStream ms = new MemoryStream())
+ {
+ serializer.SerializeToStream(obj, ms);
+ ms.Position = 0;
+ return serializer.DeserializeFromStream<T>(ms);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj
index e2341ab62..80804f02e 100644
--- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj
+++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj
@@ -58,6 +58,7 @@
<Compile Include="ExtensionMethods\EnumExtensions.cs" />
<Compile Include="ExtensionMethods\IMessageExtensions.cs" />
<Compile Include="ExtensionMethods\IParameterizedExtensions.cs" />
+ <Compile Include="ExtensionMethods\ObjectExtensions.cs" />
<Compile Include="ExtensionMethods\StringExtensions.cs" />
<Compile Include="Helpers\AssemblyHelper.cs" />
<Compile Include="Helpers\PathHelper.cs" />
@@ -71,5 +72,11 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Tango.Serialization\Tango.Serialization.csproj">
+ <Project>{22f87980-e990-4686-be81-be63d562c4d5}</Project>
+ <Name>Tango.Serialization</Name>
+ </ProjectReference>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs
new file mode 100644
index 000000000..565854804
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/BinaryDataSerializer.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization.Formatters.Binary;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Serialization
+{
+ /// <summary>
+ /// Represents a data serializer for serializing data using binary formatter.
+ /// </summary>
+ public class BinaryDataSerializer : IDataSerializer
+ {
+ /// <summary>
+ /// Serialize object to a file.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="filePath">The full path to the file to write.</param>
+ public void SerializeToFile<T>(T obj, string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath,FileMode.Create))
+ {
+ SerializeToStream(obj, fs);
+ }
+ }
+
+ /// <summary>
+ /// Deserialize object from a file.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="filePath">The full path of the data file.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromFile<T>(string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Open))
+ {
+ return DeserializeFromStream<T>(fs);
+ }
+ }
+
+ /// <summary>
+ /// Serialize object to stream.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="st">The stream to write.</param>
+ public void SerializeToStream<T>(T obj, Stream st)
+ {
+ BinaryFormatter f = new BinaryFormatter();
+ f.Serialize(st, obj);
+ }
+
+ /// <summary>
+ /// Deserialize object from stream.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="st">Stream to read from.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromStream<T>(Stream st)
+ {
+ BinaryFormatter f = new BinaryFormatter();
+ return (T)f.Deserialize(st);
+ }
+
+ /// <summary>
+ /// Returns the serializer full name.
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return SerializationHelper.GetSerializerName(this);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs b/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs
new file mode 100644
index 000000000..e072827fe
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/CryptographyHelper.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Text;
+using System.Security.Cryptography;
+using System.IO;
+using System.Linq;
+using System.Security;
+using System.Runtime.InteropServices;
+
+namespace Tango.Serialization
+{
+ /// <summary>
+ /// Represents a helper class for encryption and decryption of plain text.
+ /// </summary>
+ internal static class CryptographyHelper
+ {
+ private static SecureString passkey;
+
+ /// <summary>
+ /// Initializes the <see cref="CryptographyHelper"/> class.
+ /// </summary>
+ static CryptographyHelper()
+ {
+ passkey = new SecureString();
+ passkey.AppendChar('S');
+ passkey.AppendChar('@');
+ passkey.AppendChar('Y');
+ passkey.AppendChar('!');
+ }
+
+ // This constant is used to determine the keysize of the encryption algorithm in bits.
+ // We divide this by 8 within the code below to get the equivalent number of bytes.
+ private const int Keysize = 256;
+
+ // This constant determines the number of iterations for the password bytes generation function.
+ private const int DerivationIterations = 1000;
+
+ /// <summary>
+ /// Encrypts the specified plain text.
+ /// </summary>
+ /// <param name="plainText">The plain text.</param>
+ /// <returns></returns>
+ public static string Encrypt(string plainText)
+ {
+ // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
+ // so that the same Salt and IV values can be used when decrypting.
+ var saltStringBytes = Generate256BitsOfRandomEntropy();
+ var ivStringBytes = Generate256BitsOfRandomEntropy();
+ var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
+ using (var password = new Rfc2898DeriveBytes(ConvertSecureStringToString(passkey), saltStringBytes, DerivationIterations))
+ {
+ var keyBytes = password.GetBytes(Keysize / 8);
+ using (var symmetricKey = new RijndaelManaged())
+ {
+ symmetricKey.BlockSize = 256;
+ symmetricKey.Mode = CipherMode.CBC;
+ symmetricKey.Padding = PaddingMode.PKCS7;
+ using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
+ {
+ using (var memoryStream = new MemoryStream())
+ {
+ using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
+ {
+ cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
+ cryptoStream.FlushFinalBlock();
+ // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
+ var cipherTextBytes = saltStringBytes;
+ cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
+ cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
+ memoryStream.Close();
+ cryptoStream.Close();
+ return Convert.ToBase64String(cipherTextBytes);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Decrypts the specified cipher text.
+ /// </summary>
+ /// <param name="cipherText">The cipher text.</param>
+ /// <returns></returns>
+ public static string Decrypt(string cipherText)
+ {
+ // Get the complete stream of bytes that represent:
+ // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
+ var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
+ // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
+ var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
+ // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
+ var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
+ // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
+ var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
+
+ using (var password = new Rfc2898DeriveBytes(ConvertSecureStringToString(passkey), saltStringBytes, DerivationIterations))
+ {
+ var keyBytes = password.GetBytes(Keysize / 8);
+ using (var symmetricKey = new RijndaelManaged())
+ {
+ symmetricKey.BlockSize = 256;
+ symmetricKey.Mode = CipherMode.CBC;
+ symmetricKey.Padding = PaddingMode.PKCS7;
+ using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
+ {
+ using (var memoryStream = new MemoryStream(cipherTextBytes))
+ {
+ using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
+ {
+ var plainTextBytes = new byte[cipherTextBytes.Length];
+ var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
+ memoryStream.Close();
+ cryptoStream.Close();
+ return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Generate256s the bits of random entropy.
+ /// </summary>
+ /// <returns></returns>
+ private static byte[] Generate256BitsOfRandomEntropy()
+ {
+ var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits.
+ using (var rngCsp = new RNGCryptoServiceProvider())
+ {
+ // Fill the array with cryptographically secure random bytes.
+ rngCsp.GetBytes(randomBytes);
+ }
+ return randomBytes;
+ }
+
+ /// <summary>
+ /// Converts the secure string to string.
+ /// </summary>
+ /// <param name="value">The value.</param>
+ /// <returns></returns>
+ private static String ConvertSecureStringToString(SecureString value)
+ {
+ IntPtr valuePtr = IntPtr.Zero;
+ try
+ {
+ valuePtr = Marshal.SecureStringToGlobalAllocUnicode(value);
+ return Marshal.PtrToStringUni(valuePtr);
+ }
+ finally
+ {
+ Marshal.ZeroFreeGlobalAllocUnicode(valuePtr);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs
new file mode 100644
index 000000000..93465967e
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/IDataSerializer.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Serialization
+{
+ /// <summary>
+ /// Represent an interface for creating a custom data serializer.
+ /// </summary>
+ public interface IDataSerializer
+ {
+ /// <summary>
+ /// Serialize object to a file.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="filePath">The full path to the file to write.</param>
+ void SerializeToFile<T>(T obj, String filePath);
+
+ /// <summary>
+ /// Deserialize object from a file.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="filePath">The full path of the data file.</param>
+ /// <returns>The resulting object.</returns>
+ T DeserializeFromFile<T>(String filePath);
+
+ /// <summary>
+ /// Serialize object to stream.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="st">The stream to write.</param>
+ void SerializeToStream<T>(T obj, Stream st);
+
+ /// <summary>
+ /// Deserialize object from stream.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="st">Stream to read from.</param>
+ /// <returns>The resulting object.</returns>
+ T DeserializeFromStream<T>(Stream st);
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs
new file mode 100644
index 000000000..674f68289
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/JsonDataSerializer.cs
@@ -0,0 +1,87 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Serialization
+{
+ /// <summary>
+ /// Represents a data serializer for serializing data using the light weight textual Json format.
+ /// </summary>
+ public class JsonDataSerializer : IDataSerializer
+ {
+
+ /// <summary>
+ /// Serialize object to a file.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="filePath">The full path to the file to write.</param>
+ public void SerializeToFile<T>(T obj, string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Create))
+ {
+ SerializeToStream<T>(obj, fs);
+ }
+ }
+
+ /// <summary>
+ /// Deserialize object from a file.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="filePath">The full path of the data file.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromFile<T>(string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Open))
+ {
+ return DeserializeFromStream<T>(fs);
+ }
+ }
+
+ /// <summary>
+ /// Serialize object to stream.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="st">The stream to write.</param>
+ public void SerializeToStream<T>(T obj, Stream st)
+ {
+ JsonSerializer serializer = new JsonSerializer();
+ using (StreamWriter streamReader = new StreamWriter(st))
+ {
+ serializer.Serialize(streamReader, obj);
+ }
+ }
+
+ /// <summary>
+ /// Deserialize object from stream.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="st">Stream to read from.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromStream<T>(Stream st)
+ {
+ JsonSerializer serializer = new JsonSerializer();
+ T data;
+ using (StreamReader streamReader = new StreamReader(st))
+ {
+ data = (T)serializer.Deserialize(streamReader, typeof(T));
+ }
+ return data;
+ }
+
+ /// <summary>
+ /// Returns the serializer full name.
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return SerializationHelper.GetSerializerName(this);
+ }
+
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..f3c038f0e
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/Properties/AssemblyInfo.cs
@@ -0,0 +1,6 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Tango - Serialization Components")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs b/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs
new file mode 100644
index 000000000..2d00c8621
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/SerializationHelper.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Serialization
+{
+ /// <summary>
+ /// Contains a collection of IDataSerializer related helper methods.
+ /// </summary>
+ public static class SerializationHelper
+ {
+ /// <summary>
+ /// Gets a list of all IDataSerializer implemented types.
+ /// </summary>
+ /// <returns></returns>
+ public static List<Type> GetSerializersTypes()
+ {
+ var type = typeof(IDataSerializer);
+ var serializers = System.Reflection.Assembly.GetAssembly(type).GetTypes().Where(x => type.IsAssignableFrom(x) && !x.IsInterface);
+ return serializers.ToList();
+ }
+
+ /// <summary>
+ /// Gets a list of all IDataSerializer implemented instances.
+ /// </summary>
+ /// <returns></returns>
+ public static List<IDataSerializer> GetSerializersInstances()
+ {
+ var types = GetSerializersTypes();
+
+ List<IDataSerializer> serializers = new List<IDataSerializer>();
+
+ foreach (var type in types)
+ {
+ var instance = Activator.CreateInstance(type) as IDataSerializer;
+ serializers.Add(instance);
+ }
+
+ return serializers;
+ }
+
+ /// <summary>
+ /// Returns a serializer instance by type name.
+ /// </summary>
+ /// <param name="name">Name of IDataSerializer type.</param>
+ /// <returns></returns>
+ public static IDataSerializer GetSerializerByName(String name)
+ {
+ var types = GetSerializersTypes();
+ var type = types.SingleOrDefault(x => x.Name == name);
+ return Activator.CreateInstance(type) as IDataSerializer;
+ }
+
+ /// <summary>
+ /// Returns the name of the specified IDataSerializer.
+ /// </summary>
+ /// <param name="serializer">The specified IDataSerializer.</param>
+ /// <returns></returns>
+ public static String GetSerializerName(IDataSerializer serializer)
+ {
+ return serializer.GetType().Name;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj b/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj
new file mode 100644
index 000000000..453d317f5
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/Tango.Serialization.csproj
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{22F87980-E990-4686-BE81-BE63D562C4D5}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Tango.Serialization</RootNamespace>
+ <AssemblyName>Tango.Serialization</AssemblyName>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="Google.Protobuf, Version=3.5.0.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+ <HintPath>..\packages\Google.Protobuf.3.5.0\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
+ <Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
+ <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="BinaryDataSerializer.cs" />
+ <Compile Include="CryptographyHelper.cs" />
+ <Compile Include="IDataSerializer.cs" />
+ <Compile Include="JsonDataSerializer.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SerializationHelper.cs" />
+ <Compile Include="XmlDataSerializer.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs b/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs
new file mode 100644
index 000000000..0453e9120
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/XmlDataSerializer.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Xml.Serialization;
+
+namespace Tango.Serialization
+{
+ /// <summary>
+ /// Represents a data serializer for serializing data using standard xml serializer.
+ /// </summary>
+ public class XmlDataSerializer : IDataSerializer
+ {
+
+ /// <summary>
+ /// Serialize object to a file.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="filePath">The full path to the file to write.</param>
+ public void SerializeToFile<T>(T obj, string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Create))
+ {
+ SerializeToStream<T>(obj, fs);
+ }
+ }
+
+ /// <summary>
+ /// Serialize object to encrypted file.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="filePath">The full path to the file to write.</param>
+ public void SerializeToEncryptedFile<T>(T obj, string filePath)
+ {
+ var plainText = SerializeToString(obj);
+ var cypherText = CryptographyHelper.Encrypt(plainText);
+ File.WriteAllText(filePath, cypherText);
+ }
+
+ /// <summary>
+ /// Serialize object to encrypted string.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ public String SerializeToEncryptedString<T>(T obj)
+ {
+ var plainText = SerializeToString(obj);
+ var cypherText = CryptographyHelper.Encrypt(plainText);
+ return cypherText;
+ }
+
+ /// <summary>
+ /// Deserialize object from encrypted file.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="filePath">The full path of the data file.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromEncryptedFile<T>(string filePath)
+ {
+ var cypherText = File.ReadAllText(filePath);
+ var plainText = CryptographyHelper.Decrypt(cypherText);
+ return DeserializeFromString<T>(plainText);
+ }
+
+ /// <summary>
+ /// Deserialize object from encrypted string.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromEncryptedString<T>(string encyptedString)
+ {
+ var plainText = CryptographyHelper.Decrypt(encyptedString);
+ return DeserializeFromString<T>(plainText);
+ }
+
+ /// <summary>
+ /// Deserialize object from a file.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="filePath">The full path of the data file.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromFile<T>(string filePath)
+ {
+ using (FileStream fs = new FileStream(filePath, FileMode.Open))
+ {
+ return DeserializeFromStream<T>(fs);
+ }
+ }
+
+
+ /// <summary>
+ /// Serialize object to stream.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <param name="st">The stream to write.</param>
+ public void SerializeToStream<T>(T obj, Stream st)
+ {
+ XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround.
+ f.Serialize(st, obj);
+ }
+
+ /// <summary>
+ /// Serialize object to string.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <returns></returns>
+ public String SerializeToString<T>(T obj)
+ {
+ XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround.
+
+ using (StringWriter textWriter = new StringWriter())
+ {
+ f.Serialize(textWriter, obj);
+ return textWriter.ToString();
+ }
+ }
+
+ /// <summary>
+ /// Deserialize object from stream.
+ /// </summary>
+ /// <typeparam name="T">Type of object to deserialize.</typeparam>
+ /// <param name="st">Stream to read from.</param>
+ /// <returns>The resulting object.</returns>
+ public T DeserializeFromStream<T>(Stream st)
+ {
+ XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround.
+ return (T)f.Deserialize(st);
+ }
+
+ /// <summary>
+ /// Deserialize object from string.
+ /// </summary>
+ /// <typeparam name="T">Type of specified object.</typeparam>
+ /// <param name="obj">The specified object.</param>
+ /// <returns></returns>
+ public T DeserializeFromString<T>(String str)
+ {
+ XmlSerializer f = XmlSerializer.FromTypes(new[] { typeof(T) })[0]; //Microsoft bug workaround.
+ using (TextReader reader = new StringReader(str))
+ {
+ return (T)f.Deserialize(reader);
+ }
+ }
+
+ /// <summary>
+ /// Returns the serializer full name.
+ /// </summary>
+ /// <returns></returns>
+ public override string ToString()
+ {
+ return SerializationHelper.GetSerializerName(this);
+ }
+
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Serialization/packages.config b/Software/Visual_Studio/Tango.Serialization/packages.config
new file mode 100644
index 000000000..dbb73d29f
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Serialization/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="Google.Protobuf" version="3.5.0" targetFramework="net46" />
+ <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net46" />
+</packages> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Settings/DataBase.cs b/Software/Visual_Studio/Tango.Settings/DataBase.cs
new file mode 100644
index 000000000..1a504d0ac
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Settings/DataBase.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.Settings
+{
+ [Serializable]
+ public class DataBase
+ {
+ public String SQLServerAddress { get; set; }
+
+ public DataBase()
+ {
+ SQLServerAddress = "localhost\\SQLEXPRESS";
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..d5b3aa0ae
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Settings/Properties/AssemblyInfo.cs
@@ -0,0 +1,6 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("Tango - Global Settings")]
+[assembly: ComVisible(false)] \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Settings/SettingsCollection.cs b/Software/Visual_Studio/Tango.Settings/SettingsCollection.cs
new file mode 100644
index 000000000..c6f98f187
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Settings/SettingsCollection.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Serialization;
+
+namespace Tango.Settings
+{
+ [Serializable]
+ public class SettingsCollection
+ {
+ public DataBase DataBase { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SettingsCollection"/> class.
+ /// </summary>
+ public SettingsCollection()
+ {
+ DataBase = new DataBase();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Settings/SettingsManager.cs b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs
new file mode 100644
index 000000000..8455cb91d
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Settings/SettingsManager.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Logging;
+using Tango.Serialization;
+
+namespace Tango.Settings
+{
+ /// <summary>
+ /// Represents a settings manager for loading and saving application settings.
+ /// </summary>
+ public static class SettingsManager
+ {
+ /// <summary>
+ /// Gets or sets a value indicating whether the settings manager is initialized.
+ /// </summary>
+ public static bool IsInitialized { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the default settings.
+ /// </summary>
+ /// <value>
+ /// The default.
+ /// </value>
+ public static SettingsCollection Default { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the default file path.
+ /// </summary>
+ /// <value>
+ /// The default file path.
+ /// </value>
+ public static String DefaultFilePath { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the default folder for application settings.
+ /// </summary>
+ public static String DefaultFolder { get; private set; }
+
+ /// <summary>
+ /// Saves application settings to XML file.
+ /// </summary>
+ /// <param name="filePath">The path to the XML file.</param>
+ /// <param name="stCollection">The instance of the SettingsCollection to save.</param>
+ public static void SaveToXML(String filePath, SettingsCollection stCollection)
+ {
+ LogManager.Log("Saving application configuration to " + "'" + filePath + "'");
+ XmlDataSerializer serializer = new XmlDataSerializer();
+ serializer.SerializeToFile<SettingsCollection>(stCollection, filePath);
+ }
+
+ /// <summary>
+ /// Loads application settings from XML file.
+ /// </summary>
+ /// <param name="filePath">The file path.</param>
+ /// <returns></returns>
+ public static SettingsCollection LoadFromXML(String filePath)
+ {
+ LogManager.Log("Loading application configuration from " + "'" + filePath + "'");
+ XmlDataSerializer serialier = new XmlDataSerializer();
+ return serialier.DeserializeFromFile<SettingsCollection>(filePath);
+ }
+
+ /// <summary>
+ /// Saves the default settings.
+ /// </summary>
+ public static void SaveDefaultSettings()
+ {
+ SaveToXML(DefaultFilePath, Default);
+ }
+
+ /// <summary>
+ /// Restores to default.
+ /// </summary>
+ public static void RestoreToDefault()
+ {
+ Default = new SettingsCollection();
+ SaveDefaultSettings();
+ }
+
+ /// <summary>
+ /// Initializes the <see cref="SettingsManager"/> class.
+ /// </summary>
+ static SettingsManager()
+ {
+ Initialize();
+ }
+
+ /// <summary>
+ /// Initializes the settings manager.
+ /// </summary>
+ private static void Initialize()
+ {
+ if (IsInitialized) return;
+
+ LogManager.Log("Initializing application configuration...");
+
+ DefaultFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Twine", "Tango", "Settings.xml");
+ DefaultFolder = Path.GetDirectoryName(DefaultFilePath);
+
+ try
+ {
+ Default = LoadFromXML(DefaultFilePath);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Could not load application configuration.");
+
+ try
+ {
+ LogManager.Log("Creating application configuration directory structure...");
+ Directory.CreateDirectory(DefaultFolder);
+ }
+ catch (Exception ex2)
+ {
+ LogManager.Log(ex2, "Could not generate directory structure.");
+ }
+ }
+
+ if (Default == null)
+ {
+ Default = new SettingsCollection();
+
+ try
+ {
+ LogManager.Log("Generating default configuration file.");
+ SaveToXML(DefaultFilePath, Default);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Could not generate default configuration file.");
+ }
+ }
+ else
+ {
+ LogManager.Log("Application configuration loaded successfully.");
+ }
+
+ IsInitialized = true;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj b/Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj
new file mode 100644
index 000000000..2916075bf
--- /dev/null
+++ b/Software/Visual_Studio/Tango.Settings/Tango.Settings.csproj
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Tango.Settings</RootNamespace>
+ <AssemblyName>Tango.Settings</AssemblyName>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="DataBase.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="SettingsCollection.cs" />
+ <Compile Include="SettingsManager.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
+ <Name>Tango.Logging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\Tango.Serialization\Tango.Serialization.csproj">
+ <Project>{22f87980-e990-4686-be81-be63d562c4d5}</Project>
+ <Name>Tango.Serialization</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs b/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs
index 2cd9e2d41..ae39e118b 100644
--- a/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs
+++ b/Software/Visual_Studio/Tango.Synchronization/Remote/RemoteDBSynchronizer.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using remote = Tango.DAL.Remote.DB;
using local = Tango.DAL.Local.DB;
+using Tango.Settings;
namespace Tango.Synchronization.Remote
{
@@ -12,7 +13,7 @@ namespace Tango.Synchronization.Remote
{
public static void Synchronize(String sqliteDbFile, String serialNumber)
{
- using (var remoteDB = new remote.RemoteDB("LOCALHOST\\SQLEXPRESS", false))
+ using (var remoteDB = new remote.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false))
{
using (var localDB = new local.LocalDB(sqliteDbFile))
{
diff --git a/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj b/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj
index 30208539c..009f79047 100644
--- a/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj
+++ b/Software/Visual_Studio/Tango.Synchronization/Tango.Synchronization.csproj
@@ -96,6 +96,10 @@
<Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
<Name>Tango.Logging</Name>
</ProjectReference>
+ <ProjectReference Include="..\Tango.Settings\Tango.Settings.csproj">
+ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project>
+ <Name>Tango.Settings</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
diff --git a/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs
index a04e5605d..e9fa5e6ba 100644
--- a/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs
+++ b/Software/Visual_Studio/Tango.UnitTesting/DAL_TST.cs
@@ -2,6 +2,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Tango.DAL;
using System.Linq;
+using Tango.Settings;
namespace Tango.UnitTesting
{
@@ -14,7 +15,7 @@ namespace Tango.UnitTesting
{
String guid = Guid.NewGuid().ToString();
- using (var db = new DAL.Remote.DB.RemoteDB("LOCALHOST\\SQLEXPRESS", false))
+ using (var db = new DAL.Remote.DB.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false))
{
var action = new DAL.Remote.DB.ACTION();
action.CODE = 1;
@@ -27,7 +28,7 @@ namespace Tango.UnitTesting
db.SaveChanges();
}
- using (var db = new DAL.Remote.DB.RemoteDB("LOCALHOST\\SQLEXPRESS", false))
+ using (var db = new DAL.Remote.DB.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false))
{
var action = db.ACTIONS.Single(x => x.GUID == guid);
db.ACTIONS.Remove(action);
diff --git a/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs
index 26d197bcf..3f39211cf 100644
--- a/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs
+++ b/Software/Visual_Studio/Tango.UnitTesting/Synchronization_TST.cs
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using remote = Tango.DAL.Remote.DB;
using local = Tango.DAL.Local.DB;
using Tango.Synchronization.Remote;
+using Tango.Settings;
namespace Tango.UnitTesting
{
@@ -27,7 +28,7 @@ namespace Tango.UnitTesting
[TestMethod]
public void Generate_Demo_Remote_Machine()
{
- using (var remoteDB = new remote.RemoteDB("LOCALHOST\\SQLEXPRESS", false))
+ using (var remoteDB = new remote.RemoteDB(SettingsManager.Default.DataBase.SQLServerAddress, false))
{
var organization = new remote.ORGANIZATION()
{
diff --git a/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj b/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj
index fd9d04b34..79dab4c0d 100644
--- a/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj
+++ b/Software/Visual_Studio/Tango.UnitTesting/Tango.UnitTesting.csproj
@@ -112,6 +112,10 @@
<Project>{40073806-914e-4e78-97ab-fa9639308ebe}</Project>
<Name>Tango.Protobuf</Name>
</ProjectReference>
+ <ProjectReference Include="..\Tango.Settings\Tango.Settings.csproj">
+ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project>
+ <Name>Tango.Settings</Name>
+ </ProjectReference>
<ProjectReference Include="..\Tango.SharedUI\Tango.SharedUI.csproj">
<Project>{ac489889-6e50-4f16-9dba-ff4c6f9ec72b}</Project>
<Name>Tango.SharedUI</Name>
diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln
index 15cc293c6..21533bfd7 100644
--- a/Software/Visual_Studio/Tango.sln
+++ b/Software/Visual_Studio/Tango.sln
@@ -63,6 +63,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.DAL.Local", "Tango.DA
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.MachineDesigner.UI", "Utilities\Tango.MachineDesigner.UI\Tango.MachineDesigner.UI.csproj", "{116DFDB0-7681-46FE-8BAD-FE8AE09BB076}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Settings", "Tango.Settings\Tango.Settings.csproj", "{D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Serialization", "Tango.Serialization\Tango.Serialization.csproj", "{22F87980-E990-4686-BE81-BE63D562C4D5}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -335,6 +339,30 @@ Global
{116DFDB0-7681-46FE-8BAD-FE8AE09BB076}.Release|x64.Build.0 = Release|Any CPU
{116DFDB0-7681-46FE-8BAD-FE8AE09BB076}.Release|x86.ActiveCfg = Release|Any CPU
{116DFDB0-7681-46FE-8BAD-FE8AE09BB076}.Release|x86.Build.0 = Release|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x64.Build.0 = Debug|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Debug|x86.Build.0 = Debug|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x64.ActiveCfg = Release|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x64.Build.0 = Release|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x86.ActiveCfg = Release|Any CPU
+ {D8F1AD85-526A-4F50-B6DC-D437AF63D8D8}.Release|x86.Build.0 = Release|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x64.Build.0 = Debug|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Debug|x86.Build.0 = Debug|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x64.ActiveCfg = Release|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x64.Build.0 = Release|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x86.ActiveCfg = Release|Any CPU
+ {22F87980-E990-4686-BE81-BE63D562C4D5}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE