Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored IOC class, Platform clases and updated ablyrealtime and ablyrest for the same #1254

Merged
merged 12 commits into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 5 additions & 10 deletions src/IO.Ably.Android/Platform.cs
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
using IO.Ably.Transport;
using System.Net.NetworkInformation;
using IO.Ably.Push;
using System.Net.NetworkInformation;
using IO.Ably.Realtime;

namespace IO.Ably
{
internal class Platform : IPlatform
{
private static readonly object _lock = new object();

internal static bool HookedUpToNetworkEvents { get; private set; }
public Agent.PlatformRuntime PlatformId => Agent.PlatformRuntime.XamarinAndroid;
public bool SyncContextDefault => true;
public ITransportFactory TransportFactory => null;

public IMobileDevice MobileDevice { get; set; }
private static readonly object Lock = new object();

internal static bool HookedUpToNetworkEvents { get; set; }

public void RegisterOsNetworkStateChanged(ILogger logger)
{
lock (_lock)
lock (Lock)
{
if (HookedUpToNetworkEvents == false)
{
Expand Down
24 changes: 4 additions & 20 deletions src/IO.Ably.NETFramework/Platform.cs
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
using IO.Ably.Transport;
using System.Net.NetworkInformation;
using IO.Ably.Push;
using System.Net.NetworkInformation;
using IO.Ably.Realtime;

namespace IO.Ably
{
internal class Platform : IPlatform
{
private static readonly object _lock = new object();

static Platform()
{
Initialize();
}

internal static bool HookedUpToNetworkEvents { get; private set; }

public Agent.PlatformRuntime PlatformId => Agent.PlatformRuntime.Framework;

public ITransportFactory TransportFactory => null;

public IMobileDevice MobileDevice { get; set; }
private static readonly object Lock = new object();

internal static void Initialize()
{
HookedUpToNetworkEvents = false;
}
internal static bool HookedUpToNetworkEvents { get; set; }

public void RegisterOsNetworkStateChanged(ILogger logger)
{
lock (_lock)
lock (Lock)
{
if (HookedUpToNetworkEvents == false)
{
Expand Down
20 changes: 2 additions & 18 deletions src/IO.Ably.NETStandard20/Platform.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,10 @@
using System.Net.NetworkInformation;
using IO.Ably.Push;
using IO.Ably.Realtime;
using IO.Ably.Transport;

namespace IO.Ably
{
internal class Platform : IPlatform
{
private static readonly object Lock = new object();

static Platform()
{
Initialize();
}

internal static bool HookedUpToNetworkEvents { get; private set; }

// Defined as per https://learn.microsoft.com/en-us/dotnet/standard/frameworks#preprocessor-symbols
#if NET6_0
public Agent.PlatformRuntime PlatformId => Agent.PlatformRuntime.Net6;
Expand All @@ -25,14 +14,9 @@ static Platform()
public Agent.PlatformRuntime PlatformId => Agent.PlatformRuntime.Netstandard20;
#endif

public ITransportFactory TransportFactory => null;

public IMobileDevice MobileDevice { get; set; }
private static readonly object Lock = new object();

internal static void Initialize()
{
HookedUpToNetworkEvents = false;
}
internal static bool HookedUpToNetworkEvents { get; set; }

public void RegisterOsNetworkStateChanged(ILogger logger)
{
Expand Down
17 changes: 9 additions & 8 deletions src/IO.Ably.Push.Android/AndroidMobileDevice.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Net;
using System.Runtime.CompilerServices;
using Android.App;
using Android.Content;
using Android.Gms.Tasks;
Expand All @@ -12,13 +13,13 @@ namespace IO.Ably.Push.Android
public class AndroidMobileDevice : IMobileDevice
{
private const string TokenType = "fcm";
private readonly ILogger _logger;
private static AblyRealtime _realtimeInstance;

internal AndroidMobileDevice(PushCallbacks callbacks, ILogger logger)
private ILogger Logger { get; set; }

internal AndroidMobileDevice(PushCallbacks callbacks)
{
Callbacks = callbacks;
_logger = logger;
}

/// <summary>
Expand All @@ -44,11 +45,11 @@ public static IRealtimeClient Initialise(ClientOptions ablyClientOptions, Action
/// <returns>Initialised Ably instance which supports push notification registrations.</returns>
public static IRealtimeClient Initialise(ClientOptions ablyClientOptions, PushCallbacks callbacks = null)
{
var androidMobileDevice = new AndroidMobileDevice(callbacks ?? new PushCallbacks(), DefaultLogger.LoggerInstance);
IoC.MobileDevice = androidMobileDevice;
var androidMobileDevice = new AndroidMobileDevice(callbacks ?? new PushCallbacks());

// Create the instance of ably used for Push registrations
_realtimeInstance = new AblyRealtime(ablyClientOptions, androidMobileDevice);
androidMobileDevice.Logger = _realtimeInstance.Logger;
_realtimeInstance.Push.InitialiseStateMachine();
return _realtimeInstance;
}
Expand Down Expand Up @@ -100,15 +101,15 @@ public void RequestRegistrationToken(Action<Result<RegistrationToken>> callback)
{
try
{
_logger.Debug("Requesting a new Registration token");
Logger.Debug("Requesting a new Registration token");
var messagingInstance = FirebaseMessaging.Instance;
var resultTask = messagingInstance.GetToken();

resultTask.AddOnCompleteListener(new RequestTokenCompleteListener(callback, _logger));
resultTask.AddOnCompleteListener(new RequestTokenCompleteListener(callback, Logger));
}
catch (Exception e)
{
_logger.Error("Error while requesting a new Registration token.", e);
Logger.Error("Error while requesting a new Registration token.", e);
var errorInfo = new ErrorInfo($"Failed to request AndroidToken. Error: {e?.Message}.", 50000, HttpStatusCode.InternalServerError, e);
callback(Result.Fail<RegistrationToken>(errorInfo));
}
Expand Down
18 changes: 9 additions & 9 deletions src/IO.Ably.Push.iOS/AppleMobileDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ public class AppleMobileDevice : IMobileDevice
{
private const string TokenType = "apns";

private readonly ILogger _logger;
private static AblyRealtime _realtimeInstance;

private AppleMobileDevice(PushCallbacks callbacks, ILogger logger)
private ILogger Logger { get; set; }

private AppleMobileDevice(PushCallbacks callbacks)
{
Callbacks = callbacks;
_logger = logger;
}

/// <summary>
Expand All @@ -42,9 +42,9 @@ public static IRealtimeClient Initialise(ClientOptions ablyClientOptions, Action
/// <returns>Initialised Ably instance which supports push notification registrations.</returns>
public static IRealtimeClient Initialise(ClientOptions ablyClientOptions, PushCallbacks callbacks = null)
{
var mobileDevice = new AppleMobileDevice(callbacks, DefaultLogger.LoggerInstance);
IoC.MobileDevice = mobileDevice;
var mobileDevice = new AppleMobileDevice(callbacks);
_realtimeInstance = new AblyRealtime(ablyClientOptions, mobileDevice);
mobileDevice.Logger = _realtimeInstance.Logger;
_realtimeInstance.Push.InitialiseStateMachine();
return _realtimeInstance;
}
Expand Down Expand Up @@ -95,7 +95,7 @@ public static void OnRegistrationTokenFailed(ErrorInfo error)
/// <inheritdoc/>
public void SetPreference(string key, string value, string groupName)
{
_logger.Debug($"Setting preferences: {groupName}:{key} with value {value}");
Logger.Debug($"Setting preferences: {groupName}:{key} with value {value}");
Preferences.Set(key, value, groupName);
}

Expand All @@ -108,14 +108,14 @@ public string GetPreference(string key, string groupName)
/// <inheritdoc/>
public void RemovePreference(string key, string groupName)
{
_logger.Debug($"Removing preference: {groupName}:{key}");
Logger.Debug($"Removing preference: {groupName}:{key}");
Preferences.Remove(key, groupName);
}

/// <inheritdoc/>
public void ClearPreferences(string groupName)
{
_logger.Debug($"Clearing preferences group: {groupName}");
Logger.Debug($"Clearing preferences group: {groupName}");
Preferences.Clear(groupName);
}

Expand All @@ -136,7 +136,7 @@ public void RequestRegistrationToken(Action<Result<RegistrationToken>> unusedAct
}
else
{
_logger.Error($"Error signing up for remote notifications: {error.LocalizedDescription}");
Logger.Error($"Error signing up for remote notifications: {error.LocalizedDescription}");
}
});
}
Expand Down
5 changes: 3 additions & 2 deletions src/IO.Ably.Shared/AblyRealtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public AblyRealtime(string key)
/// </summary>
/// <param name="options"><see cref="ClientOptions"/>.</param>
public AblyRealtime(ClientOptions options)
: this(options, CreateRestFunc, IoC.MobileDevice)
: this(options, CreateRestFunc)
{
}

Expand All @@ -65,6 +65,7 @@ internal AblyRealtime(ClientOptions options, Func<ClientOptions, IMobileDevice,
}

CaptureSynchronizationContext(options);

RestClient = createRestFunc != null ? createRestFunc.Invoke(options, mobileDevice) : new AblyRest(options, mobileDevice);
Push = new PushRealtime(RestClient, Logger);

Expand All @@ -76,7 +77,7 @@ internal AblyRealtime(ClientOptions options, Func<ClientOptions, IMobileDevice,
IoC.RegisterOsNetworkStateChanged(Logger);
}

Channels = new RealtimeChannels(this, Connection, mobileDevice);
Channels = new RealtimeChannels(this, Connection, RestClient.MobileDevice);
RestClient.AblyAuth.OnAuthUpdated = ConnectionManager.OnAuthUpdated;

State = new RealtimeState(options.GetFallbackHosts()?.Shuffle().ToList(), Logger, options.NowFunc);
Expand Down
13 changes: 7 additions & 6 deletions src/IO.Ably.Shared/AblyRest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,19 @@ public AblyRest(Action<ClientOptions> init)
{
Options = new ClientOptions();
init(Options);
InitializeAbly(IoC.MobileDevice);
InitializeAbly();
}

/// <summary>
/// Initialize the library with a custom set of options.
/// </summary>
/// <param name="clientOptions">instance of clientOptions.</param>
public AblyRest(ClientOptions clientOptions)
: this(clientOptions, IoC.MobileDevice)
: this(clientOptions, null)
{
}

internal AblyRest(ClientOptions clientOptions, IMobileDevice mobileDevice)
internal AblyRest(ClientOptions clientOptions, IMobileDevice mobileDevice = null)
{
Options = clientOptions;
InitializeAbly(mobileDevice);
Expand Down Expand Up @@ -122,7 +122,7 @@ public LocalDevice Device
internal ILogger Logger { get; set; }

/// <summary>Initializes the rest client and validates the passed in options.</summary>
private void InitializeAbly(IMobileDevice mobileDevice)
private void InitializeAbly(IMobileDevice mobileDevice = null)
{
if (Options == null)
{
Expand All @@ -144,9 +144,10 @@ private void InitializeAbly(IMobileDevice mobileDevice)
HttpClient = new AblyHttpClient(new AblyHttpOptions(Options));
ExecuteHttpRequest = HttpClient.Execute;
AblyAuth = new AblyAuth(Options, this);
Channels = new RestChannels(this, mobileDevice);
Push = new PushRest(this, Logger);

MobileDevice = mobileDevice;
Channels = new RestChannels(this, MobileDevice);
Push = new PushRest(this, Logger);
AblyAuth.OnClientIdChanged = OnAuthClientIdChanged;
}

Expand Down
2 changes: 1 addition & 1 deletion src/IO.Ably.Shared/Defaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ internal static string GetVersion()
public static readonly TimeSpan ConnectionStateTtl = TimeSpan.FromSeconds(120); // https://sdk.ably.com/builds/ably/specification/main/features/#DF1a
public static readonly TimeSpan FallbackRetryTimeout = TimeSpan.FromMinutes(10); // https://sdk.ably.com/builds/ably/specification/main/features/#TO3l10

public static readonly ITransportFactory WebSocketTransportFactory = IoC.TransportFactory;
public static readonly ITransportFactory WebSocketTransportFactory = new MsWebSocketTransport.TransportFactory();

internal const int TokenErrorCodesRangeStart = 40140;
internal const int TokenErrorCodesRangeEnd = 40149;
Expand Down
4 changes: 0 additions & 4 deletions src/IO.Ably.Shared/IPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ internal interface IPlatform
{
Agent.PlatformRuntime PlatformId { get; }

ITransportFactory TransportFactory { get; }

IMobileDevice MobileDevice { get; set; }

/// <summary>
/// This method when implemented in each Platform class includes logic to subscribe to
/// NetworkStatus changes from the operating system. It is then exposed through
Expand Down
59 changes: 5 additions & 54 deletions src/IO.Ably.Shared/IoC.cs
Original file line number Diff line number Diff line change
@@ -1,61 +1,12 @@
using System;
using System.IO;
using System.Reflection;
using IO.Ably.Push;
using IO.Ably.Transport;

namespace IO.Ably
namespace IO.Ably
{
/// <summary>This class initializes dynamically-injected platform dependencies.</summary>
internal static class IoC
/// <summary>This class initializes Platform.</summary>
internal class IoC
{
private static readonly IPlatform Platform;

/// <summary>Load AblyPlatform.dll, instantiate AblyPlatform.PlatformImpl type.</summary>
static IoC()
{
try
{
var name = new AssemblyName("IO.Ably");
var asm = Assembly.Load(name);
var type = asm.GetType("IO.Ably.Platform");
if (type != null)
{
var obj = Activator.CreateInstance(type);
Platform = obj as IPlatform;
}
else
{
DefaultLogger.Debug("Platform class does not exist. Defaulting Microsoft Websocket library.");
}
}
catch (FileNotFoundException e)
{
DefaultLogger.Debug($"Assembly cannot be loaded. Defaulting Microsoft Websocket library. ({e.Message})");
}
}

public static ITransportFactory TransportFactory => Platform?.TransportFactory ?? new MsWebSocketTransport.TransportFactory();

public static void RegisterOsNetworkStateChanged(ILogger logger) => Platform.RegisterOsNetworkStateChanged(logger);
public static readonly Platform Platform = new Platform();

public static Agent.PlatformRuntime PlatformId => Platform?.PlatformId ?? Agent.PlatformRuntime.Other;

public static IMobileDevice MobileDevice
{
get
{
try
{
return Platform.MobileDevice;
}
catch (Exception e) when (e is NotImplementedException)
{
DefaultLogger.Error("Mobile Device is no supported on the current platform.", e);
return null;
}
}
set => Platform.MobileDevice = value;
}
public static void RegisterOsNetworkStateChanged(ILogger logger) => Platform.RegisterOsNetworkStateChanged(logger);
}
}
2 changes: 1 addition & 1 deletion src/IO.Ably.Shared/Push/LocalDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ internal static LocalDevice GetInstance(IMobileDevice mobileDevice, string clien
if (mobileDevice is null)
{
throw new AblyException(
"Cannot initialise LocalDevice instance before initialising the MobileDevice class. For Android call AndroidMobileDevice.Initialise() and for iOS call AppleMobileDevice.Initialise()");
"Cannot initialise LocalDevice instance before initializing the MobileDevice class. For Android call AndroidMobileDevice.Initialise() and for iOS call AppleMobileDevice.Initialise()");
}

switch (Instance)
Expand Down
Loading
Loading