Changed sign key in library MtApiService: using MtApiKey.snk. Added logging into MtApiService and used ILMerge.Task to merge assemblies into one dll.

This commit is contained in:
vdemydiuk
2016-10-12 16:37:54 +03:00
parent e373f7976c
commit 1d407b5e16
31 changed files with 1050 additions and 528 deletions
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- -->
<!-- ILMerge project-specific settings. Almost never need to be set explicitly. -->
<!-- for details, see http://research.microsoft.com/en-us/people/mbarnett/ilmerge.aspx -->
<!-- -->
<!-- *** set this file to Type=None, CopyToOutput=Never *** -->
<!-- If True, all copy local dependencies will also be merged from referenced projects whether they are referenced in the current project explicitly or not -->
<ILMergeTransitive>true</ILMergeTransitive>
<!-- Extra ILMerge library paths (semicolon-separated). Dont put your package dependencies here, they will be added automagically -->
<ILMergeLibraryPath></ILMergeLibraryPath>
<!-- The solution NuGet package directory if not standard 'SOLUTION\packages' -->
<ILMergePackagesPath></ILMergePackagesPath>
<!-- The merge order file name if differs from standard 'ILMergeOrder.txt' -->
<ILMergeOrderFile></ILMergeOrderFile>
<!-- The strong key file name if not specified in the project -->
<ILMergeKeyFile>MtApiKey.snk</ILMergeKeyFile>
<!-- The assembly version if differs for the version of the main assembly -->
<ILMergeAssemblyVersion></ILMergeAssemblyVersion>
<!-- added in Version 1.0.4 -->
<ILMergeFileAlignment></ILMergeFileAlignment>
<!-- added in Version 1.0.4, default=none -->
<ILMergeAllowDuplicateType></ILMergeAllowDuplicateType>
<!-- If the <see cref="CopyAttributes"/> is also set, any assembly-level attributes names that have the same type are copied over into the target assembly -->
<ILMergeAllowMultipleAssemblyLevelAttributes></ILMergeAllowMultipleAssemblyLevelAttributes>
<!-- See ILMerge documentation -->
<ILMergeAllowZeroPeKind></ILMergeAllowZeroPeKind>
<!-- The assembly level attributes of each input assembly are copied over into the target assembly -->
<ILMergeCopyAttributes></ILMergeCopyAttributes>
<!-- Creates a .pdb file for the output assembly and merges into it any .pdb files found for input assemblies, default=true -->
<ILMergeDebugInfo></ILMergeDebugInfo>
<!-- Target assembly will be delay signed -->
<ILMergeDelaySign></ILMergeDelaySign>
<!-- Types in assemblies other than the primary assembly have their visibility modified -->
<ILMergeInternalize></ILMergeInternalize>
<!-- The path name of the file that will be used to identify types that are not to have their visibility modified -->
<ILMergeInternalizeExcludeFile></ILMergeInternalizeExcludeFile>
<!-- XML documentation files are merged to produce an XML documentation file for the target assembly -->
<ILMergeXmlDocumentation></ILMergeXmlDocumentation>
<!-- External assembly references in the manifest of the target assembly will use full public keys (false) or public key tokens (true, default value) -->
<ILMergePublicKeyTokens></ILMergePublicKeyTokens>
<!-- Types with the same name are all merged into a single type in the target assembly -->
<ILMergeUnionMerge></ILMergeUnionMerge>
<!-- The version of the target framework, default 40 (works for 45 too) -->
<ILTargetPlatform></ILTargetPlatform>
</PropertyGroup>
</Project>
+4
View File
@@ -0,0 +1,4 @@
# this file contains the partial list of the merged assemblies in the merge order
# you can fill it from the obj\CONFIG\PROJECT.ilmerge generated on every build
# and finetune merge order to your satisfaction
+2 -5
View File
@@ -1,13 +1,10 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MTApiService namespace MTApiService
{ {
public interface IMtApiServer public interface IMtApiServer
{ {
MtResponse SendCommand(MtCommand command); MtResponse SendCommand(MtCommand command);
IEnumerable<MtQuote> GetQuotes(); List<MtQuote> GetQuotes();
} }
} }
+55
View File
@@ -0,0 +1,55 @@
using System;
using log4net;
using log4net.Appender;
using log4net.Core;
using log4net.Layout;
using log4net.Repository.Hierarchy;
namespace MTApiService
{
public class LogConfigurator
{
private const string LogFileNameExtension = "txt";
public static void Setup(string profileName)
{
if (string.IsNullOrEmpty(profileName))
throw new ArgumentNullException();
var hierarchy = (Hierarchy) LogManager.GetRepository();
var patternLayout = new PatternLayout
{
ConversionPattern = "%date [%thread] %-5level %logger - %message%newline"
};
patternLayout.ActivateOptions();
string filename = $"{DateTime.Now.ToString("yyyy-dd-M--HH-mm-ss")}.{LogFileNameExtension}";
var roller = new RollingFileAppender
{
AppendToFile = false,
File = $@"{System.IO.Path.GetTempPath()}{profileName}\Logs\{filename}",
Layout = patternLayout,
PreserveLogFileNameExtension = true,
MaxSizeRollBackups = 5,
MaximumFileSize = "1GB",
RollingStyle = RollingFileAppender.RollingMode.Size,
StaticLogFileName = false
};
roller.ActivateOptions();
hierarchy.Root.AddAppender(roller);
var memory = new MemoryAppender();
memory.ActivateOptions();
hierarchy.Root.AddAppender(memory);
#if (DEBUG)
hierarchy.Root.Level = Level.Debug;
#else
hierarchy.Root.Level = Level.Info;
#endif
hierarchy.Configured = true;
}
}
}
+27 -3
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props" Condition="Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props')" />
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@@ -14,6 +15,8 @@
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile> </TargetFrameworkProfile>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -35,12 +38,17 @@
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<SignAssembly>true</SignAssembly> <SignAssembly>false</SignAssembly>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<AssemblyOriginatorKeyFile>MtApiKey.pfx</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\packages\log4net.2.0.5\lib\net40-full\log4net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" /> <Reference Include="System.Runtime.Serialization" />
@@ -54,6 +62,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="ICommandManager.cs" /> <Compile Include="ICommandManager.cs" />
<Compile Include="IMetaTraderHandler.cs" /> <Compile Include="IMetaTraderHandler.cs" />
<Compile Include="LogConfigurator.cs" />
<Compile Include="MtCommandEventArgs.cs" /> <Compile Include="MtCommandEventArgs.cs" />
<Compile Include="IDisposableChannel.cs" /> <Compile Include="IDisposableChannel.cs" />
<Compile Include="IMtApiServer.cs" /> <Compile Include="IMtApiServer.cs" />
@@ -78,13 +87,28 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="MtApiKey.pfx" /> <None Include="ILMerge.props">
<SubType>Designer</SubType>
</None>
<None Include="MtApiKey.snk" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="ILMergeOrder.txt" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>
<PostBuildEvent> <PostBuildEvent>
</PostBuildEvent> </PostBuildEvent>
</PropertyGroup> </PropertyGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.props'))" />
<Error Condition="!Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets'))" />
</Target>
<Import Project="..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets" Condition="Exists('..\packages\MSBuild.ILMerge.Task.1.0.5\build\MSBuild.ILMerge.Task.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">
Binary file not shown.
BIN
View File
Binary file not shown.
+11 -14
View File
@@ -1,20 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; using System.ServiceModel;
using System.ServiceModel.Channels; using System.ServiceModel.Channels;
namespace MTApiService namespace MTApiService
{ {
class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable internal class MtApiProxy : DuplexClientBase<IMtApi>, IMtApi, IDisposable
{ {
public MtApiProxy(InstanceContext callbackContext, Binding binding, public MtApiProxy(InstanceContext callbackContext, Binding binding, EndpointAddress remoteAddress)
EndpointAddress remoteAddress)
: base(callbackContext, binding, remoteAddress) : base(callbackContext, binding, remoteAddress)
{ {
base.InnerDuplexChannel.Faulted += new EventHandler(InnerDuplexChannel_Faulted); InnerDuplexChannel.Faulted += InnerDuplexChannel_Faulted;
base.InnerDuplexChannel.Open(); InnerDuplexChannel.Open();
} }
#region IMtApi Members #region IMtApi Members
@@ -34,7 +31,7 @@ namespace MTApiService
return Channel.SendCommand(command); return Channel.SendCommand(command);
} }
public IEnumerable<MtQuote> GetQuotes() public List<MtQuote> GetQuotes()
{ {
return Channel.GetQuotes(); return Channel.GetQuotes();
} }
@@ -47,19 +44,19 @@ namespace MTApiService
{ {
try try
{ {
this.Close(); Close();
} }
catch (CommunicationException) catch (CommunicationException)
{ {
this.Abort(); Abort();
} }
catch (TimeoutException) catch (TimeoutException)
{ {
this.Abort(); Abort();
} }
catch (Exception) catch (Exception)
{ {
this.Abort(); Abort();
} }
} }
@@ -68,9 +65,9 @@ namespace MTApiService
#region Private Methods #region Private Methods
private void InnerDuplexChannel_Faulted(object sender, EventArgs e) private void InnerDuplexChannel_Faulted(object sender, EventArgs e)
{ {
if (Faulted != null) Faulted?.Invoke(this, e);
Faulted(this, e);
} }
#endregion #endregion
#region Events #region Events
+108 -35
View File
@@ -1,8 +1,8 @@
using System; using System;
using System.Diagnostics;
using System.Collections; using System.Collections;
using System.ServiceModel; using System.ServiceModel;
using System.Collections.Generic; using System.Collections.Generic;
using log4net;
namespace MTApiService namespace MTApiService
{ {
@@ -14,6 +14,8 @@ namespace MTApiService
public delegate void MtQuoteHandler(MtQuote quote); public delegate void MtQuoteHandler(MtQuote quote);
#region Fields #region Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtClient));
private MtApiProxy _proxy; private MtApiProxy _proxy;
private bool _isConnected; private bool _isConnected;
#endregion #endregion
@@ -21,7 +23,7 @@ namespace MTApiService
#region Public Methods #region Public Methods
public void Open(string host, int port) public void Open(string host, int port)
{ {
Debug.WriteLine("[INFO] MtClient::Open"); Log.DebugFormat("Open: begin. host = {0}, port = {1}", host, port);
if (string.IsNullOrEmpty(host)) if (string.IsNullOrEmpty(host))
throw new ArgumentNullException(nameof(host), "host is null or empty"); throw new ArgumentNullException(nameof(host), "host is null or empty");
@@ -32,7 +34,10 @@ namespace MTApiService
var urlService = $"net.tcp://{host}:{port}/{ServiceName}"; var urlService = $"net.tcp://{host}:{port}/{ServiceName}";
if (_proxy != null) if (_proxy != null)
{
Log.Warn("Open: end. _proxy is not null.");
return; return;
}
var bind = new NetTcpBinding(SecurityMode.None) var bind = new NetTcpBinding(SecurityMode.None)
{ {
@@ -52,17 +57,24 @@ namespace MTApiService
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService)); _proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted; _proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
} }
public void Open(int port) public void Open(int port)
{ {
Log.DebugFormat("Open: begin. port = {0}", port);
if (port < 0 || port > 65536) if (port < 0 || port > 65536)
throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid"); throw new ArgumentOutOfRangeException(nameof(port), "port value is invalid");
var urlService = $"net.pipe://localhost/{ServiceName}_{port}"; var urlService = $"net.pipe://localhost/{ServiceName}_{port}";
if (_proxy != null) if (_proxy != null)
{
Log.Warn("Open: end. _proxy is not null.");
return; return;
}
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None) var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
{ {
@@ -82,11 +94,13 @@ namespace MTApiService
_proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService)); _proxy = new MtApiProxy(new InstanceContext(this), bind, new EndpointAddress(urlService));
_proxy.Faulted += ProxyFaulted; _proxy.Faulted += ProxyFaulted;
Log.Debug("Open: end.");
} }
public void Close() public void Close()
{ {
Debug.WriteLine("[INFO] MtClient::Close"); Log.Debug("Close: begin.");
if (_proxy != null) if (_proxy != null)
{ {
@@ -96,35 +110,52 @@ namespace MTApiService
} }
_isConnected = false; _isConnected = false;
Log.Debug("Close: end.");
} }
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public void Connect() public void Connect()
{ {
Debug.WriteLine("[INFO] MtClient::Connect"); Log.Debug("Connect: begin.");
if (_proxy == null)
{
Log.Error("Connect: _proxy is not defined.");
throw new CommunicationException("Connection failed to service. Proxy is not defined (needs to call Open)");
}
if (_isConnected)
{
Log.Warn("Connected: end. Client is already connected.");
return;
}
try try
{ {
if (_proxy != null && _isConnected)
return;
_isConnected = _proxy.Connect(); _isConnected = _proxy.Connect();
if (_isConnected == false)
throw new Exception("Connected failed");
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.WriteLine("[ERROR] MtClient::Connect: {0}", ex.Message); Log.ErrorFormat("Connect: Exception - {0}", ex.Message);
Close(); Close();
throw new CommunicationException("Connection failed to service"); throw new CommunicationException($"Connection failed to service. {ex.Message}");
} }
if (_isConnected == false)
{
Log.Error("Connect: end. Connection failed.");
throw new CommunicationException("Connection failed");
}
Log.Debug("Connect: end.");
} }
public void Disconnect() public void Disconnect()
{ {
Debug.WriteLine("[INFO] MtClient::Disconnect"); Log.Debug("Disconnect: begin.");
try try
{ {
@@ -134,26 +165,40 @@ namespace MTApiService
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.WriteLine("[ERROR] MtClient::Disconnect: {0}", ex.Message); Log.ErrorFormat("Disconnect: Exception - {0}", ex.Message);
Close(); Close();
} }
Log.Debug("Disconnect: end.");
} }
public MtResponse SendCommand(int commandType, ArrayList commandParameters) /// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters)
{ {
Debug.WriteLine("[INFO] MtClient::SendCommand: commandType = {0}", commandType); Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
MtResponse result = null; MtResponse result;
if (_proxy == null)
{
Log.Error("SendCommand: Proxy is not defined.");
throw new CommunicationException("Proxy is not defined.");
}
if (_isConnected == false)
{
Log.Error("SendCommand: Client is not connected.");
throw new CommunicationException("Client is not connected.");
}
try try
{ {
if (_proxy != null && _isConnected) result = _proxy.SendCommand(new MtCommand(commandType, parameters));
result = _proxy.SendCommand(new MtCommand(commandType, commandParameters));
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.WriteLine("[ERROR] MtClient::SendCommand: {0}", ex.Message); Log.ErrorFormat("SendCommand: Exception - {0}", ex.Message);
Close(); Close();
@@ -163,27 +208,41 @@ namespace MTApiService
return result; return result;
} }
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public IEnumerable<MtQuote> GetQuotes() public IEnumerable<MtQuote> GetQuotes()
{ {
Debug.WriteLine("[INFO] MtClient::GetQuotes"); Log.Debug("GetQuotes: begin.");
IEnumerable<MtQuote> result = null; if (_proxy == null)
{
Log.Warn("GetQuotes: end. _proxy is not defined.");
return null;
}
if (_isConnected == false)
{
Log.Warn("GetQuotes: end. Client is not connected.");
return null;
}
List<MtQuote> result;
try try
{ {
if (_proxy != null && _isConnected) result = _proxy.GetQuotes();
result = _proxy.GetQuotes();
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.WriteLine("[ERROR] MtClient::GetQuotes: {0}", ex.Message); Log.ErrorFormat("GetQuotes: Exception - {0}", ex.Message);
Close(); Close();
throw new CommunicationException("Service connection failed"); throw new CommunicationException($"Service connection failed! {ex.Message}");
} }
return result;; Log.DebugFormat("GetQuotes: end. quotes count = {0}", result?.Count);
return result;
} }
#endregion #endregion
@@ -192,40 +251,51 @@ namespace MTApiService
public void OnQuoteUpdate(MtQuote quote) public void OnQuoteUpdate(MtQuote quote)
{ {
Log.DebugFormat("OnQuoteUpdate: begin. quote = {0}", quote);
if (quote == null) return; if (quote == null) return;
QuoteUpdated?.Invoke(quote); QuoteUpdated?.Invoke(quote);
Debug.WriteLine("[INFO] MtClient::OnQuoteUpdate: " + quote); Log.Debug("OnQuoteUpdate: end.");
} }
public void OnQuoteAdded(MtQuote quote) public void OnQuoteAdded(MtQuote quote)
{ {
Debug.WriteLine("[INFO] MtClient::OnQuoteAdded"); Log.DebugFormat("OnQuoteAdded: begin. quote = {0}", quote);
QuoteAdded?.Invoke(quote); QuoteAdded?.Invoke(quote);
Log.Debug("OnQuoteAdded: end.");
} }
public void OnQuoteRemoved(MtQuote quote) public void OnQuoteRemoved(MtQuote quote)
{ {
Debug.WriteLine("[INFO] MtClient::OnQuoteRemoved"); Log.DebugFormat("OnQuoteRemoved: begin. quote = {0}", quote);
QuoteRemoved?.Invoke(quote); QuoteRemoved?.Invoke(quote);
Log.Debug("OnQuoteRemoved: end.");
} }
public void OnServerStopped() public void OnServerStopped()
{ {
Debug.WriteLine("[INFO] MtClient::OnServerStopped"); Log.Debug("OnServerStopped: begin.");
Close(); Close();
ServerDisconnected?.Invoke(this, EventArgs.Empty); ServerDisconnected?.Invoke(this, EventArgs.Empty);
Log.Debug("OnServerStopped: end.");
} }
public void OnMtEvent(MtEvent mtEvent) public void OnMtEvent(MtEvent mtEvent)
{ {
Log.DebugFormat("OnMtEvent: begin. event = {0}", mtEvent);
MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent)); MtEventReceived?.Invoke(this, new MtEventArgs(mtEvent));
Log.Debug("OnMtEvent: end.");
} }
#endregion #endregion
@@ -239,11 +309,12 @@ namespace MTApiService
private void ProxyFaulted(object sender, EventArgs e) private void ProxyFaulted(object sender, EventArgs e)
{ {
Debug.WriteLine("[INFO] MtClient::ProxyFaulted"); Log.Debug("ProxyFaulted: begin.");
Close(); Close();
ServerFailed?.Invoke(this, EventArgs.Empty); ServerFailed?.Invoke(this, EventArgs.Empty);
Log.Debug("ProxyFaulted: end.");
} }
#endregion #endregion
@@ -252,9 +323,11 @@ namespace MTApiService
public void Dispose() public void Dispose()
{ {
Debug.WriteLine("[INFO] MtClient::Dispose"); Log.Debug("Dispose: begin.");
Close(); Close();
Log.Debug("Dispose: end.");
} }
#endregion #endregion
+5 -5
View File
@@ -1,8 +1,4 @@
using System; using System.Runtime.Serialization;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Collections; using System.Collections;
namespace MTApiService namespace MTApiService
@@ -22,5 +18,9 @@ namespace MTApiService
[DataMember] [DataMember]
public ArrayList Parameters { get; private set; } public ArrayList Parameters { get; private set; }
public override string ToString()
{
return $"CommandType = {CommandType}";
}
} }
} }
Regular → Executable
+9 -1
View File
@@ -1,4 +1,5 @@
using System.Threading; using System;
using System.Threading;
namespace MTApiService namespace MTApiService
{ {
@@ -10,6 +11,9 @@ namespace MTApiService
public MtCommandTask(MtCommand command) public MtCommandTask(MtCommand command)
{ {
if (command == null)
throw new ArgumentNullException(nameof(command));
Command = command; Command = command;
} }
@@ -33,5 +37,9 @@ namespace MTApiService
_responseWaiter.Set(); _responseWaiter.Set();
} }
public override string ToString()
{
return $"Command = {Command}";
}
} }
} }
+1 -5
View File
@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MTApiService namespace MTApiService
{ {
public class MtConnectionProfile public class MtConnectionProfile
+44 -10
View File
@@ -1,31 +1,50 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using log4net;
namespace MTApiService namespace MTApiService
{ {
internal class MtCommandExecutorManager : ICommandManager internal class MtCommandExecutorManager : ICommandManager
{ {
#region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtCommandExecutorManager));
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
private readonly object _locker = new object();
#endregion
#region Public Methods #region Public Methods
public void Stop() public void Stop()
{ {
Log.Debug("Stop: begin.");
lock (_locker) lock (_locker)
{ {
_commandExecutors.Clear(); _commandExecutors.Clear();
_commandTasks.Clear(); _commandTasks.Clear();
} }
Log.Debug("Stop: end.");
} }
public void AddCommandExecutor(MtExpert commandExecutor) public void AddCommandExecutor(MtExpert commandExecutor)
{ {
if (commandExecutor == null) if (commandExecutor == null)
return; throw new ArgumentNullException(nameof(commandExecutor));
Log.DebugFormat("AddCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
var notify = false; var notify = false;
lock (_locker) lock (_locker)
{ {
if (_commandExecutors.Contains(commandExecutor)) if (_commandExecutors.Contains(commandExecutor))
{
Log.Warn("AddCommandExecutor: end. Command executor already exist.");
return; return;
}
_commandExecutors.Add(commandExecutor); _commandExecutors.Add(commandExecutor);
if (_commandTasks.Count > 0) if (_commandTasks.Count > 0)
@@ -41,18 +60,25 @@ namespace MTApiService
{ {
NotifyCommandReady(); NotifyCommandReady();
} }
Log.Debug("AddCommandExecutor: end.");
} }
public void RemoveCommandExecutor(MtExpert commandExecutor) public void RemoveCommandExecutor(MtExpert commandExecutor)
{ {
if (commandExecutor == null) if (commandExecutor == null)
return; throw new ArgumentNullException(nameof(commandExecutor));
Log.DebugFormat("RemoveCommandExecutor: begin. commandExecutor = {0}", commandExecutor);
var notify = false; var notify = false;
lock (_locker) lock (_locker)
{ {
if (_commandExecutors.Contains(commandExecutor) == false) if (_commandExecutors.Contains(commandExecutor) == false)
{
Log.Warn("RemoveCommandExecutor: end. Command executor is not exist in collection.");
return; return;
}
_commandExecutors.Remove(commandExecutor); _commandExecutors.Remove(commandExecutor);
if (_commandTasks.Count > 0) if (_commandTasks.Count > 0)
@@ -68,12 +94,16 @@ namespace MTApiService
{ {
NotifyCommandReady(); NotifyCommandReady();
} }
Log.Debug("RemoveCommandExecutor: end.");
} }
public void EnqueueCommandTask(MtCommandTask task) public void EnqueueCommandTask(MtCommandTask task)
{ {
if (task == null) if (task == null)
return; throw new ArgumentNullException(nameof(task));
Log.DebugFormat("EnqueueCommandTask: begin. task = {0}", task);
lock (_locker) lock (_locker)
{ {
@@ -81,10 +111,14 @@ namespace MTApiService
} }
NotifyCommandReady(); NotifyCommandReady();
Log.Debug("EnqueueCommandTask: end.");
} }
public MtCommandTask DequeueCommandTask() public MtCommandTask DequeueCommandTask()
{ {
Log.Debug("DequeueCommandTask: called.");
lock (_locker) lock (_locker)
{ {
return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null; return _commandTasks.Count > 0 ? _commandTasks.Dequeue() : null;
@@ -96,6 +130,8 @@ namespace MTApiService
#region Private Methods #region Private Methods
private void NotifyCommandReady() private void NotifyCommandReady()
{ {
Log.Debug("NotifyCommandReady: begin.");
var commandExecutors = new List<MtExpert>(); var commandExecutors = new List<MtExpert>();
lock (_locker) lock (_locker)
{ {
@@ -106,10 +142,14 @@ namespace MTApiService
{ {
executor.NotifyCommandReady(); executor.NotifyCommandReady();
} }
Log.DebugFormat("NotifyCommandReady: end. Notified executor count = {0}", commandExecutors.Count);
} }
private void CommandExecutor_CommandExecuted(object sender, EventArgs e) private void CommandExecutor_CommandExecuted(object sender, EventArgs e)
{ {
Log.Debug("CommandExecutor_CommandExecuted: begin.");
var notify = false; var notify = false;
lock (_locker) lock (_locker)
{ {
@@ -124,14 +164,8 @@ namespace MTApiService
NotifyCommandReady(); NotifyCommandReady();
} }
Log.Debug("CommandExecutor_CommandExecuted: end.");
} }
#endregion #endregion
#region Private Fields
private readonly List<MtExpert> _commandExecutors = new List<MtExpert>();
private readonly Queue<MtCommandTask> _commandTasks = new Queue<MtCommandTask>();
private readonly object _locker = new object();
#endregion
} }
} }
+91 -66
View File
@@ -1,4 +1,5 @@
using System; using System;
using log4net;
namespace MTApiService namespace MTApiService
{ {
@@ -6,6 +7,89 @@ namespace MTApiService
{ {
public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote); public delegate void MtQuoteHandler(MtExpert expert, MtQuote quote);
#region Private Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtExpert));
private readonly IMetaTraderHandler _mtHadler;
private MtCommandTask _commandTask;
private ICommandManager _commandManager;
private readonly object _locker = new object();
#endregion
#region Public Methods
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
{
if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
Quote = quote;
Handle = handle;
_mtHadler = mtHandler;
}
public void Deinit()
{
Log.Debug("Deinit: begin.");
IsEnable = false;
FireOnDeinited();
Log.Debug("Deinit: end.");
}
public void SendResponse(MtResponse response)
{
Log.DebugFormat("SendResponse: begin. response = {0}", response);
_commandTask.SetResult(response);
_commandTask = null;
FireOnCommandExecuted();
Log.Debug("SendResponse: end.");
}
public int GetCommandType()
{
Log.Debug("GetCommandType: called.");
var commandManager = CommandManager;
if (commandManager != null)
{
_commandTask = commandManager.DequeueCommandTask();
}
return _commandTask?.Command?.CommandType ?? 0;
}
public object GetCommandParameter(int index)
{
Log.DebugFormat("GetCommandType: called. index = {0}", index);
var command = _commandTask?.Command;
if (command?.Parameters != null && index >= 0 && index < command.Parameters.Count)
{
return command.Parameters[index];
}
return null;
}
public void SendEvent(MtEvent mtEvent)
{
Log.DebugFormat("SendEvent: begin. event = {0}", mtEvent);
FireOnMtEvent(mtEvent);
Log.Debug("SendEvent: end.");
}
public override string ToString()
{
return $"ExpertHandle = {Handle}";
}
#endregion
#region Properties #region Properties
private MtQuote _quote; private MtQuote _quote;
public MtQuote Quote public MtQuote Quote
@@ -19,7 +103,7 @@ namespace MTApiService
} }
set set
{ {
lock(_locker) lock (_locker)
{ {
_quote = value; _quote = value;
} }
@@ -28,7 +112,7 @@ namespace MTApiService
} }
} }
public int Handle { get; private set; } public int Handle { get; }
private bool _isEnable = true; private bool _isEnable = true;
public bool IsEnable public bool IsEnable
@@ -69,73 +153,21 @@ namespace MTApiService
#endregion #endregion
#region Public Methods
public MtExpert(int handle, MtQuote quote, IMetaTraderHandler mtHandler)
{
Quote = quote;
Handle = handle;
_mtHadler = mtHandler;
}
public void Deinit()
{
IsEnable = false;
FireOnDeinited();
}
public void SendResponse(MtResponse response)
{
_commandTask.SetResult(response);
_commandTask = null;
FireOnCommandExecuted();
}
public int GetCommandType()
{
var commandManager = CommandManager;
if (commandManager != null)
{
_commandTask = commandManager.DequeueCommandTask();
}
return _commandTask != null && _commandTask.Command != null ? _commandTask.Command.CommandType : 0;
}
public object GetCommandParameter(int index)
{
if (_commandTask != null)
{
var command = _commandTask.Command;
if (command != null && command.Parameters != null
&& index >= 0 && index < command.Parameters.Count)
{
return command.Parameters[index];
}
}
return null;
}
public void SendEvent(MtEvent mtEvent)
{
FireOnMtEvent(mtEvent);
}
#endregion
#region IMtCommandExecutor #region IMtCommandExecutor
public void NotifyCommandReady() public void NotifyCommandReady()
{ {
Log.Debug("NotifyCommandReady: begin.");
SendTickToMetaTrader(); SendTickToMetaTrader();
Log.Debug("NotifyCommandReady: end.");
} }
#endregion #endregion
#region Private Methods #region Private Methods
private void SendTickToMetaTrader() private void SendTickToMetaTrader()
{ {
if (_mtHadler != null) _mtHadler.SendTickToMetaTrader(Handle);
{
_mtHadler.SendTickToMetaTrader(Handle);
}
} }
private void FireOnQuoteChanged(MtQuote quote) private void FireOnQuoteChanged(MtQuote quote)
@@ -165,12 +197,5 @@ namespace MTApiService
public event EventHandler CommandExecuted; public event EventHandler CommandExecuted;
public event EventHandler<MtEventArgs> OnMtEvent; public event EventHandler<MtEventArgs> OnMtEvent;
#endregion #endregion
#region Private Fields
private readonly IMetaTraderHandler _mtHadler;
private MtCommandTask _commandTask;
private ICommandManager _commandManager;
private readonly object _locker = new object();
#endregion
} }
} }
+1 -5
View File
@@ -1,8 +1,4 @@
using System; using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService namespace MTApiService
{ {
+1 -5
View File
@@ -1,8 +1,4 @@
using System; using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService namespace MTApiService
{ {
+1 -6
View File
@@ -1,9 +1,4 @@
using System; using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
namespace MTApiService namespace MTApiService
{ {
+1 -5
View File
@@ -1,8 +1,4 @@
using System; using System.Runtime.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace MTApiService namespace MTApiService
{ {
-3
View File
@@ -1,7 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization; using System.Runtime.Serialization;
namespace MTApiService namespace MTApiService
+89 -83
View File
@@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32; using Microsoft.Win32;
using System.Diagnostics; using System.Diagnostics;
@@ -9,12 +7,12 @@ namespace MTApiService
{ {
public class MtRegistryManager public class MtRegistryManager
{ {
private const string SOFTWARE = "Software"; private const string Software = "Software";
private const string APP_NAME = "MtApi"; private const string AppName = "MtApi";
private const string PROFILES_REGKEY = "ConnectionProfiles"; private const string ProfilesRegkey = "ConnectionProfiles";
private const string HOST_REGVALUE_NAME = "Host"; private const string HostRegvalueName = "Host";
private const string PORT_REGVALUE_NAME = "Port"; private const string PortRegvalueName = "Port";
private const string SIGNATURE_REGVALUE_NAME = "MtSignature"; private const string SignatureRegvalueName = "MtSignature";
#region Public Methods #region Public Methods
public static IEnumerable<MtConnectionProfile> LoadConnectionProfiles() public static IEnumerable<MtConnectionProfile> LoadConnectionProfiles()
@@ -53,12 +51,12 @@ namespace MTApiService
string signature = null; string signature = null;
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true); var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey != null) if (softwareRegKey != null)
{ {
using (softwareRegKey) using (softwareRegKey)
{ {
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true); var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey != null) if (appRegKey != null)
{ {
using (appRegKey) using (appRegKey)
@@ -73,7 +71,7 @@ namespace MTApiService
{ {
using (numberKey) using (numberKey)
{ {
signature = numberKey.GetValue(SIGNATURE_REGVALUE_NAME).ToString(); signature = numberKey.GetValue(SignatureRegvalueName).ToString();
} }
} }
} }
@@ -94,7 +92,7 @@ namespace MTApiService
return null; return null;
} }
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true); var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRgKey == null) if (softwareRgKey == null)
return null; return null;
@@ -105,35 +103,33 @@ namespace MTApiService
{ {
//app name //app name
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true); var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
if (appRegKey == null)
if (appRegKey != null)
{ {
appRegKey = softwareRgKey.CreateSubKey(APP_NAME); using (appRegKey)
}
using (appRegKey)
{
//account name
var accountKey = appRegKey.OpenSubKey(accountName, true);
if (accountKey == null)
{ {
accountKey = appRegKey.CreateSubKey(accountName); //account name
} var accountKey = appRegKey.OpenSubKey(accountName, true) ?? appRegKey.CreateSubKey(accountName);
using (accountKey) if (accountKey != null)
{
//account number
var numberKey = accountKey.OpenSubKey(accountNumber, true);
if (numberKey == null)
{ {
numberKey = accountKey.CreateSubKey(accountNumber); using (accountKey)
} {
//account number
var numberKey = accountKey.OpenSubKey(accountNumber, true) ??
accountKey.CreateSubKey(accountNumber);
using (numberKey) if (numberKey != null)
{ {
numberKey.SetValue(SIGNATURE_REGVALUE_NAME, signature); using (numberKey)
{
numberKey.SetValue(SignatureRegvalueName, signature);
retVal = numberKey.ToString(); retVal = numberKey.ToString();
}
}
}
} }
} }
} }
@@ -142,20 +138,19 @@ namespace MTApiService
return retVal; return retVal;
} }
public static bool ExportKey(string RegKey, string SavePath) public static bool ExportKey(string regKey, string savePath)
{ {
string path = "\"" + SavePath + "\""; var path = $"\"{savePath}\"";
string key = "\"" + RegKey + "\""; var key = $"\"{regKey}\"";
Process proc = new Process(); var proc = new Process();
try try
{ {
proc.StartInfo.FileName = "regedit.exe"; proc.StartInfo.FileName = "regedit.exe";
proc.StartInfo.UseShellExecute = false; proc.StartInfo.UseShellExecute = false;
proc = Process.Start("regedit.exe", "/e " + path + " " + key + ""); proc = Process.Start("regedit.exe", "/e " + path + " " + key + "");
if (proc != null) proc?.WaitForExit();
proc.WaitForExit();
} }
catch(Exception) catch(Exception)
{ {
@@ -163,8 +158,7 @@ namespace MTApiService
} }
finally finally
{ {
if (proc != null) proc?.Dispose();
proc.Dispose();
} }
return true; return true;
@@ -177,33 +171,38 @@ namespace MTApiService
{ {
List<MtConnectionProfile> profiles = null; List<MtConnectionProfile> profiles = null;
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true); var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey != null) if (softwareRegKey != null)
{ {
using (softwareRegKey) using (softwareRegKey)
{ {
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true); var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey != null) if (appRegKey != null)
{ {
using (appRegKey) using (appRegKey)
{ {
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true); var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
if (profilesRegKey != null) if (profilesRegKey != null)
{ {
using (profilesRegKey) using (profilesRegKey)
{ {
profiles = new List<MtConnectionProfile>(); profiles = new List<MtConnectionProfile>();
foreach (string profileNameKey in profilesRegKey.GetSubKeyNames()) foreach (var profileNameKey in profilesRegKey.GetSubKeyNames())
{ {
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileNameKey)) var tempKey = profilesRegKey.OpenSubKey(profileNameKey);
if (tempKey != null)
{ {
var profile = new MtConnectionProfile(profileNameKey); using (tempKey)
{
var profile = new MtConnectionProfile(profileNameKey)
{
Host = tempKey.GetValue(HostRegvalueName).ToString(),
Port = (int) tempKey.GetValue(PortRegvalueName)
};
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString(); profiles.Add(profile);
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME); }
profiles.Add(profile);
} }
} }
} }
@@ -220,27 +219,33 @@ namespace MTApiService
{ {
MtConnectionProfile profile = null; MtConnectionProfile profile = null;
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true); var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey != null) if (softwareRegKey != null)
{ {
using (softwareRegKey) using (softwareRegKey)
{ {
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true); var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey != null) if (appRegKey != null)
{ {
using (appRegKey) using (appRegKey)
{ {
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true); var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
if (profilesRegKey != null) if (profilesRegKey != null)
{ {
using (profilesRegKey) using (profilesRegKey)
{ {
using (RegistryKey tempKey = profilesRegKey.OpenSubKey(profileName)) var tempKey = profilesRegKey.OpenSubKey(profileName);
if (tempKey != null)
{ {
profile = new MtConnectionProfile(profileName); using (tempKey)
{
profile = new MtConnectionProfile(profileName)
{
Host = tempKey.GetValue(HostRegvalueName).ToString(),
Port = (int) tempKey.GetValue(PortRegvalueName)
};
profile.Host = tempKey.GetValue(HOST_REGVALUE_NAME).ToString(); }
profile.Port = (int)tempKey.GetValue(PORT_REGVALUE_NAME);
} }
} }
} }
@@ -254,7 +259,7 @@ namespace MTApiService
private static void SaveConnectionProfileToRegistry(MtConnectionProfile profile) private static void SaveConnectionProfileToRegistry(MtConnectionProfile profile)
{ {
RegistryKey softwareRgKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true); var softwareRgKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRgKey == null) if (softwareRgKey == null)
return; return;
@@ -262,29 +267,30 @@ namespace MTApiService
using (softwareRgKey) using (softwareRgKey)
{ {
//app name //app name
var appRegKey = softwareRgKey.OpenSubKey(APP_NAME, true); var appRegKey = softwareRgKey.OpenSubKey(AppName, true) ?? softwareRgKey.CreateSubKey(AppName);
if (appRegKey == null)
if (appRegKey != null)
{ {
appRegKey = softwareRgKey.CreateSubKey(APP_NAME); using (appRegKey)
}
using (appRegKey)
{
//ConnectionProfiles key
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true);
if (profilesRegKey == null)
{ {
profilesRegKey = appRegKey.CreateSubKey(PROFILES_REGKEY); //ConnectionProfiles key
} var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true) ??
appRegKey.CreateSubKey(ProfilesRegkey);
using (profilesRegKey) if (profilesRegKey != null)
{
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
using (profileKey)
{ {
profileKey.SetValue(HOST_REGVALUE_NAME, profile.Host); using (profilesRegKey)
profileKey.SetValue(PORT_REGVALUE_NAME, profile.Port); {
var profileKey = profilesRegKey.CreateSubKey(profile.Name);
if (profileKey != null)
{
using (profileKey)
{
profileKey.SetValue(HostRegvalueName, profile.Host);
profileKey.SetValue(PortRegvalueName, profile.Port);
}
}
}
} }
} }
} }
@@ -293,19 +299,19 @@ namespace MTApiService
private static void DeleteConnectionProfileFromRegistry(string profileName) private static void DeleteConnectionProfileFromRegistry(string profileName)
{ {
var softwareRegKey = Registry.CurrentUser.OpenSubKey(SOFTWARE, true); var softwareRegKey = Registry.CurrentUser.OpenSubKey(Software, true);
if (softwareRegKey == null) if (softwareRegKey == null)
return; return;
using (softwareRegKey) using (softwareRegKey)
{ {
var appRegKey = softwareRegKey.OpenSubKey(APP_NAME, true); var appRegKey = softwareRegKey.OpenSubKey(AppName, true);
if (appRegKey == null) if (appRegKey == null)
return; return;
using (appRegKey) using (appRegKey)
{ {
var profilesRegKey = appRegKey.OpenSubKey(PROFILES_REGKEY, true); var profilesRegKey = appRegKey.OpenSubKey(ProfilesRegkey, true);
if (profilesRegKey == null) if (profilesRegKey == null)
return; return;
+66
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Collections; using System.Collections;
using System.Globalization;
namespace MTApiService namespace MTApiService
{ {
@@ -35,6 +36,11 @@ namespace MTApiService
public int Value { get; private set; } public int Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -49,6 +55,11 @@ namespace MTApiService
public long Value { get; private set; } public long Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -63,6 +74,11 @@ namespace MTApiService
public ulong Value { get; private set; } public ulong Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -77,6 +93,11 @@ namespace MTApiService
public double Value { get; private set; } public double Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString(CultureInfo.CurrentCulture);
}
} }
[DataContract] [DataContract]
@@ -91,6 +112,11 @@ namespace MTApiService
public string Value { get; private set; } public string Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value;
}
} }
[DataContract] [DataContract]
@@ -105,6 +131,11 @@ namespace MTApiService
public bool Value { get; private set; } public bool Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -119,6 +150,11 @@ namespace MTApiService
public double[] Value { get; private set; } public double[] Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -133,6 +169,11 @@ namespace MTApiService
public int[] Value { get; private set; } public int[] Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -147,6 +188,11 @@ namespace MTApiService
public long[] Value { get; private set; } public long[] Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -161,6 +207,11 @@ namespace MTApiService
public ArrayList Value { get; private set; } public ArrayList Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -175,6 +226,11 @@ namespace MTApiService
public MtMqlRates[] Value { get; private set; } public MtMqlRates[] Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -189,6 +245,11 @@ namespace MTApiService
public MtMqlTick Value { get; private set; } public MtMqlTick Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
[DataContract] [DataContract]
@@ -203,6 +264,11 @@ namespace MTApiService
public MtMqlBookInfo[] Value { get; private set; } public MtMqlBookInfo[] Value { get; private set; }
public override object GetValue() { return Value; } public override object GetValue() { return Value; }
public override string ToString()
{
return Value.ToString();
}
} }
} }
+192 -106
View File
@@ -3,17 +3,26 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.ServiceModel; using System.ServiceModel;
using System.Net; using System.Net;
using System.Diagnostics;
using System.ServiceModel.Channels; using System.ServiceModel.Channels;
using System.Net.Sockets; using System.Net.Sockets;
using log4net;
namespace MTApiService namespace MTApiService
{ {
internal class MtServer : IDisposable, IMtApiServer internal class MtServer : IDisposable, IMtApiServer
{ {
#region Constants #region Constants
private const int WAIT_RESPONSE_TIME = 40000; // 40 sec private const int WaitResponseTime = 40000; // 40 sec
private const int STOP_EXPERT_INTERVAL = 1000; // 1 sec private const int StopExpertInterval = 1000; // 1 sec
#endregion
#region Fields
private static readonly ILog Log = LogManager.GetLogger(typeof(MtServer));
private readonly MtService _service;
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
private readonly List<MtExpert> _experts = new List<MtExpert>();
#endregion #endregion
#region ctor #region ctor
@@ -25,99 +34,126 @@ namespace MTApiService
#endregion #endregion
#region Properties #region Properties
public int Port { get; private set; } public int Port { get; }
#endregion #endregion
#region Public Methods #region Public Methods
public void Start() public void Start()
{ {
Log.Debug("Start: begin");
var hostsInitialized = InitHosts(Port); var hostsInitialized = InitHosts(Port);
if (hostsInitialized == false)
{ Log.DebugFormat("Start: end. hostsInitialized = {0}", hostsInitialized);
Debug.WriteLine("Start: InitHosts failed. ");
}
} }
private bool InitHosts(int port) private bool InitHosts(int port)
{ {
Log.DebugFormat("InitHosts: begin. port = {0}", port);
int count;
lock (_hosts) lock (_hosts)
{ {
if (_hosts.Count > 0) if (_hosts.Count > 0)
{
Log.Info("InitHosts: end. Host's has been initialized");
return false; return false;
}
//init local pipe host //init local pipe host
string localUrl = CreateConnectionAddress(null, port, true); var localUrl = CreateConnectionAddress(null, port, true);
ServiceHost localServiceHost = CreateServiceHost(localUrl, true); var localServiceHost = CreateServiceHost(localUrl, true);
if (localServiceHost != null) if (localServiceHost != null)
{ {
_hosts.Add(localServiceHost); _hosts.Add(localServiceHost);
} }
//init network hosts //init network hosts
IPHostEntry ips = Dns.GetHostEntry(Dns.GetHostName()); var dnsHostName = Dns.GetHostName();
if (ips != null) var ips = Dns.GetHostEntry(dnsHostName);
if (ips == null)
{ {
foreach (IPAddress ipAddress in ips.AddressList) Log.WarnFormat("InitHosts: end. Dns.GetHostEntry has returned null for DNS Host Name {0}", dnsHostName);
return false;
}
foreach (var ipAddress in ips.AddressList)
{
if (ipAddress?.AddressFamily == AddressFamily.InterNetwork)
{ {
if (ipAddress != null) var ip = ipAddress.ToString();
var networkUrl = CreateConnectionAddress(ip, port, false);
var serviceHost = CreateServiceHost(networkUrl, false);
if (serviceHost != null)
{ {
if (ipAddress.AddressFamily == AddressFamily.InterNetwork) _hosts.Add(serviceHost);
{
string ip = ipAddress.ToString();
string networkUrl = CreateConnectionAddress(ip, port, false);
ServiceHost serviceHost = CreateServiceHost(networkUrl, false);
if (serviceHost != null)
{
_hosts.Add(serviceHost);
}
}
} }
} }
} }
count = _hosts.Count;
} }
Log.DebugFormat("InitHosts: end. Host's count = {0}", count);
return true; return true;
} }
private ServiceHost CreateServiceHost(string serverUrlAdress, bool local) private ServiceHost CreateServiceHost(string serverUrlAdress, bool local)
{ {
ServiceHost serviceHost = null; Log.DebugFormat("CreateServiceHost: begin. serverUrlAdress = {0}; local = {1}", serverUrlAdress, local);
if (serverUrlAdress != null)
{
try
{
serviceHost = new ServiceHost(_service);
var binding = CreateConnectionBinding(local);
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress); if (serverUrlAdress == null)
serviceHost.Open(); {
} Log.Warn("CreateServiceHost: end. serverUrlAdress is not defined");
catch(Exception e) return null;
{
Debug.WriteLine("CreateServiceHost: Create ServiceHost failed. " + e.Message);
}
} }
ServiceHost serviceHost;
try
{
serviceHost = new ServiceHost(_service);
var binding = CreateConnectionBinding(local);
serviceHost.AddServiceEndpoint(typeof(IMtApi), binding, serverUrlAdress);
serviceHost.Open();
}
catch(Exception e)
{
Log.ErrorFormat("CreateServiceHost: Error! {0}", e.Message);
serviceHost = null;
}
Log.Debug("CreateServiceHost: end.");
return serviceHost; return serviceHost;
} }
public void AddExpert(MtExpert expert) public void AddExpert(MtExpert expert)
{ {
if (expert != null) Log.DebugFormat("AddExpert: begin. expert {0}", expert);
if (expert == null)
{ {
expert.Deinited += expert_Deinited; Log.Warn("AddExpert: end. expert is not defined");
expert.QuoteChanged += expert_QuoteChanged; return;
expert.OnMtEvent += Expert_OnMtEvent;
lock (_experts)
{
_experts.Add(expert);
}
_executorManager.AddCommandExecutor(expert);
_service.OnQuoteAdded(expert.Quote);
} }
expert.Deinited += expert_Deinited;
expert.QuoteChanged += expert_QuoteChanged;
expert.OnMtEvent += Expert_OnMtEvent;
lock (_experts)
{
_experts.Add(expert);
}
_executorManager.AddCommandExecutor(expert);
_service.OnQuoteAdded(expert.Quote);
Log.Debug("AddExpert: end.");
} }
#endregion #endregion
@@ -126,25 +162,30 @@ namespace MTApiService
public MtResponse SendCommand(MtCommand command) public MtResponse SendCommand(MtCommand command)
{ {
MtResponse response = null; Log.DebugFormat("SendCommand: begin. command {0}", command);
if (command != null) if (command == null)
{ {
var task = new MtCommandTask(command); Log.Warn("SendCommand: end. command is not defined");
_executorManager.EnqueueCommandTask(task); return null;
//wait for execute command in MetaTrader
response = task.WaitResult(WAIT_RESPONSE_TIME);
} }
var task = new MtCommandTask(command);
_executorManager.EnqueueCommandTask(task);
//wait for execute command in MetaTrader
var response = task.WaitResult(WaitResponseTime);
return response; return response;
} }
public IEnumerable<MtQuote> GetQuotes() public List<MtQuote> GetQuotes()
{ {
Log.Debug("GetQuotes: called");
lock (_experts) lock (_experts)
{ {
return (from s in _experts select s.Quote); return _experts.Select(s => s.Quote).ToList();
} }
} }
@@ -153,99 +194,127 @@ namespace MTApiService
#region Private Methods #region Private Methods
private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) private void stopTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{ {
var expertsCount = 0; Log.DebugFormat("stopTimer_Elapsed: begin");
int expertsCount;
lock (_experts) lock (_experts)
{ {
expertsCount = _experts.Count(); expertsCount = _experts.Count;
} }
if (expertsCount == 0) if (expertsCount == 0)
{ {
_service.OnStopServer(); _service.OnStopServer();
Log.DebugFormat("stopTimer_Elapsed: experts count is 0. Call Stop().");
Stop(); Stop();
} }
var stopTimer = sender as System.Timers.Timer; var stopTimer = sender as System.Timers.Timer;
if (stopTimer != null) if (stopTimer == null) return;
{
stopTimer.Stop(); stopTimer.Stop();
stopTimer.Elapsed -= stopTimer_Elapsed; stopTimer.Elapsed -= stopTimer_Elapsed;
}
Log.DebugFormat("stopTimer_Elapsed: end");
} }
private string CreateConnectionAddress(string host, int port, bool local) private static string CreateConnectionAddress(string host, int port, bool local)
{ {
Log.DebugFormat("CreateConnectionAddress: begin. host = {0}, port = {1}, local = {2}", host, port, local);
string connectionAddress = null; string connectionAddress = null;
if (local == true) if (local)
{ {
//by Pipe //by Pipe
connectionAddress = "net.pipe://localhost/MtApiService_" + port.ToString(); connectionAddress = "net.pipe://localhost/MtApiService_" + port;
} }
else else
{ {
//by Socket //by Socket
if (host != null) if (host != null)
{ {
connectionAddress = "net.tcp://" + host.ToString() + ":" + port.ToString() + "/MtApiService"; connectionAddress = "net.tcp://" + host + ":" + port + "/MtApiService";
} }
} }
Log.DebugFormat("CreateConnectionAddress: end. connectionAddress = {0}", connectionAddress);
return connectionAddress; return connectionAddress;
} }
private static Binding CreateConnectionBinding(bool local) private static Binding CreateConnectionBinding(bool local)
{ {
Binding connectionBinding = null; Log.DebugFormat("CreateConnectionBinding: begin. local = {0}", local);
if (local == true) Binding connectionBinding;
if (local)
{ {
//by Pipe //by Pipe
var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None); var bind = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None)
bind.MaxReceivedMessageSize = 2147483647; {
bind.MaxBufferSize = 2147483647; MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required // Commented next statement since it is not required
bind.MaxBufferPoolSize = 2147483647;
bind.ReaderQuotas.MaxArrayLength = 2147483647;
bind.ReaderQuotas.MaxBytesPerRead = 2147483647;
bind.ReaderQuotas.MaxDepth = 2147483647;
bind.ReaderQuotas.MaxStringContentLength = 2147483647;
bind.ReaderQuotas.MaxNameTableCharCount = 2147483647;
connectionBinding = bind; connectionBinding = bind;
} }
else else
{ {
//by Socket //by Socket
var bind = new NetTcpBinding(SecurityMode.None); var bind = new NetTcpBinding(SecurityMode.None)
bind.MaxReceivedMessageSize = 2147483647; {
bind.MaxBufferSize = 2147483647; MaxReceivedMessageSize = 2147483647,
MaxBufferSize = 2147483647,
MaxBufferPoolSize = 2147483647,
ReaderQuotas =
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxStringContentLength = 2147483647,
MaxNameTableCharCount = 2147483647
}
};
// Commented next statement since it is not required // Commented next statement since it is not required
bind.MaxBufferPoolSize = 2147483647;
bind.ReaderQuotas.MaxArrayLength = 2147483647;
bind.ReaderQuotas.MaxBytesPerRead = 2147483647;
bind.ReaderQuotas.MaxDepth = 2147483647;
bind.ReaderQuotas.MaxStringContentLength = 2147483647;
bind.ReaderQuotas.MaxNameTableCharCount = 2147483647;
connectionBinding = bind; connectionBinding = bind;
} }
Log.Debug("CreateConnectionBinding: end.");
return connectionBinding; return connectionBinding;
} }
private void Stop() private void Stop()
{ {
Log.Debug("Stop: begin.");
_executorManager.Stop(); _executorManager.Stop();
lock (_hosts) lock (_hosts)
{ {
if (_hosts.Count == 0) if (_hosts.Count == 0)
{
Log.Debug("Stop: end. Host count is 0.");
return; return;
}
try try
{ {
@@ -254,15 +323,18 @@ namespace MTApiService
host.Close(); host.Close();
} }
} }
catch (TimeoutException) catch (TimeoutException ex)
{ {
Log.ErrorFormat("Stop: TimeoutException - {0}", ex.Message);
foreach (var host in _hosts) foreach (var host in _hosts)
{ {
host.Abort(); host.Abort();
} }
} }
catch (Exception) catch (Exception ex)
{ {
Log.ErrorFormat("Stop: Exception - {0}", ex.Message);
// ignored // ignored
} }
finally finally
@@ -272,20 +344,27 @@ namespace MTApiService
} }
FireOnStopped(); FireOnStopped();
Log.Debug("Stop: end.");
} }
private void expert_Deinited(object sender, EventArgs e) private void expert_Deinited(object sender, EventArgs e)
{ {
if (sender == null) Log.Debug("expert_Deinited: begin.");
return;
var expert = (MtExpert)sender; var expert = sender as MtExpert;
var expertsCount = 0; if (expert == null)
{
Log.Warn("expert_Deinited: end. Expert is not defined.");
return;
}
int expertsCount;
lock (_experts) lock (_experts)
{ {
_experts.Remove(expert); _experts.Remove(expert);
expertsCount = _experts.Count(); expertsCount = _experts.Count;
} }
_executorManager.RemoveCommandExecutor(expert); _executorManager.RemoveCommandExecutor(expert);
@@ -299,19 +378,29 @@ namespace MTApiService
{ {
var stopTimer = new System.Timers.Timer(); var stopTimer = new System.Timers.Timer();
stopTimer.Elapsed += stopTimer_Elapsed; stopTimer.Elapsed += stopTimer_Elapsed;
stopTimer.Interval = STOP_EXPERT_INTERVAL; stopTimer.Interval = StopExpertInterval;
stopTimer.Start(); stopTimer.Start();
} }
Log.Debug("expert_Deinited: end.");
} }
private void expert_QuoteChanged(MtExpert expert, MtQuote quote) private void expert_QuoteChanged(MtExpert expert, MtQuote quote)
{ {
Log.DebugFormat("expert_QuoteChanged: begin. expert = {0}, quote = {1}", expert, quote);
_service.QuoteUpdate(quote); _service.QuoteUpdate(quote);
Log.Debug("expert_QuoteChanged: end.");
} }
private void Expert_OnMtEvent(object sender, MtEventArgs e) private void Expert_OnMtEvent(object sender, MtEventArgs e)
{ {
Log.DebugFormat("Expert_OnMtEvent: begin. event = {0}", e.Event);
_service.OnMtEvent(e.Event); _service.OnMtEvent(e.Event);
Log.Debug("Expert_OnMtEvent: end.");
} }
private void FireOnStopped() private void FireOnStopped()
@@ -328,16 +417,13 @@ namespace MTApiService
#region IDispose #region IDispose
public void Dispose() public void Dispose()
{ {
Log.Debug("Dispose: begin");
Stop(); Stop();
Log.Debug("Dispose: end.");
} }
#endregion #endregion
#region Fields
private readonly MtService _service;
private readonly List<ServiceHost> _hosts = new List<ServiceHost>();
private readonly MtCommandExecutorManager _executorManager = new MtCommandExecutorManager();
private readonly List<MtExpert> _experts = new List<MtExpert>();
#endregion
} }
} }
+100 -57
View File
@@ -1,21 +1,26 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using log4net;
using System.Text;
using System.ServiceModel;
using System.Net;
using System.Diagnostics;
namespace MTApiService namespace MTApiService
{ {
public class MtServerInstance public class MtServerInstance
{ {
#region Init_Instance #region Fields
private const string LogProfileName = "MtApiService";
static readonly MtServerInstance mInstance = new MtServerInstance(); private static readonly ILog Log = LogManager.GetLogger(typeof(MtServerInstance));
private static readonly MtServerInstance Instance = new MtServerInstance();
private readonly Dictionary<int, MtServer> _servers = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> _experts = new Dictionary<int, MtExpert>();
#endregion
#region Init Instance
private MtServerInstance() private MtServerInstance()
{ {
LogConfigurator.Setup(LogProfileName);
} }
static MtServerInstance() static MtServerInstance()
@@ -24,7 +29,7 @@ namespace MTApiService
public static MtServerInstance GetInstance() public static MtServerInstance GetInstance()
{ {
return mInstance; return Instance;
} }
#endregion #endregion
@@ -33,20 +38,23 @@ namespace MTApiService
#region Public Methods #region Public Methods
public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler) public void InitExpert(int expertHandle, int port, string symbol, double bid, double ask, IMetaTraderHandler mtHandler)
{ {
Debug.WriteLine("MtApiServerInstance::InitExpert: symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port); if (mtHandler == null)
throw new ArgumentNullException(nameof(mtHandler));
MtServer server = null; Log.InfoFormat("InitExpert: begin. symbol = {0}, expertHandle = {1}, port = {2}", symbol, expertHandle, port);
lock (mServersDictionary)
MtServer server;
lock (_servers)
{ {
if (mServersDictionary.ContainsKey(port)) if (_servers.ContainsKey(port))
{ {
server = mServersDictionary[port]; server = _servers[port];
} }
else else
{ {
server = new MtServer(port); server = new MtServer(port);
server.Stopped += new EventHandler(server_Stopped); server.Stopped += server_Stopped;
mServersDictionary[port] = server; _servers[port] = server;
server.Start(); server.Start();
} }
@@ -54,26 +62,28 @@ namespace MTApiService
var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler); var expert = new MtExpert(expertHandle, new MtQuote(symbol, bid, ask), mtHandler);
lock (mExpertsDictionary) lock (_experts)
{ {
mExpertsDictionary[expert.Handle] = expert; _experts[expert.Handle] = expert;
} }
server.AddExpert(expert); server.AddExpert(expert);
Log.Info("InitExpert: end");
} }
public void DeinitExpert(int expertHandle) public void DeinitExpert(int expertHandle)
{ {
Debug.WriteLine("MtApiServerInstance::DeinitExpert: expertHandle = {0}", expertHandle); Log.InfoFormat("DeinitExpert: begin. symbol = {0}", expertHandle);
MtExpert expert = null; MtExpert expert = null;
lock (mExpertsDictionary) lock (_experts)
{ {
if (mExpertsDictionary.ContainsKey(expertHandle) == true) if (_experts.ContainsKey(expertHandle))
{ {
expert = mExpertsDictionary[expertHandle]; expert = _experts[expertHandle];
mExpertsDictionary.Remove(expertHandle); _experts.Remove(expertHandle);
} }
} }
@@ -81,110 +91,143 @@ namespace MTApiService
{ {
expert.Deinit(); expert.Deinit();
} }
else
{
Log.WarnFormat("DeinitExpert: expert with id {0} has not been found.", expertHandle);
}
Log.Info("DeinitExpert: end");
} }
public void SendQuote(int expertHandle, string symbol, double bid, double ask) public void SendQuote(int expertHandle, string symbol, double bid, double ask)
{ {
Debug.WriteLine("MtApiServerInstance::SendQuote: enter. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask); Log.DebugFormat("SendQuote: begin. symbol = {0}, bid = {1}, ask = {2}", symbol, bid, ask);
MtExpert expert = null; MtExpert expert;
lock (mExpertsDictionary) lock (_experts)
{ {
expert = mExpertsDictionary[expertHandle]; expert = _experts[expertHandle];
} }
if (expert != null) if (expert != null)
{ {
expert.Quote = new MtQuote(symbol, bid, ask); expert.Quote = new MtQuote(symbol, bid, ask);
} }
else
{
Log.WarnFormat("SendQuote: expert with id {0} has not been found.", expertHandle);
}
Debug.WriteLine("MtApiServerInstance::SendQuote: finish."); Log.Debug("SendQuote: end");
} }
public void SendEvent(int expertHandle, int eventType, string payload) public void SendEvent(int expertHandle, int eventType, string payload)
{ {
Debug.WriteLine("MtApiServerInstance::SendEvent called. eventType = {0}, payload = {1}", eventType, payload); Log.DebugFormat("SendEvent: begin. eventType = {0}, payload = {1}", eventType, payload);
MtExpert expert = null; MtExpert expert;
lock (mExpertsDictionary) lock (_experts)
{ {
expert = mExpertsDictionary[expertHandle]; expert = _experts[expertHandle];
} }
if (expert != null) if (expert != null)
{ {
expert.SendEvent(new MtEvent(eventType, payload)); expert.SendEvent(new MtEvent(eventType, payload));
} }
else
{
Log.WarnFormat("SendEvent: expert with id {0} has not been found.", expertHandle);
}
Debug.WriteLine("MtApiServerInstance::SendEvent: finished"); Log.Debug("SendEvent: end");
} }
public void SendResponse(int expertHandle, MtResponse response) public void SendResponse(int expertHandle, MtResponse response)
{ {
Debug.WriteLine("MtApiServerInstance::SendResponse: id = {0}, response = {1}", expertHandle, response); Log.DebugFormat("SendResponse: begin. id = {0}, response = {1}", expertHandle, response);
MtExpert expert = null; MtExpert expert;
lock (mExpertsDictionary) lock (_experts)
{ {
expert = mExpertsDictionary[expertHandle]; expert = _experts[expertHandle];
} }
if (expert != null) if (expert != null)
{ {
expert.SendResponse(response); expert.SendResponse(response);
} }
else
{
Log.WarnFormat("SendResponse: expert with id {0} has not been found.", expertHandle);
}
Debug.WriteLine("MtApiServerInstance::SendResponse: finish"); Log.Debug("SendResponse: end");
} }
public int GetCommandType(int expertHandle) public int GetCommandType(int expertHandle)
{ {
Debug.WriteLine("MtApiServerInstance::GetCommandType: expertHandle = {0}", expertHandle); Log.DebugFormat("GetCommandType: begin. expertHandle = {0}", expertHandle);
MtExpert expert = null; MtExpert expert;
lock (mExpertsDictionary) lock (_experts)
{ {
expert = mExpertsDictionary[expertHandle]; expert = _experts[expertHandle];
} }
return (expert != null) ? expert.GetCommandType() : 0; if (expert == null)
{
Log.WarnFormat("GetCommandType: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetCommandType() ?? 0;
Log.DebugFormat("GetCommandType: end. retval = {0}", retval);
return retval;
} }
public object GetCommandParameter(int expertHandle, int index) public object GetCommandParameter(int expertHandle, int index)
{ {
Debug.WriteLine("MtApiServerInstance::GetCommandParameter: expertHandle = {0}, index = {1}", expertHandle, index); Log.DebugFormat("GetCommandParameter: begin. expertHandle = {0}, index = {1}", expertHandle, index);
MtExpert expert = null; MtExpert expert;
lock (mExpertsDictionary) lock (_experts)
{ {
expert = mExpertsDictionary[expertHandle]; expert = _experts[expertHandle];
} }
return (expert != null) ? expert.GetCommandParameter(index) : null; if (expert == null)
{
Log.WarnFormat("GetCommandParameter: expert with id {0} has not been found.", expertHandle);
}
var retval = expert?.GetCommandParameter(index);
Log.DebugFormat("GetCommandParameter: end. retval = {0}", retval);
return retval;
} }
#endregion #endregion
#region Private Methods #region Private Methods
private void server_Stopped(object sender, EventArgs e) private void server_Stopped(object sender, EventArgs e)
{ {
MtServer server = (MtServer)sender; var server = (MtServer)sender;
server.Stopped -= server_Stopped; server.Stopped -= server_Stopped;
var port = server.Port; var port = server.Port;
lock (mServersDictionary)
Log.InfoFormat("server_Stopped: port = {0}", port);
lock (_servers)
{ {
if (mServersDictionary.ContainsKey(port)) if (_servers.ContainsKey(port))
{ {
mServersDictionary.Remove(port); _servers.Remove(port);
} }
} }
} }
#endregion #endregion
#region Fields
private readonly MtRegistryManager mConnectionManager = new MtRegistryManager();
private readonly Dictionary<int, MtServer> mServersDictionary = new Dictionary<int, MtServer>();
private readonly Dictionary<int, MtExpert> mExpertsDictionary = new Dictionary<int, MtExpert>();
#endregion
} }
} }
+96 -45
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.ServiceModel; using System.ServiceModel;
using System.Threading; using System.Threading;
using log4net;
namespace MTApiService namespace MTApiService
{ {
@@ -18,7 +19,7 @@ namespace MTApiService
MtResponse SendCommand(MtCommand command); MtResponse SendCommand(MtCommand command);
[OperationContract] [OperationContract]
IEnumerable<MtQuote> GetQuotes(); List<MtQuote> GetQuotes();
} }
[ServiceContract] [ServiceContract]
@@ -46,107 +47,149 @@ namespace MTApiService
InstanceContextMode = InstanceContextMode.Single)] InstanceContextMode = InstanceContextMode.Single)]
public sealed class MtService : IMtApi public sealed class MtService : IMtApi
{ {
private static readonly ILog Log = LogManager.GetLogger(typeof(MtService));
public MtService(IMtApiServer serverCallback) public MtService(IMtApiServer serverCallback)
{ {
if (serverCallback == null) if (serverCallback == null)
throw new ArgumentNullException("serverCallback"); throw new ArgumentNullException(nameof(serverCallback));
mServer = serverCallback; _server = serverCallback;
} }
#region IMtApi #region IMtApi
public bool Connect() public bool Connect()
{ {
bool connected = false; Log.Debug("Connect: begin");
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>(); var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
if (callback != null) if (callback == null)
{ {
Log.Warn("Connect: end. Callback is not definded.");
return false;
}
var connected = false;
try
{
_clientsLocker.AcquireWriterLock(10000);
try try
{ {
mClientsLocker.AcquireWriterLock(10000); if (_clientCallbacks.Contains(callback) == false)
_clientCallbacks.Add(callback);
try connected = true;
{
if (mClientCallbacks.Contains(callback) == false)
mClientCallbacks.Add(callback);
connected = true;
}
finally
{
mClientsLocker.ReleaseWriterLock();
}
} }
catch (ApplicationException) finally
{ {
_clientsLocker.ReleaseWriterLock();
} }
} }
catch (ApplicationException ex)
{
Log.ErrorFormat("Connect: ApplicationException - {0}", ex.Message);
}
Log.DebugFormat("Connect: end. connected = {0}", connected);
return connected; return connected;
} }
public void Disconnect() public void Disconnect()
{ {
IMtApiCallback callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>(); Log.Debug("Disconnect: begin");
if (callback != null) var callback = OperationContext.Current.GetCallbackChannel<IMtApiCallback>();
if (callback == null)
{ {
Log.Warn("Disconnect: end. Callback is not definded.");
return;
}
try
{
_clientsLocker.AcquireWriterLock(10000);
try try
{ {
mClientsLocker.AcquireWriterLock(10000); _clientCallbacks.Remove(callback);
try
{
mClientCallbacks.Remove(callback);
}
finally
{
mClientsLocker.ReleaseWriterLock();
}
} }
catch (ApplicationException) finally
{ {
_clientsLocker.ReleaseWriterLock();
} }
} }
catch (ApplicationException ex)
{
Log.ErrorFormat("Disconnect: ApplicationException - {0}", ex.Message);
}
Log.Debug("Disconnect: end.");
} }
public MtResponse SendCommand(MtCommand command) public MtResponse SendCommand(MtCommand command)
{ {
return mServer.SendCommand(command); Log.DebugFormat("SendCommand: called. command = {0}", command);
return _server.SendCommand(command);
} }
public IEnumerable<MtQuote> GetQuotes() public List<MtQuote> GetQuotes()
{ {
return mServer.GetQuotes(); Log.Debug("GetQuotes: called.");
return _server.GetQuotes();
} }
#endregion #endregion
#region Public Methods #region Public Methods
public void OnStopServer() public void OnStopServer()
{ {
Log.Debug("OnStopServer: begin.");
ExecuteCallbackAction(a => a.OnServerStopped()); ExecuteCallbackAction(a => a.OnServerStopped());
Log.Debug("OnStopServer: end.");
} }
public void QuoteUpdate(MtQuote quote) public void QuoteUpdate(MtQuote quote)
{ {
Log.Debug("QuoteUpdate: begin.");
ExecuteCallbackAction(a => a.OnQuoteUpdate(quote)); ExecuteCallbackAction(a => a.OnQuoteUpdate(quote));
Log.Debug("QuoteUpdate: end.");
} }
public void OnQuoteAdded(MtQuote quote) public void OnQuoteAdded(MtQuote quote)
{ {
Log.Debug("OnQuoteAdded: begin.");
ExecuteCallbackAction(a => a.OnQuoteAdded(quote)); ExecuteCallbackAction(a => a.OnQuoteAdded(quote));
Log.Debug("OnQuoteAdded: end.");
} }
public void OnQuoteRemoved(MtQuote quote) public void OnQuoteRemoved(MtQuote quote)
{ {
Log.Debug("OnQuoteRemoved: begin.");
ExecuteCallbackAction(a => a.OnQuoteRemoved(quote)); ExecuteCallbackAction(a => a.OnQuoteRemoved(quote));
Log.Debug("OnQuoteRemoved: end.");
} }
public void OnMtEvent(MtEvent mtEvent) public void OnMtEvent(MtEvent mtEvent)
{ {
Log.Debug("OnMtEvent: begin.");
ExecuteCallbackAction(a => a.OnMtEvent(mtEvent)); ExecuteCallbackAction(a => a.OnMtEvent(mtEvent));
Log.Debug("OnMtEvent: end.");
} }
#endregion #endregion
@@ -154,22 +197,26 @@ namespace MTApiService
private void ExecuteCallbackAction(Action<IMtApiCallback> action) private void ExecuteCallbackAction(Action<IMtApiCallback> action)
{ {
Log.Debug("ExecuteCallbackAction: begin.");
try try
{ {
mClientsLocker.AcquireReaderLock(2000); _clientsLocker.AcquireReaderLock(2000);
List<IMtApiCallback> crashedClientCallbacks = null; List<IMtApiCallback> crashedClientCallbacks = null;
try try
{ {
foreach (var callback in mClientCallbacks) foreach (var callback in _clientCallbacks)
{ {
try try
{ {
action(callback); action(callback);
} }
catch (Exception) catch (Exception ex)
{ {
Log.ErrorFormat("ExecuteCallbackAction: Exception - {0}", ex.Message);
if (crashedClientCallbacks == null) if (crashedClientCallbacks == null)
crashedClientCallbacks = new List<IMtApiCallback>(); crashedClientCallbacks = new List<IMtApiCallback>();
@@ -179,29 +226,33 @@ namespace MTApiService
if (crashedClientCallbacks != null) if (crashedClientCallbacks != null)
{ {
Log.WarnFormat("ExecuteCallbackAction: crashed callback count = {0}", crashedClientCallbacks.Count);
foreach (var crashedCallback in crashedClientCallbacks) foreach (var crashedCallback in crashedClientCallbacks)
{ {
mClientCallbacks.Remove(crashedCallback); _clientCallbacks.Remove(crashedCallback);
} }
} }
} }
finally finally
{ {
mClientsLocker.ReleaseReaderLock(); _clientsLocker.ReleaseReaderLock();
} }
} }
catch (ApplicationException) catch (ApplicationException ex)
{ {
//TODO: add logging Log.ErrorFormat("ExecuteCallbackAction: ApplicationException - {0}", ex.Message);
} }
Log.Debug("ExecuteCallbackAction: end.");
} }
#endregion #endregion
#region Fields #region Fields
private readonly IMtApiServer mServer; private readonly IMtApiServer _server;
private readonly List<IMtApiCallback> mClientCallbacks = new List<IMtApiCallback>(); private readonly List<IMtApiCallback> _clientCallbacks = new List<IMtApiCallback>();
private readonly ReaderWriterLock mClientsLocker = new ReaderWriterLock(); private readonly ReaderWriterLock _clientsLocker = new ReaderWriterLock();
#endregion #endregion
} }
} }
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="ILMerge" version="2.13.0307" targetFramework="net40" />
<package id="log4net" version="2.0.5" targetFramework="net40" />
<package id="MSBuild.ILMerge.Task" version="1.0.5" targetFramework="net40" />
</packages>
+4
View File
@@ -22,6 +22,8 @@ namespace MtApi
//Special constant //Special constant
public const int NULL = 0; public const int NULL = 0;
public const int EMPTY = -1; public const int EMPTY = -1;
private const string LogProfileName = "MtApiClient";
#endregion #endregion
#region Private Fields #region Private Fields
@@ -34,6 +36,8 @@ namespace MtApi
public MtApiClient() public MtApiClient()
{ {
LogConfigurator.Setup(LogProfileName);
_client.QuoteAdded += _client_QuoteAdded; _client.QuoteAdded += _client_QuoteAdded;
_client.QuoteRemoved += _client_QuoteRemoved; _client.QuoteRemoved += _client_QuoteRemoved;
_client.QuoteUpdated += _client_QuoteUpdated; _client.QuoteUpdated += _client_QuoteUpdated;
+4 -1
View File
@@ -22,6 +22,7 @@ namespace MtApi5
#endregion #endregion
private const char ParamSeparator = ';'; private const char ParamSeparator = ';';
private const string LogProfileName = "MtApi5Client";
public delegate void QuoteHandler(object sender, string symbol, double bid, double ask); public delegate void QuoteHandler(object sender, string symbol, double bid, double ask);
@@ -34,6 +35,8 @@ namespace MtApi5
#region Public Methods #region Public Methods
public MtApi5Client() public MtApi5Client()
{ {
LogConfigurator.Setup(LogProfileName);
ConnectionState = Mt5ConnectionState.Disconnected; ConnectionState = Mt5ConnectionState.Disconnected;
_client.QuoteAdded += mClient_QuoteAdded; _client.QuoteAdded += mClient_QuoteAdded;
@@ -1492,7 +1495,7 @@ namespace MtApi5
throw new Exception(ex.Message, ex); throw new Exception(ex.Message, ex);
} }
var responseValue = response.GetValue(); var responseValue = response?.GetValue();
return responseValue != null ? (T) responseValue : default(T); return responseValue != null ? (T) responseValue : default(T);
} }
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
@@ -10,8 +10,9 @@
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>MtApi5TestClient</RootNamespace> <RootNamespace>MtApi5TestClient</RootNamespace>
<AssemblyName>MtApi5TestClient</AssemblyName> <AssemblyName>MtApi5TestClient</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
@@ -25,6 +26,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<PlatformTarget>x86</PlatformTarget> <PlatformTarget>x86</PlatformTarget>
@@ -34,6 +36,7 @@
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -50,6 +53,7 @@
<CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets> <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
<OutputPath>bin\Release\</OutputPath> <OutputPath>bin\Release\</OutputPath>
@@ -67,6 +71,7 @@
<CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories> <CodeAnalysisRuleDirectories>;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules</CodeAnalysisRuleDirectories>
<CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules> <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
<CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules> <CodeAnalysisFailOnMissingRules>false</CodeAnalysisFailOnMissingRules>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
@@ -124,6 +129,7 @@
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource> </EmbeddedResource>
<None Include="app.config" />
<None Include="Properties\Settings.settings"> <None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator> <Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput> <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+11 -19
View File
@@ -1,15 +1,15 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.18034 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace MtApi5TestClient.Properties namespace MtApi5TestClient.Properties {
{ using System;
/// <summary> /// <summary>
@@ -22,28 +22,23 @@ namespace MtApi5TestClient.Properties
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources internal class Resources {
{
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() internal Resources() {
{
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager internal static global::System.Resources.ResourceManager ResourceManager {
{ get {
get if (object.ReferenceEquals(resourceMan, null)) {
{
if ((resourceMan == null))
{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MtApi5TestClient.Properties.Resources", typeof(Resources).Assembly); global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MtApi5TestClient.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp; resourceMan = temp;
} }
@@ -56,14 +51,11 @@ namespace MtApi5TestClient.Properties
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
/// </summary> /// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture internal static global::System.Globalization.CultureInfo Culture {
{ get {
get
{
return resourceCulture; return resourceCulture;
} }
set set {
{
resourceCulture = value; resourceCulture = value;
} }
} }
+6 -10
View File
@@ -1,28 +1,24 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// This code was generated by a tool. // This code was generated by a tool.
// Runtime Version:4.0.30319.18034 // Runtime Version:4.0.30319.42000
// //
// Changes to this file may cause incorrect behavior and will be lost if // Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated. // the code is regenerated.
// </auto-generated> // </auto-generated>
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
namespace MtApi5TestClient.Properties namespace MtApi5TestClient.Properties {
{
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
{
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default public static Settings Default {
{ get {
get
{
return defaultInstance; return defaultInstance;
} }
} }
+3
View File
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>