using System.Threading;
using TradeIdeas.TIProData.Interfaces;
namespace TradeIdeas.TIProData
{
///
/// IConnectionMaster gives a high level view of the connection. Most
/// parts of the code will only need to talk with this object, and its
/// exported members to talk with the server.
///
/// The next level down is the ConnectionLifeCycle object. This is
/// very generic and is responsible for creating and destroying the
/// TalkWithServer objects, which are the next lower level. Those
/// create a fairly generic server connection. ConnectionMaster
/// takes care of other things, like logging in at appropriate times.
/// When the main program asks to send a single message, the
/// IConnectionMaster object might first send a login message then
/// send the message requested by the main program.
///
/// In the Delphi code all of the functions of this object, and the
/// objects it owns were all part of one class. The C# version
/// splits the work into more pieces. IConnectionMaster is very
/// small. Most it just owns all of the things which should exist
/// exactly once per connection.
///
/// It is perfectly reasonable to create more than one ConnectionMaster
/// object. That was not possible in Delphi, mostly as a convenience.
/// It was easier to have just one place to look for this object.
/// Now we rely on the main program to create an appropriate variable
/// to store this object.
///
public class ConnectionMaster : IConnectionMaster
{
///
/// This is what automatically reconnects, when required.
///
private ConnectionLifeCycle _connectionLifeCycle;
///
/// This lets you set the username and related items for the connection.
///
public ILoginManager LoginManager { get; private set; }
///
/// This provides ping statistics, if required.
/// This is sometimes required to keep the connection alive.
///
public PingManager PingManager { get; private set; }
///
/// This is a convenent way to send messages. It helps manage retries, among
/// other things.
///
public ISendManager SendManager { get; private set; }
///
/// This takes care of reading and setting symbol lists.
///
public ListManager ListManager { get; private set; }
///
/// This is the way to request streaming data for an alert window.
///
public StreamingAlertsManager StreamingAlertsManager { get; private set; }
///
/// This is the way to request historical alerts.
///
public HistoryManager HistoryManager { get; private set; }
///
/// This is the way to request historical top list data.
///
/// At one time this was also used for streaming data.
/// TopListRequest is now the preferred way to get streaming or non-historical snapshot data.
///
public TopListManager TopListManager { get; private set; }
///
/// This accesses the company name and exchange. We cache it so we can access it
/// quickly and we don't send a lot of duplicate requests to the server.
///
public ISymbolDetailsCacheManager SymbolDetailsCacheManager { get; private set; }
///
/// This is the way to run the OddsMaker.
///
public OddsMakerManager OddsMakerManager { get; private set; }
///
/// This is the preferred way to request icons and the like.
///
public ImageCacheManager ImageCacheManager { get; private set; }
///
/// This is the way to get the company profile text
///
public CompanyProfileManager CompanyProfileManager { get; private set; }
///
/// This is the way to get insider trades
///
public InsidersManager InsidersManager { get; private set; }
///
/// This provides limited access to the connection life cycle. The main program
/// can use this to offer connection instructions or to monitor the status of the
/// connection.
///
public ConnectionBase ConnectionBase { get { return _connectionLifeCycle; } }
///
/// This is related to TIQ-Like stuff such as RBI, GBI
///
public TraditionalAlertsManager TraditionalAlertsManager { get; private set; }
///
/// Constructor for the connection master.
///
public ConnectionMaster()
{
_connectionLifeCycle = new ConnectionLifeCycle();
// Initialize the login manager before anything else so it will be the first
// one to get callbacks from the connection life cycle. We want to send the
// login command first, before any other commands.
LoginManager = new LoginManager(_connectionLifeCycle);
PingManager = new PingManager(_connectionLifeCycle);
SendManager = new SendManager(_connectionLifeCycle, LoginManager);
ListManager = new ListManager(_connectionLifeCycle, SendManager);
StreamingAlertsManager = new StreamingAlertsManager(_connectionLifeCycle, SendManager);
HistoryManager = new HistoryManager(_connectionLifeCycle);
TopListManager = new TopListManager(_connectionLifeCycle);
SymbolDetailsCacheManager = new SymbolDetailsCacheManager(SendManager);
OddsMakerManager = new OddsMakerManager(SendManager);
ImageCacheManager = new ImageCacheManager(SendManager);
CompanyProfileManager = new CompanyProfileManager(SendManager);
InsidersManager = new InsidersManager(SendManager);
TraditionalAlertsManager = new TraditionalAlertsManager(SendManager);
Interlocked.CompareExchange(ref _first, this, null);
}
///
/// Throw away the resources. Can't use this object again after this.
/// It is safe to call this more than once.
///
/// You don't usually call Dispose(). Typically you create a IConnectionMaster once
/// when the program first starts and use it forever. However, if you do choose to
/// create lots of these, consider calling Dispose() to clean up memory.
///
public void Dispose()
{
if (null != _connectionLifeCycle)
_connectionLifeCycle.Dispose();
//SoftReset();
// Calling SoftReset from the GUI lead to a deadlock. The thread will
// disconnect the socket soon enough, and that's all we really need.
}
///
/// The destructor calls Dispose().
///
~ConnectionMaster()
{
Dispose();
}
private static IConnectionMaster _first;
///
/// A reference to the first IConnectionMaster created.
///
/// You have a lot of freedom with IConnectionMaster object. You can create as many as you need.
/// You can use multiple at once. You can Destroy() old ones. But in practice most programs only
/// use one of these. And it can be a pain for every library to find the IConnectionMaster created
/// by the main program.
///
/// This always points to the first IConnectionMaster object created. Chances are, that's what
/// you want.
///
public static IConnectionMaster First { get { return _first; } }
}
}