Switched to SharpLibDisplay. MiniDisplay
authorStephane Lenclud
Sat, 23 Jan 2016 06:23:15 +0100
branchMiniDisplay
changeset 4513d8af0e778f4
parent 450 f2d8620e2434
child 452 79a3f5946a87
Switched to SharpLibDisplay.
GUI/SharpDisplay.cs
GUI/SharpDisplayClient.cs
GUI/SharpDisplayInterface.cs
OpenHardwareMonitor.csproj
packages.config
     1.1 --- a/GUI/SharpDisplay.cs	Tue Feb 03 10:14:18 2015 +0100
     1.2 +++ b/GUI/SharpDisplay.cs	Sat Jan 23 06:23:15 2016 +0100
     1.3 @@ -20,7 +20,7 @@
     1.4  using System.Runtime.InteropServices;
     1.5  using UacHelpers;
     1.6  using System.ServiceModel;
     1.7 -using SharpDisplay;
     1.8 +using SharpLib.Display;
     1.9  
    1.10  
    1.11  namespace OpenHardwareMonitor.GUI
    1.12 @@ -31,13 +31,13 @@
    1.13          private PersistentSettings settings;
    1.14          private UnitManager unitManager;
    1.15          private List<SensorSharpDisplay> iSensors = new List<SensorSharpDisplay>();
    1.16 -        private global::SharpDisplay.DisplayClient iClient;
    1.17 -        DataField iTextFieldTop;
    1.18 -		DataField iTextFieldBottom;
    1.19 -		DataField iTextFieldTopRight;
    1.20 -		DataField iTextFieldBottomRight;
    1.21 +        private Client iClient;
    1.22 +        TextField iTextFieldTop;
    1.23 +        TextField iTextFieldBottom;
    1.24 +        TextField iTextFieldTopRight;
    1.25 +        TextField iTextFieldBottomRight;
    1.26  
    1.27 -		DataField[] iTextFields;
    1.28 +        DataField[] iTextFields;
    1.29  
    1.30          private int iNextSensorToDisplay = 0;
    1.31          private int iTickCounter = 0;
    1.32 @@ -53,12 +53,12 @@
    1.33  
    1.34              //Connect our client
    1.35              //Instance context is then managed by our client class
    1.36 -            iClient = new global::SharpDisplay.DisplayClient();
    1.37 +            iClient = new Client();
    1.38              //
    1.39 -			iTextFieldTop = new DataField(0);
    1.40 -			iTextFieldBottom = new DataField(1);
    1.41 -			iTextFieldTopRight = new DataField(2, "", ContentAlignment.MiddleRight);
    1.42 -			iTextFieldBottomRight = new DataField(3, "", ContentAlignment.MiddleRight);
    1.43 +			iTextFieldTop = new TextField("", ContentAlignment.MiddleLeft,0,0);
    1.44 +			iTextFieldBottom = new TextField("", ContentAlignment.MiddleLeft, 0, 1);
    1.45 +			iTextFieldTopRight = new TextField("", ContentAlignment.MiddleRight,1,0);
    1.46 +			iTextFieldBottomRight = new TextField("", ContentAlignment.MiddleRight,1,1);
    1.47  			//
    1.48  			iClient.Open();
    1.49  			iClient.SetName("Open Hardware Monitor");
     2.1 --- a/GUI/SharpDisplayClient.cs	Tue Feb 03 10:14:18 2015 +0100
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,291 +0,0 @@
     2.4 -
     2.5 -using System;
     2.6 -using System.Collections.Generic;
     2.7 -using System.Linq;
     2.8 -using System.Text;
     2.9 -using System.Threading.Tasks;
    2.10 -using System.Windows.Forms;
    2.11 -using SharpDisplay;
    2.12 -using System.ServiceModel;
    2.13 -using System.ServiceModel.Channels;
    2.14 -
    2.15 -
    2.16 -namespace SharpDisplay
    2.17 -{
    2.18 -    /// <summary>
    2.19 -    ///
    2.20 -    /// </summary>
    2.21 -    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    2.22 -    public class Callback : ICallback, IDisposable
    2.23 -    {
    2.24 -		private DisplayClient DisplayClient { get; set; }
    2.25 -
    2.26 -		public Callback(DisplayClient aClient)
    2.27 -        {
    2.28 -            DisplayClient = aClient;
    2.29 -        }
    2.30 -
    2.31 -        public void OnConnected()
    2.32 -        {
    2.33 -            //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    2.34 -            //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    2.35 -
    2.36 -            MessageBox.Show("OnConnected()", "Client");
    2.37 -        }
    2.38 -
    2.39 -
    2.40 -        public void OnCloseOrder()
    2.41 -        {
    2.42 -			DisplayClient.Close();
    2.43 -            //Debug.Assert(Thread.CurrentThread.IsThreadPoolThread);
    2.44 -            //Trace.WriteLine("Callback thread = " + Thread.CurrentThread.ManagedThreadId);
    2.45 -
    2.46 -            //MessageBox.Show("OnServerClosing()", "Client");
    2.47 -            //MainForm.CloseConnectionThreadSafe();
    2.48 -            //MainForm.CloseThreadSafe();
    2.49 -        }
    2.50 -
    2.51 -        //From IDisposable
    2.52 -        public void Dispose()
    2.53 -        {
    2.54 -
    2.55 -        }
    2.56 -    }
    2.57 -
    2.58 -
    2.59 -    /// <summary>
    2.60 -    ///
    2.61 -    /// </summary>
    2.62 -    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    2.63 -    public class Client : DuplexClientBase<IService>
    2.64 -    {
    2.65 -        public string SessionId { get { return InnerChannel.SessionId; } }
    2.66 -
    2.67 -        public Client(ICallback aCallback)
    2.68 -            : base(new InstanceContext(aCallback), new NetTcpBinding(SecurityMode.None, true), new EndpointAddress("net.tcp://localhost:8001/DisplayService"))
    2.69 -        { }
    2.70 -
    2.71 -        public void SetName(string aClientName)
    2.72 -        {
    2.73 -            Channel.SetName(aClientName);
    2.74 -        }
    2.75 -
    2.76 -        public void SetLayout(TableLayout aLayout)
    2.77 -        {
    2.78 -            Channel.SetLayout(aLayout);
    2.79 -        }
    2.80 -
    2.81 -        public void SetField(DataField aField)
    2.82 -        {
    2.83 -            Channel.SetField(aField);
    2.84 -        }
    2.85 -
    2.86 -        public void SetFields(System.Collections.Generic.IList<DataField> aFields)
    2.87 -        {
    2.88 -            Channel.SetFields(aFields);
    2.89 -        }
    2.90 -
    2.91 -        public int ClientCount()
    2.92 -        {
    2.93 -            return Channel.ClientCount();
    2.94 -        }
    2.95 -
    2.96 -        public bool IsReady()
    2.97 -        {
    2.98 -            return State == CommunicationState.Opened || State == CommunicationState.Created;
    2.99 -        }
   2.100 -    }
   2.101 -
   2.102 -
   2.103 -    /// <summary>
   2.104 -    /// Handle connection with our Sharp Display Server.
   2.105 -    /// If the connection is faulted it will attempt to restart it.
   2.106 -    /// </summary>
   2.107 -    public class DisplayClient
   2.108 -    {
   2.109 -        private Client iClient;
   2.110 -        private Callback iCallback;
   2.111 -        private bool resetingConnection = false;
   2.112 -
   2.113 -        //private MainForm MainForm { get; set; }
   2.114 -        public string SessionId { get { return iClient.SessionId; } }
   2.115 -        public string Name { get; private set; }
   2.116 -        private TableLayout Layout { get; set; }
   2.117 -        private System.Collections.Generic.IList<DataField> Fields { get; set; }
   2.118 -
   2.119 -
   2.120 -        public DisplayClient(/*MainForm aMainForm*/)
   2.121 -        {
   2.122 -            //MainForm = aMainForm;
   2.123 -            Name = "";
   2.124 -            Fields = new DataField[]{};
   2.125 -        }
   2.126 -
   2.127 -        /// <summary>
   2.128 -        /// Initialize our server connection.
   2.129 -        /// </summary>
   2.130 -        public void Open()
   2.131 -        {
   2.132 -            iCallback = new Callback(this);
   2.133 -            iClient = new Client(iCallback);
   2.134 -        }
   2.135 -
   2.136 -        /// <summary>
   2.137 -        /// Terminate our server connection.
   2.138 -        /// </summary>
   2.139 -        public void Close()
   2.140 -        {
   2.141 -            iClient.Close();
   2.142 -            iClient = null;
   2.143 -            iCallback.Dispose();
   2.144 -            iCallback = null;
   2.145 -        }
   2.146 -
   2.147 -        /// <summary>
   2.148 -        /// Tells whether a server connection is available.
   2.149 -        /// </summary>
   2.150 -        /// <returns>True if a server connection is available. False otherwise.</returns>
   2.151 -        public bool IsReady()
   2.152 -        {
   2.153 -            return (iClient != null && iCallback != null && iClient.IsReady());
   2.154 -        }
   2.155 -
   2.156 -        /// <summary>
   2.157 -        /// Check if our server connection is available and attempt reset it if it isn't.
   2.158 -        /// This is notably dealing with timed out connections.
   2.159 -        /// </summary>
   2.160 -        public void CheckConnection()
   2.161 -        {
   2.162 -            if (!IsReady() && !resetingConnection)
   2.163 -            {
   2.164 -                //Try to reconnect
   2.165 -                Open();
   2.166 -
   2.167 -                //Avoid stack overflow in case of persisting failure
   2.168 -                resetingConnection = true;
   2.169 -
   2.170 -                try
   2.171 -                {
   2.172 -                    //On reconnect there is a bunch of properties we need to reset
   2.173 -                    if (Name != "")
   2.174 -                    {
   2.175 -                        iClient.SetName(Name);
   2.176 -                    }
   2.177 -
   2.178 -                    SetLayout(Layout);
   2.179 -                    iClient.SetFields(Fields);
   2.180 -                }
   2.181 -                finally
   2.182 -                {
   2.183 -                    //Make sure our this state does not get out of sync
   2.184 -                    resetingConnection = true;
   2.185 -                }
   2.186 -            }
   2.187 -        }
   2.188 -
   2.189 -        public void SetName(string aClientName)
   2.190 -        {
   2.191 -            Name = aClientName;
   2.192 -            CheckConnection();
   2.193 -            iClient.SetName(aClientName);
   2.194 -        }
   2.195 -
   2.196 -
   2.197 -        public void SetLayout(TableLayout aLayout)
   2.198 -        {
   2.199 -            Layout = aLayout;
   2.200 -            CheckConnection();
   2.201 -            iClient.SetLayout(aLayout);
   2.202 -        }
   2.203 -
   2.204 -        /// <summary>
   2.205 -        /// Set the specified field.
   2.206 -        /// </summary>
   2.207 -        /// <param name="aField"></param>
   2.208 -        /// <returns>True if the specified field was set client side. False means you need to redefine all your fields using CreateFields.</returns>
   2.209 -        public bool SetField(DataField aField)
   2.210 -        {
   2.211 -            int i = 0;
   2.212 -            bool fieldFound = false;
   2.213 -            foreach (DataField field in Fields)
   2.214 -            {
   2.215 -                if (field.Index == aField.Index)
   2.216 -                {
   2.217 -                    //Update our field then
   2.218 -                    Fields[i] = aField;
   2.219 -                    fieldFound = true;
   2.220 -                    break;
   2.221 -                }
   2.222 -                i++;
   2.223 -            }
   2.224 -
   2.225 -            if (!fieldFound)
   2.226 -            {
   2.227 -                //Field not found, make to use SetFields with all your fields at least once after setting your layout.
   2.228 -                return false;
   2.229 -            }
   2.230 -
   2.231 -            CheckConnection();
   2.232 -            iClient.SetField(aField);
   2.233 -            return true;
   2.234 -        }
   2.235 -
   2.236 -        /// <summary>
   2.237 -        /// Use this function when updating existing fields.
   2.238 -        /// </summary>
   2.239 -        /// <param name="aFields"></param>
   2.240 -        public bool SetFields(System.Collections.Generic.IList<DataField> aFields)
   2.241 -        {
   2.242 -            int fieldFoundCount = 0;
   2.243 -            foreach (DataField fieldUpdate in aFields)
   2.244 -            {
   2.245 -                int i = 0;
   2.246 -                foreach (DataField existingField in Fields)
   2.247 -                {
   2.248 -                    if (existingField.Index == fieldUpdate.Index)
   2.249 -                    {
   2.250 -                        //Update our field then
   2.251 -                        Fields[i] = fieldUpdate;
   2.252 -                        fieldFoundCount++;
   2.253 -                        //Move on to the next field
   2.254 -                        break;
   2.255 -                    }
   2.256 -                    i++;
   2.257 -                }
   2.258 -            }
   2.259 -
   2.260 -            //
   2.261 -            if (fieldFoundCount!=aFields.Count)
   2.262 -            {
   2.263 -                //Field not found, make sure to use SetFields with all your fields at least once after setting your layout.
   2.264 -                return false;
   2.265 -            }
   2.266 -
   2.267 -            CheckConnection();
   2.268 -            iClient.SetFields(aFields);
   2.269 -            return true;
   2.270 -        }
   2.271 -
   2.272 -        /// <summary>
   2.273 -        /// Use this function when creating your fields.
   2.274 -        /// </summary>
   2.275 -        /// <param name="aFields"></param>
   2.276 -        public void CreateFields(System.Collections.Generic.IList<DataField> aFields)
   2.277 -        {
   2.278 -            Fields = aFields;
   2.279 -            CheckConnection();
   2.280 -            iClient.SetFields(aFields);
   2.281 -        }
   2.282 -
   2.283 -        public int ClientCount()
   2.284 -        {
   2.285 -            CheckConnection();
   2.286 -            return iClient.ClientCount();
   2.287 -        }
   2.288 -
   2.289 -
   2.290 -
   2.291 -    }
   2.292 -
   2.293 -
   2.294 -}
     3.1 --- a/GUI/SharpDisplayInterface.cs	Tue Feb 03 10:14:18 2015 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,204 +0,0 @@
     3.4 -//
     3.5 -// Define a public API for both SharpDisplay client and server to use.
     3.6 -//
     3.7 -
     3.8 -using System;
     3.9 -using System.Collections.Generic;
    3.10 -using System.Linq;
    3.11 -using System.Text;
    3.12 -using System.Threading.Tasks;
    3.13 -using System.ServiceModel;
    3.14 -using System.Collections;
    3.15 -using System.Drawing;
    3.16 -using System.Runtime.Serialization;
    3.17 -using System.Windows.Forms;
    3.18 -
    3.19 -
    3.20 -namespace SharpDisplay
    3.21 -{
    3.22 -	/// <summary>
    3.23 -	/// For client to specify a specific layout.
    3.24 -	/// </summary>
    3.25 -	[DataContract]
    3.26 -	public class TableLayout
    3.27 -	{
    3.28 -		public TableLayout()
    3.29 -		{
    3.30 -			Columns = new List<ColumnStyle>();
    3.31 -			Rows = new List<RowStyle>();
    3.32 -			Cells = new List<DataField>();
    3.33 -		}
    3.34 -
    3.35 -		public TableLayout(int aColumnCount, int aRowCount)
    3.36 -		{
    3.37 -			Columns = new List<ColumnStyle>();
    3.38 -			Rows = new List<RowStyle>();
    3.39 -
    3.40 -			for (int i = 0; i < aColumnCount; i++)
    3.41 -			{
    3.42 -				Columns.Add(new ColumnStyle(SizeType.Percent, 100 / aColumnCount));
    3.43 -			}
    3.44 -
    3.45 -			for (int i = 0; i < aRowCount; i++)
    3.46 -			{
    3.47 -				Rows.Add(new RowStyle(SizeType.Percent, 100 / aRowCount));
    3.48 -			}
    3.49 -		}
    3.50 -
    3.51 -		[DataMember]
    3.52 -		public List<DataField> Cells { get; set; }
    3.53 -
    3.54 -		[DataMember]
    3.55 -		public List<ColumnStyle> Columns { get; set; }
    3.56 -
    3.57 -		[DataMember]
    3.58 -		public List<RowStyle> Rows { get; set; }
    3.59 -	}
    3.60 -
    3.61 -	/// <summary>
    3.62 -	///
    3.63 -	/// </summary>
    3.64 -	[DataContract]
    3.65 -	public class DataField
    3.66 -	{
    3.67 -		public DataField()
    3.68 -		{
    3.69 -			Index = 0;
    3.70 -			ColumnSpan = 1;
    3.71 -			RowSpan = 1;
    3.72 -			//Text
    3.73 -			Text = "";
    3.74 -			Alignment = ContentAlignment.MiddleLeft;
    3.75 -			//Bitmap
    3.76 -			Bitmap = null;
    3.77 -		}
    3.78 -
    3.79 -		//Text constructor
    3.80 -		public DataField(int aIndex, string aText = "", ContentAlignment aAlignment = ContentAlignment.MiddleLeft)
    3.81 -		{
    3.82 -			ColumnSpan = 1;
    3.83 -			RowSpan = 1;
    3.84 -			Index = aIndex;
    3.85 -			Text = aText;
    3.86 -			Alignment = aAlignment;
    3.87 -			//
    3.88 -			Bitmap = null;
    3.89 -		}
    3.90 -
    3.91 -		//Bitmap constructor
    3.92 -		public DataField(int aIndex, Bitmap aBitmap)
    3.93 -		{
    3.94 -			ColumnSpan = 1;
    3.95 -			RowSpan = 1;
    3.96 -			Index = aIndex;
    3.97 -			Bitmap = aBitmap;
    3.98 -			//Text
    3.99 -			Text = "";
   3.100 -			Alignment = ContentAlignment.MiddleLeft;
   3.101 -		}
   3.102 -
   3.103 -
   3.104 -		//Generic layout properties
   3.105 -		[DataMember]
   3.106 -		public int Index { get; set; }
   3.107 -
   3.108 -		[DataMember]
   3.109 -		public int Column { get; set; }
   3.110 -
   3.111 -		[DataMember]
   3.112 -		public int Row { get; set; }
   3.113 -
   3.114 -		[DataMember]
   3.115 -		public int ColumnSpan { get; set; }
   3.116 -
   3.117 -		[DataMember]
   3.118 -		public int RowSpan { get; set; }
   3.119 -
   3.120 -		//Text properties
   3.121 -		[DataMember]
   3.122 -		public string Text { get; set; }
   3.123 -
   3.124 -		[DataMember]
   3.125 -		public ContentAlignment Alignment { get; set; }
   3.126 -
   3.127 -		//Bitmap properties
   3.128 -		[DataMember]
   3.129 -		public Bitmap Bitmap { get; set; }
   3.130 -
   3.131 -		//
   3.132 -		public bool IsBitmap { get { return Bitmap != null; } }
   3.133 -		//
   3.134 -		public bool IsText { get { return Bitmap == null; } }
   3.135 -		//
   3.136 -		public bool IsSameLayout(DataField aField)
   3.137 -		{
   3.138 -			return (aField.ColumnSpan == ColumnSpan && aField.RowSpan == RowSpan);
   3.139 -		}
   3.140 -	}
   3.141 -
   3.142 -	/// <summary>
   3.143 -	/// Define our SharpDisplay service.
   3.144 -	/// Clients and servers must implement it to communicate with one another.
   3.145 -	/// Through this service clients can send requests to a server.
   3.146 -	/// Through this service a server session can receive requests from a client.
   3.147 -	/// </summary>
   3.148 -	[ServiceContract(CallbackContract = typeof(ICallback), SessionMode = SessionMode.Required)]
   3.149 -	public interface IService
   3.150 -	{
   3.151 -		/// <summary>
   3.152 -		/// Set the name of this client.
   3.153 -		/// Name is a convenient way to recognize your client.
   3.154 -		/// Naming you client is not mandatory.
   3.155 -		/// In the absence of a name the session ID is often used instead.
   3.156 -		/// </summary>
   3.157 -		/// <param name="aClientName"></param>
   3.158 -		[OperationContract(IsOneWay = true)]
   3.159 -		void SetName(string aClientName);
   3.160 -
   3.161 -		/// <summary>
   3.162 -		/// </summary>
   3.163 -		/// <param name="aLayout"></param>
   3.164 -		[OperationContract(IsOneWay = true)]
   3.165 -		void SetLayout(TableLayout aLayout);
   3.166 -
   3.167 -		/// <summary>
   3.168 -		/// Set the given field on your display.
   3.169 -		/// Fields are often just lines of text or bitmaps.
   3.170 -		/// </summary>
   3.171 -		/// <param name="aTextFieldIndex"></param>
   3.172 -		[OperationContract(IsOneWay = true)]
   3.173 -		void SetField(DataField aField);
   3.174 -
   3.175 -		/// <summary>
   3.176 -		/// Allows a client to set multiple fields at once.
   3.177 -		/// </summary>
   3.178 -		/// <param name="aFields"></param>
   3.179 -		[OperationContract(IsOneWay = true)]
   3.180 -		void SetFields(System.Collections.Generic.IList<DataField> aFields);
   3.181 -
   3.182 -		/// <summary>
   3.183 -		/// Provides the number of clients currently connected
   3.184 -		/// </summary>
   3.185 -		/// <returns></returns>
   3.186 -		[OperationContract()]
   3.187 -		int ClientCount();
   3.188 -
   3.189 -	}
   3.190 -
   3.191 -	/// <summary>
   3.192 -	/// SharDisplay callback provides a means for a server to notify its clients.
   3.193 -	/// </summary>
   3.194 -	public interface ICallback
   3.195 -	{
   3.196 -		[OperationContract(IsOneWay = true)]
   3.197 -		void OnConnected();
   3.198 -
   3.199 -		/// <summary>
   3.200 -		/// Tell our client to close its connection.
   3.201 -		/// Notably sent when the server is shutting down.
   3.202 -		/// </summary>
   3.203 -		[OperationContract(IsOneWay = true)]
   3.204 -		void OnCloseOrder();
   3.205 -	}
   3.206 -
   3.207 -}
     4.1 --- a/OpenHardwareMonitor.csproj	Tue Feb 03 10:14:18 2015 +0100
     4.2 +++ b/OpenHardwareMonitor.csproj	Sat Jan 23 06:23:15 2016 +0100
     4.3 @@ -65,6 +65,10 @@
     4.4      <Reference Include="OxyPlot.WindowsForms">
     4.5        <HintPath>External\OxyPlot.WindowsForms.dll</HintPath>
     4.6      </Reference>
     4.7 +    <Reference Include="SharpLibDisplay, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
     4.8 +      <HintPath>packages\SharpLibDisplay.0.2.4\lib\net40\SharpLibDisplay.dll</HintPath>
     4.9 +      <Private>True</Private>
    4.10 +    </Reference>
    4.11      <Reference Include="System" />
    4.12      <Reference Include="System.Configuration.Install" />
    4.13      <Reference Include="System.Drawing" />
    4.14 @@ -116,8 +120,6 @@
    4.15      <Compile Include="GUI\SensorNotifyIcon.cs" />
    4.16      <Compile Include="GUI\SensorSharpDisplay.cs" />
    4.17      <Compile Include="GUI\SharpDisplay.cs" />
    4.18 -    <Compile Include="GUI\SharpDisplayClient.cs" />
    4.19 -    <Compile Include="GUI\SharpDisplayInterface.cs" />
    4.20      <Compile Include="GUI\ShowDesktop.cs" />
    4.21      <Compile Include="GUI\SoundGraphDisplay.cs" />
    4.22      <Compile Include="GUI\SoundGraphServer.cs" />
    4.23 @@ -188,6 +190,7 @@
    4.24    </ItemGroup>
    4.25    <ItemGroup>
    4.26      <None Include="App.config" />
    4.27 +    <None Include="packages.config" />
    4.28      <None Include="Resources\app.manifest">
    4.29        <SubType>Designer</SubType>
    4.30      </None>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/packages.config	Sat Jan 23 06:23:15 2016 +0100
     5.3 @@ -0,0 +1,4 @@
     5.4 +<?xml version="1.0" encoding="utf-8"?>
     5.5 +<packages>
     5.6 +  <package id="SharpLibDisplay" version="0.2.4" targetFramework="net40" />
     5.7 +</packages>
     5.8 \ No newline at end of file