Core - Nullable refactoring

Core - Nullable refactoring


Core - Nullable refactoring (finish)
This commit is contained in:
SpoinkyNL committed 2020-11-17 22:50:38 +01:00
1 parent b185b28645
commit fb3466e102
61 files changed
+320 -272

No files matched your search

@@ -11,32 +11,32 @@ namespace Artemis.Core.DataModelExpansions
/// <summary>
/// Gets or sets the user-friendly name for this property, shown in the UI.
/// </summary>
public string Name { get; set; }
public string? Name { get; set; }
/// <summary>
/// Gets or sets the user-friendly description for this property, shown in the UI.
/// </summary>
public string Description { get; set; }
public string? Description { get; set; }
/// <summary>
/// Gets or sets the an optional prefix to show before displaying elements in the UI.
/// </summary>
public string Prefix { get; set; }
public string? Prefix { get; set; }
/// <summary>
/// Gets or sets an optional affix to show behind displaying elements in the UI.
/// </summary>
public string Affix { get; set; }
public string? Affix { get; set; }
/// <summary>
/// Gets or sets an optional maximum value, this value is not enforced but used for percentage calculations.
/// </summary>
public object MaxValue { get; set; }
public object? MaxValue { get; set; }
/// <summary>
/// Gets or sets an optional minimum value, this value is not enforced but used for percentage calculations.
/// </summary>
public object MinValue { get; set; }
public object? MinValue { get; set; }
/// <summary>
/// Gets or sets whether this property resets the max depth of the data model, defaults to true
@@ -15,6 +15,16 @@ namespace Artemis.Core.DataModelExpansions
{
private readonly Dictionary<string, DataModel> _dynamicDataModels = new Dictionary<string, DataModel>();
/// <summary>
/// Creates a new instance of the <see cref="DataModel" /> class
/// </summary>
protected DataModel()
{
// These are both set right after construction to keep the constructor of inherited classes clean
Feature = null!;
DataModelDescription = null!;
}
/// <summary>
/// Gets the plugin feature this data model belongs to
/// </summary>
@@ -60,7 +70,7 @@ namespace Artemis.Core.DataModelExpansions
/// <param name="key">The key of the child, must be unique to this data model</param>
/// <param name="name">An optional name, if not provided the key will be used in a humanized form</param>
/// <param name="description">An optional description</param>
public T AddDynamicChild<T>(T dynamicDataModel, string key, string name = null, string description = null) where T : DataModel
public T AddDynamicChild<T>(T dynamicDataModel, string key, string? name = null, string? description = null) where T : DataModel
{
if (dynamicDataModel == null)
throw new ArgumentNullException(nameof(dynamicDataModel));
@@ -140,7 +150,7 @@ namespace Artemis.Core.DataModelExpansions
/// <returns>If found, the dynamic data model otherwise <c>null</c></returns>
public T? DynamicChild<T>(string key) where T : DataModel
{
_dynamicDataModels.TryGetValue(key, out DataModel value);
_dynamicDataModels.TryGetValue(key, out DataModel? value);
return value as T;
}
@@ -16,7 +16,7 @@ namespace Artemis.Core.DataModelExpansions
/// </summary>
public T DataModel
{
get => (T) InternalDataModel;
get => InternalDataModel as T ?? throw new InvalidOperationException("Internal datamodel does not match the type of the data model");
internal set => InternalDataModel = value;
}
@@ -49,11 +49,5 @@ namespace Artemis.Core.DataModelExpansions
DataModel.DataModelDescription = GetDataModelDescription();
base.InternalEnable();
}
internal override void InternalDisable()
{
DataModel = null;
base.InternalDisable();
}
}
}
@@ -31,7 +31,7 @@ namespace Artemis.Core.DeviceProviders
/// A logger used by the device provider internally, ignore this
/// </summary>
[Inject]
public ILogger Logger { get; set; }
public ILogger? Logger { get; set; }
/// <inheritdoc />
public override void Disable()
@@ -10,10 +10,20 @@ namespace Artemis.Core.LayerBrushes
{
private LayerBrushType _brushType;
private ILayerBrushConfigurationDialog? _configurationDialog;
private LayerBrushDescriptor? _descriptor;
private LayerBrushDescriptor _descriptor;
private Layer _layer;
private bool _supportsTransformation = true;
/// <summary>
/// Creates a new instance of the <see cref="BaseLayerBrush" /> class
/// </summary>
protected BaseLayerBrush()
{
// Both are set right after construction to keep the constructor of inherited classes clean
_layer = null!;
_descriptor = null!;
}
/// <summary>
/// Gets the layer this brush is applied to
/// </summary>
@@ -26,7 +36,7 @@ namespace Artemis.Core.LayerBrushes
/// <summary>
/// Gets the descriptor of this brush
/// </summary>
public LayerBrushDescriptor? Descriptor
public LayerBrushDescriptor Descriptor
{
get => _descriptor;
internal set => SetAndNotify(ref _descriptor, value);
@@ -7,7 +7,7 @@ namespace Artemis.Core.LayerBrushes
/// </summary>
public abstract class PropertiesLayerBrush<T> : BaseLayerBrush where T : LayerPropertyGroup
{
private T _properties;
private T _properties = null!;
/// <summary>
/// Gets whether all properties on this brush are initialized
@@ -35,7 +35,7 @@ namespace Artemis.Core.LayerBrushes
internal void InitializeProperties()
{
Properties = Activator.CreateInstance<T>();
Properties.GroupDescription ??= new PropertyGroupDescriptionAttribute {Name = Descriptor.DisplayName, Description = Descriptor.Description};
Properties.GroupDescription = new PropertyGroupDescriptionAttribute {Name = Descriptor.DisplayName, Description = Descriptor.Description};
Properties.LayerBrush = this;
Properties.Initialize(Layer, "LayerBrush.", Descriptor.Provider);
PropertiesInitialized = true;
@@ -59,6 +59,7 @@ namespace Artemis.Core.LayerBrushes
/// </summary>
internal void CreateInstance(Layer layer)
{
if (layer == null) throw new ArgumentNullException(nameof(layer));
if (layer.LayerBrush != null)
throw new ArtemisCoreException("Layer already has an instantiated layer brush");
@@ -20,6 +20,7 @@ namespace Artemis.Core.LayerBrushes
/// </summary>
protected RgbNetLayerBrush()
{
LedGroup = new ListLedGroup();
BrushType = LayerBrushType.RgbNet;
SupportsTransformation = false;
}
@@ -75,7 +76,7 @@ namespace Artemis.Core.LayerBrushes
// Not used in this effect type
internal override void InternalRender(SKCanvas canvas, SKRect bounds, SKPaint paint)
{
throw new NotImplementedException("RGB.NET layer effectes do not implement InternalRender");
throw new NotImplementedException("RGB.NET layer effects do not implement InternalRender");
}
private void LayerOnRenderPropertiesUpdated(object? sender, EventArgs e)
@@ -9,7 +9,7 @@ namespace Artemis.Core.LayerEffects
/// </summary>
public abstract class BaseLayerEffect : CorePropertyChanged, IDisposable
{
private ILayerEffectConfigurationDialog _configurationDialog;
private ILayerEffectConfigurationDialog? _configurationDialog;
private LayerEffectDescriptor _descriptor;
private bool _enabled;
private Guid _entityId;
@@ -18,6 +18,15 @@ namespace Artemis.Core.LayerEffects
private int _order;
private RenderProfileElement _profileElement;
/// <inheritdoc />
protected BaseLayerEffect()
{
// These are set right after construction to keep the constructor of inherited classes clean
_profileElement = null!;
_descriptor = null!;
_name = null!;
}
/// <summary>
/// Gets the unique ID of this effect
/// </summary>
@@ -76,7 +85,7 @@ namespace Artemis.Core.LayerEffects
/// <summary>
/// Gets the <see cref="LayerEffectDescriptor" /> that registered this effect
/// </summary>
public LayerEffectDescriptor? Descriptor
public LayerEffectDescriptor Descriptor
{
get => _descriptor;
internal set => SetAndNotify(ref _descriptor, value);
@@ -85,7 +94,7 @@ namespace Artemis.Core.LayerEffects
/// <summary>
/// Gets or sets a configuration dialog complementing the regular properties
/// </summary>
public ILayerEffectConfigurationDialog ConfigurationDialog
public ILayerEffectConfigurationDialog? ConfigurationDialog
{
get => _configurationDialog;
protected set => SetAndNotify(ref _configurationDialog, value);
@@ -94,12 +103,12 @@ namespace Artemis.Core.LayerEffects
/// <summary>
/// Gets the ID of the <see cref="LayerEffectProvider"/> that provided this effect
/// </summary>
public string ProviderId => Descriptor?.Provider?.Id;
public string ProviderId => Descriptor.Provider.Id;
/// <summary>
/// Gets a reference to the layer property group without knowing it's type
/// </summary>
public virtual LayerPropertyGroup BaseProperties => null;
public virtual LayerPropertyGroup? BaseProperties => null;
internal string PropertyRootPath => $"LayerEffect.{EntityId}.{GetType().Name}.";
@@ -8,7 +8,7 @@ namespace Artemis.Core.LayerEffects
/// <typeparam name="T"></typeparam>
public abstract class LayerEffect<T> : BaseLayerEffect where T : LayerPropertyGroup
{
private T _properties;
private T _properties = null!;
/// <summary>
/// Gets whether all properties on this effect are initialized
@@ -11,7 +11,7 @@ namespace Artemis.Core.LayerEffects
/// </summary>
public class LayerEffectDescriptor
{
internal LayerEffectDescriptor(string displayName, string description, string icon, Type layerEffectType, LayerEffectProvider provider)
internal LayerEffectDescriptor(string displayName, string description, string icon, Type? layerEffectType, LayerEffectProvider provider)
{
DisplayName = displayName;
Description = description;
@@ -39,12 +39,12 @@ namespace Artemis.Core.LayerEffects
/// <summary>
/// The type of the layer effect
/// </summary>
public Type LayerEffectType { get; }
public Type? LayerEffectType { get; }
/// <summary>
/// The plugin that provided this <see cref="LayerEffectDescriptor" />
/// </summary>
public LayerEffectProvider? Provider { get; }
public LayerEffectProvider Provider { get; }
/// <summary>
/// Gets the GUID this descriptor is acting as a placeholder for. If null, this descriptor is not a placeholder
@@ -66,8 +66,8 @@ namespace Artemis.Core.LayerEffects
return;
}
if (Provider == null)
throw new ArtemisCoreException("Cannot create an instance of a layer effect because this descriptor is not a placeholder but is still missing its provider");
if (LayerEffectType == null)
throw new ArtemisCoreException("Cannot create an instance of a layer effect because this descriptor is not a placeholder but is still missing its LayerEffectType");
BaseLayerEffect effect = (BaseLayerEffect) Provider.Plugin.Kernel!.Get(LayerEffectType);
effect.ProfileElement = renderElement;
@@ -85,7 +85,13 @@ namespace Artemis.Core.LayerEffects
private void CreatePlaceHolderInstance(RenderProfileElement renderElement, LayerEffectEntity entity)
{
PlaceholderLayerEffect effect = new PlaceholderLayerEffect(entity, PlaceholderFor) {ProfileElement = renderElement, Descriptor = this};
if (PlaceholderFor == null)
throw new ArtemisCoreException("Cannot create a placeholder instance using a layer effect descriptor that is not a placeholder for anything");
PlaceholderLayerEffect effect = new PlaceholderLayerEffect(entity, PlaceholderFor)
{
ProfileElement = renderElement,
Descriptor = this
};
effect.Initialize();
renderElement.ActivateLayerEffect(effect);
}
@@ -16,7 +16,7 @@ namespace Artemis.Core.Modules
/// </summary>
/// <param name="processName">The name of the process that must run</param>
/// <param name="location">The location of where the process must be running from (optional)</param>
public ProcessActivationRequirement(string processName, string location = null)
public ProcessActivationRequirement(string? processName, string? location = null)
{
ProcessName = processName;
Location = location;
@@ -25,12 +25,12 @@ namespace Artemis.Core.Modules
/// <summary>
/// The name of the process that must run
/// </summary>
public string ProcessName { get; set; }
public string? ProcessName { get; set; }
/// <summary>
/// The location of where the process must be running from
/// </summary>
public string Location { get; set; }
public string? Location { get; set; }
/// <inheritdoc />
public bool Evaluate()
+1 -7
View File
@@ -18,7 +18,7 @@ namespace Artemis.Core.Modules
/// </summary>
public T DataModel
{
get => (T) InternalDataModel;
get => InternalDataModel as T ?? throw new InvalidOperationException("Internal datamodel does not match the type of the data model");
internal set => InternalDataModel = value;
}
@@ -52,12 +52,6 @@ namespace Artemis.Core.Modules
DataModel.DataModelDescription = GetDataModelDescription();
base.InternalEnable();
}
internal override void InternalDisable()
{
DataModel = null;
base.InternalDisable();
}
}
@@ -6,12 +6,11 @@ namespace Artemis.Core.Modules
public class ModuleTab<T> : ModuleTab where T : IModuleViewModel
{
/// <summary>
/// Initializes a new instance of the <see cref="ModuleTab{T}" /> class
/// Creates a new instance of the <see cref="ModuleTab{T}" /> class
/// </summary>
/// <param name="title">The title of the tab</param>
public ModuleTab(string title)
public ModuleTab(string title) : base(title)
{
Title = title;
}
/// <inheritdoc />
@@ -24,9 +23,13 @@ namespace Artemis.Core.Modules
public abstract class ModuleTab
{
/// <summary>
/// The module this tab belongs to
/// Creates a new instance of the <see cref="ModuleTab" /> class
/// </summary>
internal Module Module { get; set; }
/// <param name="title">The title of the tab</param>
protected ModuleTab(string title)
{
Title = title;
}
/// <summary>
/// The title of the tab
@@ -22,7 +22,7 @@ namespace Artemis.Core.Modules
/// </summary>
public T DataModel
{
get => (T) InternalDataModel;
get => InternalDataModel as T ?? throw new InvalidOperationException("Internal datamodel does not match the type of the data model");
internal set => InternalDataModel = value;
}
@@ -83,7 +83,6 @@ namespace Artemis.Core.Modules
{
Deactivate(true);
base.InternalDisable();
DataModel = null;
}
}
@@ -182,7 +181,7 @@ namespace Artemis.Core.Modules
ProfileRendered(deltaTime, surface, canvas, canvasInfo);
}
internal async Task ChangeActiveProfileAnimated(Profile profile, ArtemisSurface surface)
internal async Task ChangeActiveProfileAnimated(Profile? profile, ArtemisSurface? surface)
{
if (profile != null && profile.Module != this)
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
@@ -204,12 +203,14 @@ namespace Artemis.Core.Modules
await Task.Delay(50);
}
internal void ChangeActiveProfile(Profile profile, ArtemisSurface surface)
internal void ChangeActiveProfile(Profile? profile, ArtemisSurface? surface)
{
if (profile != null && profile.Module != this)
throw new ArtemisCoreException($"Cannot activate a profile of module {profile.Module} on a module of plugin {this}.");
if (!IsActivated)
throw new ArtemisCoreException("Cannot activate a profile on a deactivated module");
if (profile != null && surface == null)
throw new ArtemisCoreException("If changing the active profile to a non-null profile, a surface is required");
lock (_lock)
{
@@ -219,7 +220,7 @@ namespace Artemis.Core.Modules
ActiveProfile?.Dispose();
ActiveProfile = profile;
ActiveProfile?.Activate(surface);
ActiveProfile?.Activate(surface!);
}
OnActiveProfileChanged();
@@ -229,7 +230,7 @@ namespace Artemis.Core.Modules
{
base.Deactivate(isOverride);
Profile profile = ActiveProfile;
Profile? profile = ActiveProfile;
ActiveProfile = null;
profile?.Dispose();
}
@@ -249,7 +250,7 @@ namespace Artemis.Core.Modules
/// <summary>
/// Occurs when the <see cref="ActiveProfile" /> has changed
/// </summary>
public event EventHandler ActiveProfileChanged;
public event EventHandler? ActiveProfileChanged;
/// <summary>
/// Invokes the <see cref="ActiveProfileChanged" /> event
+6 -2
View File
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -19,10 +20,11 @@ namespace Artemis.Core
private bool _isEnabled;
internal Plugin(PluginInfo info, DirectoryInfo directory)
internal Plugin(PluginInfo info, DirectoryInfo directory, PluginEntity? pluginEntity)
{
Info = info;
Directory = directory;
Entity = pluginEntity ?? new PluginEntity {Id = Guid, IsEnabled = true};
_features = new List<PluginFeature>();
}
@@ -42,6 +44,7 @@ namespace Artemis.Core
/// </summary>
public DirectoryInfo Directory { get; }
/// <summary>
/// Gets or sets a configuration dialog for this plugin that is accessible in the UI under Settings > Plugins
/// </summary>
@@ -91,7 +94,8 @@ namespace Artemis.Core
/// </summary>
/// <param name="path">The path to resolve</param>
/// <returns>An absolute path pointing to the provided relative path</returns>
public string? ResolveRelativePath(string path)
[return: NotNullIfNotNull("path")]
public string? ResolveRelativePath(string? path)
{
return path == null ? null : Path.Combine(Directory.FullName, path);
}
+2 -2
View File
@@ -16,7 +16,7 @@ namespace Artemis.Core
/// <summary>
/// Gets the plugin that provides this feature
/// </summary>
public Plugin Plugin { get; internal set; }
public Plugin Plugin { get; internal set; } = null!; // Will be set right after construction
/// <summary>
/// Gets whether the plugin is enabled
@@ -41,7 +41,7 @@ namespace Artemis.Core
/// </summary>
public string Id => $"{GetType().FullName}-{Plugin.Guid.ToString().Substring(0, 8)}"; // Not as unique as a GUID but good enough and stays readable
internal PluginFeatureEntity Entity { get; set; }
internal PluginFeatureEntity Entity { get; set; } = null!; // Will be set right after construction
/// <summary>
/// Called when the feature is activated
+8 -8
View File
@@ -9,13 +9,13 @@ namespace Artemis.Core
[JsonObject(MemberSerialization.OptIn)]
public class PluginInfo : CorePropertyChanged
{
private string _description;
private string? _description;
private Guid _guid;
private string _icon;
private string _main;
private string _name;
private Plugin _plugin;
private Version _version;
private string? _icon;
private string _main = null!;
private string _name = null!;
private Plugin _plugin = null!;
private Version _version = null!;
internal PluginInfo()
{
@@ -45,7 +45,7 @@ namespace Artemis.Core
/// A short description of the plugin
/// </summary>
[JsonProperty]
public string Description
public string? Description
{
get => _description;
set => SetAndNotify(ref _description, value);
@@ -57,7 +57,7 @@ namespace Artemis.Core
/// icons
/// </summary>
[JsonProperty]
public string Icon
public string? Icon
{
get => _icon;
set => SetAndNotify(ref _icon, value);
@@ -1,4 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Artemis.Core.Properties;
using Artemis.Storage.Entities.Plugins;
using Artemis.Storage.Repositories.Interfaces;
using Newtonsoft.Json;
@@ -27,11 +29,11 @@ namespace Artemis.Core
Name = pluginSettingEntity.Name;
try
{
Value = JsonConvert.DeserializeObject<T>(pluginSettingEntity.Value);
_value = JsonConvert.DeserializeObject<T>(pluginSettingEntity.Value);
}
catch (JsonReaderException)
{
Value = default;
_value = default!;
}
}
@@ -43,6 +45,8 @@ namespace Artemis.Core
/// <summary>
/// The value of the setting
/// </summary>
[AllowNull]
[CanBeNull]
public T Value
{
get => _value;
@@ -50,7 +54,7 @@ namespace Artemis.Core
{
if (Equals(_value, value)) return;
_value = value;
_value = value!;
OnSettingChanged();
OnPropertyChanged(nameof(Value));
@@ -94,12 +98,12 @@ namespace Artemis.Core
/// <summary>
/// Occurs when the value of the setting has been changed
/// </summary>
public event EventHandler SettingChanged;
public event EventHandler? SettingChanged;
/// <summary>
/// Occurs when the value of the setting has been saved
/// </summary>
public event EventHandler SettingSaved;
public event EventHandler? SettingSaved;
/// <inheritdoc />
public override string ToString()
@@ -11,7 +11,7 @@ namespace Artemis.Core
public class TimedUpdateRegistration : IDisposable
{
private DateTime _lastEvent;
private Timer _timer;
private Timer? _timer;
private bool _disposed;
private readonly object _lock = new object();
@@ -53,12 +53,12 @@ namespace Artemis.Core
/// <summary>
/// Gets the action that gets called each time the update event fires
/// </summary>
public Action<double> Action { get; }
public Action<double>? Action { get; }
/// <summary>
/// Gets the task that gets called each time the update event fires
/// </summary>
public Func<double, Task> AsyncAction { get; }
public Func<double, Task>? AsyncAction { get; }
/// <summary>
/// Starts calling the <see cref="Action" /> or <see cref="AsyncAction"/> at the configured <see cref="Interval" />