mirror of
https://github.com/ICDSystems/ICD.Common.Utils.git
synced 2026-01-11 19:44:55 +00:00
Created S# .sln and moved project to src folder
This commit is contained in:
40
ICD.Common/Attributes/AbstractIcdAttribute.cs
Normal file
40
ICD.Common/Attributes/AbstractIcdAttribute.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Attributes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// AbstractIcdAttribute is the base class for all ICD attributes.
|
||||||
|
/// It provides a global cache for looking up symbols via an attribute type.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class AbstractIcdAttribute : Attribute
|
||||||
|
{
|
||||||
|
private readonly int m_HashCode;
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
protected AbstractIcdAttribute()
|
||||||
|
{
|
||||||
|
// Duplicate attributes (E.g. [A, A]) are considered to be the same instance by reflection.
|
||||||
|
// We get around this by using a GUID for the hash code.
|
||||||
|
m_HashCode = Guid.NewGuid().GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the hash code for the instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return m_HashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
9
ICD.Common/Attributes/KrangPluginAttribute.cs
Normal file
9
ICD.Common/Attributes/KrangPluginAttribute.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Attributes
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly)]
|
||||||
|
public sealed class KrangPluginAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
38
ICD.Common/Attributes/Properties/SettingsProperty.cs
Normal file
38
ICD.Common/Attributes/Properties/SettingsProperty.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Attributes.Properties
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides information on a settings property.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public sealed class SettingsProperty : Attribute
|
||||||
|
{
|
||||||
|
public enum ePropertyType
|
||||||
|
{
|
||||||
|
[PublicAPI] Default,
|
||||||
|
[PublicAPI] PortId,
|
||||||
|
[PublicAPI] DeviceId,
|
||||||
|
[PublicAPI] Ipid,
|
||||||
|
[PublicAPI] Enum
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly ePropertyType m_PropertyType;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the property type.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public ePropertyType PropertyType { get { return m_PropertyType; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="propertyType"></param>
|
||||||
|
public SettingsProperty(ePropertyType propertyType)
|
||||||
|
{
|
||||||
|
m_PropertyType = propertyType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
177
ICD.Common/Attributes/Rpc/RpcAttribute.cs
Normal file
177
ICD.Common/Attributes/Rpc/RpcAttribute.cs
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
|
#else
|
||||||
|
using System.Reflection;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils;
|
||||||
|
using ICD.Common.Utils.Collections;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Attributes.Rpc
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a method that can be called by the server via RPC.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
[MeansImplicitUse]
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
|
||||||
|
public sealed class RpcAttribute : AbstractIcdAttribute
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<Type, Dictionary<string, IcdHashSet<MethodInfo>>> s_MethodCache;
|
||||||
|
private static readonly Dictionary<Type, Dictionary<string, IcdHashSet<PropertyInfo>>> s_PropertyCache;
|
||||||
|
|
||||||
|
private static readonly SafeCriticalSection s_MethodCacheSection;
|
||||||
|
private static readonly SafeCriticalSection s_PropertyCacheSection;
|
||||||
|
|
||||||
|
private readonly string m_Key;
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
static RpcAttribute()
|
||||||
|
{
|
||||||
|
s_MethodCache = new Dictionary<Type, Dictionary<string, IcdHashSet<MethodInfo>>>();
|
||||||
|
s_PropertyCache = new Dictionary<Type, Dictionary<string, IcdHashSet<PropertyInfo>>>();
|
||||||
|
|
||||||
|
s_MethodCacheSection = new SafeCriticalSection();
|
||||||
|
s_PropertyCacheSection = new SafeCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
public RpcAttribute(string key)
|
||||||
|
{
|
||||||
|
m_Key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the method on the client with the given key, matching the parameter types.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="parameters"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[CanBeNull]
|
||||||
|
public static MethodInfo GetMethod(object client, string key, IEnumerable<object> parameters)
|
||||||
|
{
|
||||||
|
return GetMethods(client, key).FirstOrDefault(m => ReflectionUtils.MatchesMethodParameters(m, parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the property on the client with the given key, matching the parameter type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="parameter"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[CanBeNull]
|
||||||
|
public static PropertyInfo GetProperty(object client, string key, object parameter)
|
||||||
|
{
|
||||||
|
return GetProperties(client, key).FirstOrDefault(p => ReflectionUtils.MatchesPropertyParameter(p, parameter));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the methods on the client with the given key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<MethodInfo> GetMethods(object client, string key)
|
||||||
|
{
|
||||||
|
s_MethodCacheSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type clientType = client.GetType();
|
||||||
|
|
||||||
|
// Cache the methods for the key so subsequent calls are faster.
|
||||||
|
if (!s_MethodCache.ContainsKey(clientType))
|
||||||
|
s_MethodCache[clientType] = new Dictionary<string, IcdHashSet<MethodInfo>>();
|
||||||
|
|
||||||
|
if (!s_MethodCache[clientType].ContainsKey(key))
|
||||||
|
{
|
||||||
|
s_MethodCache[clientType][key] =
|
||||||
|
clientType
|
||||||
|
#if SIMPLSHARP
|
||||||
|
.GetCType()
|
||||||
|
#else
|
||||||
|
.GetTypeInfo()
|
||||||
|
#endif
|
||||||
|
.GetMethods(BindingFlags.Public |
|
||||||
|
BindingFlags.NonPublic |
|
||||||
|
BindingFlags.Instance)
|
||||||
|
.Where(m => m.GetCustomAttributes<RpcAttribute>(true)
|
||||||
|
.Any(a => a.m_Key == key))
|
||||||
|
.ToHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_MethodCache[clientType][key];
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_MethodCacheSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the properties on the client with the given key.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="client"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<PropertyInfo> GetProperties(object client, string key)
|
||||||
|
{
|
||||||
|
s_PropertyCacheSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Type clientType = client.GetType();
|
||||||
|
|
||||||
|
// Cache the properties for the key so subsequent calls are faster.
|
||||||
|
if (!s_PropertyCache.ContainsKey(clientType))
|
||||||
|
s_PropertyCache[clientType] = new Dictionary<string, IcdHashSet<PropertyInfo>>();
|
||||||
|
|
||||||
|
if (!s_PropertyCache[clientType].ContainsKey(key))
|
||||||
|
{
|
||||||
|
s_PropertyCache[clientType][key] =
|
||||||
|
clientType
|
||||||
|
#if SIMPLSHARP
|
||||||
|
.GetCType()
|
||||||
|
#else
|
||||||
|
.GetTypeInfo()
|
||||||
|
#endif
|
||||||
|
.GetProperties(BindingFlags.Public |
|
||||||
|
BindingFlags.NonPublic |
|
||||||
|
BindingFlags.Instance)
|
||||||
|
.Where(p => p.CanWrite && p.GetCustomAttributes<RpcAttribute>(true)
|
||||||
|
.Any(a => a.m_Key == key))
|
||||||
|
.ToHashSet();
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_PropertyCache[clientType][key];
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_PropertyCacheSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
13
ICD.Common/EventArguments/BoolEventArgs.cs
Normal file
13
ICD.Common/EventArguments/BoolEventArgs.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class BoolEventArgs : GenericEventArgs<bool>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public BoolEventArgs(bool data) : base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
ICD.Common/EventArguments/CharEventArgs.cs
Normal file
12
ICD.Common/EventArguments/CharEventArgs.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
public sealed class CharEventArgs : GenericEventArgs<char>
|
||||||
|
{
|
||||||
|
public CharEventArgs(char value) : base(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
ICD.Common/EventArguments/DateTimeEventArgs.cs
Normal file
16
ICD.Common/EventArguments/DateTimeEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class DateTimeEventArgs : GenericEventArgs<DateTime>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public DateTimeEventArgs(DateTime data)
|
||||||
|
: base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
ICD.Common/EventArguments/FloatEventArgs.cs
Normal file
14
ICD.Common/EventArguments/FloatEventArgs.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class FloatEventArgs : GenericEventArgs<float>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public FloatEventArgs(float data)
|
||||||
|
: base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
ICD.Common/EventArguments/GenericEventArgs.cs
Normal file
18
ICD.Common/EventArguments/GenericEventArgs.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public abstract class GenericEventArgs<T> : EventArgs
|
||||||
|
{
|
||||||
|
public T Data { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
protected GenericEventArgs(T data)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
ICD.Common/EventArguments/IntEventArgs.cs
Normal file
13
ICD.Common/EventArguments/IntEventArgs.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class IntEventArgs : GenericEventArgs<int>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public IntEventArgs(int data) : base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
13
ICD.Common/EventArguments/StringEventArgs.cs
Normal file
13
ICD.Common/EventArguments/StringEventArgs.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class StringEventArgs : GenericEventArgs<string>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public StringEventArgs(string data) : base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
ICD.Common/EventArguments/TcpReceiveEventArgs.cs
Normal file
39
ICD.Common/EventArguments/TcpReceiveEventArgs.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ICD.Common.Utils;
|
||||||
|
|
||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class TcpReceiveEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
private readonly uint m_ClientId;
|
||||||
|
private readonly string m_Data;
|
||||||
|
|
||||||
|
public uint ClientId { get { return m_ClientId; } }
|
||||||
|
|
||||||
|
public string Data { get { return m_Data; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public TcpReceiveEventArgs(uint clientId, IEnumerable<byte> data)
|
||||||
|
{
|
||||||
|
m_ClientId = clientId;
|
||||||
|
m_Data = StringUtils.ToString(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientId"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="length"></param>
|
||||||
|
public TcpReceiveEventArgs(uint clientId, IEnumerable<byte> data, int length)
|
||||||
|
{
|
||||||
|
m_ClientId = clientId;
|
||||||
|
m_Data = StringUtils.ToString(data, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
ICD.Common/EventArguments/UShortEventArgs.cs
Normal file
16
ICD.Common/EventArguments/UShortEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
public sealed class UShortEventArgs : GenericEventArgs<ushort>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public UShortEventArgs(ushort data) : base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
ICD.Common/EventArguments/XmlRecursionEventArgs.cs
Normal file
29
ICD.Common/EventArguments/XmlRecursionEventArgs.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.EventArguments
|
||||||
|
{
|
||||||
|
public sealed class XmlRecursionEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
public string Outer { get; private set; }
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public string[] Path { get; private set; }
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outer"></param>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
public XmlRecursionEventArgs(string outer, string[] path)
|
||||||
|
{
|
||||||
|
Outer = outer;
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
35
ICD.Common/ICD.Common_NetStandard.csproj
Normal file
35
ICD.Common/ICD.Common_NetStandard.csproj
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<TargetFramework>netstandard1.6</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DefineConstants>TRACE;DEBUG;STANDARD</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="SIMPLSharpLogs\**" />
|
||||||
|
<EmbeddedResource Remove="SIMPLSharpLogs\**" />
|
||||||
|
<None Remove="SIMPLSharpLogs\**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="ObfuscationSettings.cs" />
|
||||||
|
<Compile Remove="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="ICD.Common_SimplSharp.suo" />
|
||||||
|
<None Remove="ICD.SimplSharp.projectinfo" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="1.1.2" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
|
||||||
|
<PackageReference Include="System.Net.NetworkInformation" Version="4.3.0" />
|
||||||
|
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
167
ICD.Common/ICD.Common_SimplSharp.csproj
Normal file
167
ICD.Common/ICD.Common_SimplSharp.csproj
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Release</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.30729</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{CB4055C6-D59E-479E-9C56-2C92335A7D9A}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>ICD.Common</RootNamespace>
|
||||||
|
<AssemblyName>ICD.Common</AssemblyName>
|
||||||
|
<ProjectTypeGuids>{0B4745B0-194B-4BB6-8E21-E9057CA92500};{4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<PlatformFamilyName>WindowsCE</PlatformFamilyName>
|
||||||
|
<PlatformID>E2BECB1F-8C8C-41ba-B736-9BE7D946A398</PlatformID>
|
||||||
|
<OSVersion>5.0</OSVersion>
|
||||||
|
<DeployDirSuffix>SmartDeviceProject1</DeployDirSuffix>
|
||||||
|
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||||
|
<NativePlatformName>Windows CE</NativePlatformName>
|
||||||
|
<FormFactorID>
|
||||||
|
</FormFactorID>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE;SIMPLSHARP</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<AllowedReferenceRelatedFileExtensions>.allowedReferenceRelatedFileExtensions</AllowedReferenceRelatedFileExtensions>
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<NoStdLib>true</NoStdLib>
|
||||||
|
<NoConfig>true</NoConfig>
|
||||||
|
<GenerateSerializationAssemblies>off</GenerateSerializationAssemblies>
|
||||||
|
<DefineConstants>SIMPLSHARP</DefineConstants>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="mscorlib" />
|
||||||
|
<Reference Include="SimplSharpCustomAttributesInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpCustomAttributesInterface.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SimplSharpHelperInterface, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpHelperInterface.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SimplSharpNewtonsoft, Version=1.0.0.0, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpNewtonsoft.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SimplSharpReflectionInterface, Version=1.0.5583.25238, Culture=neutral, PublicKeyToken=1099c178b3b54c3b, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>C:\ProgramData\Crestron\SDK\SimplSharpReflectionInterface.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Attributes\AbstractIcdAttribute.cs" />
|
||||||
|
<Compile Include="Attributes\KrangPluginAttribute.cs" />
|
||||||
|
<Compile Include="Attributes\Properties\SettingsProperty.cs" />
|
||||||
|
<Compile Include="Attributes\Rpc\RpcAttribute.cs" />
|
||||||
|
<Compile Include="EventArguments\BoolEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\CharEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\DateTimeEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\FloatEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\GenericEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\IntEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\StringEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\TcpReceiveEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\UShortEventArgs.cs" />
|
||||||
|
<Compile Include="EventArguments\XmlRecursionEventArgs.cs" />
|
||||||
|
<None Include="ObfuscationSettings.cs" />
|
||||||
|
<Compile Include="Properties\Annotations.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Services\Logging\ILoggerService.cs" />
|
||||||
|
<Compile Include="Services\Logging\LogItem.cs" />
|
||||||
|
<Compile Include="Services\Logging\LogItemEventArgs.cs" />
|
||||||
|
<Compile Include="Services\Logging\SeverityEventArgs.cs" />
|
||||||
|
<Compile Include="Utils\AttributeUtils.cs" />
|
||||||
|
<Compile Include="Services\ServiceNotFoundException.cs" />
|
||||||
|
<Compile Include="Services\ServiceProvider.cs" />
|
||||||
|
<Compile Include="Utils\Collections\IcdHashSet.cs" />
|
||||||
|
<Compile Include="Utils\Collections\ScrollQueue.cs" />
|
||||||
|
<Compile Include="Utils\CrestronUtils.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\DateTimeExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\TypeExtensions.cs" />
|
||||||
|
<Compile Include="Utils\IcdConsole.cs" />
|
||||||
|
<Compile Include="Utils\IcdEnvironment.cs" />
|
||||||
|
<Compile Include="Utils\IcdEnvironment.SimplSharp.cs" />
|
||||||
|
<Compile Include="Utils\IcdEnvironment.Standard.cs" />
|
||||||
|
<Compile Include="Utils\IcdZip.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdDirectory.cs" />
|
||||||
|
<Compile Include="Utils\EnumUtils.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\CollectionExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\DictionaryExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\EnumerableExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\EnumExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\EventHandlerExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\JsonExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\QueueExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\ReflectionExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\StringBuilderExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\StringExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Extensions\TimeSpanExtensions.cs" />
|
||||||
|
<Compile Include="Utils\IcdErrorLog.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdEncodingStringWriter.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdFile.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdFileStream.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdMemoryStream.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdPath.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdStream.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdStreamReader.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdStringReader.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdStringWriter.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdTextReader.cs" />
|
||||||
|
<Compile Include="Utils\IO\IcdTextWriter.cs" />
|
||||||
|
<Compile Include="Utils\IStateDisposable.cs" />
|
||||||
|
<Compile Include="Utils\Json\AbstractGenericJsonConverter.cs" />
|
||||||
|
<Compile Include="Utils\Json\JsonItemWrapper.cs" />
|
||||||
|
<Compile Include="Utils\Json\JsonUtils.cs" />
|
||||||
|
<Compile Include="Utils\MathUtils.cs" />
|
||||||
|
<Compile Include="Utils\PathUtils.cs" />
|
||||||
|
<Compile Include="Utils\PrettyPrint.cs" />
|
||||||
|
<Compile Include="Utils\ProgramUtils.cs" />
|
||||||
|
<Compile Include="Utils\ReflectionUtils.cs" />
|
||||||
|
<Compile Include="Utils\SafeCriticalSection.cs" />
|
||||||
|
<Compile Include="Utils\SafeCriticalSection.SimplSharp.cs" />
|
||||||
|
<Compile Include="Utils\SafeCriticalSection.Standard.cs" />
|
||||||
|
<Compile Include="Utils\SafeMutex.cs" />
|
||||||
|
<Compile Include="Utils\StringUtils.cs" />
|
||||||
|
<Compile Include="Utils\TableBuilder.cs" />
|
||||||
|
<Compile Include="Utils\Timers\IcdStopwatch.cs" />
|
||||||
|
<Compile Include="Utils\Timers\IcdTimer.cs" />
|
||||||
|
<Compile Include="Utils\Timers\Repeater.cs" />
|
||||||
|
<Compile Include="Utils\Timers\SafeTimer.cs" />
|
||||||
|
<Compile Include="Utils\TryUtils.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlConvert.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlDocument.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlException.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlReader.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlTextWriter.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlTextWriter.SimplSharp.cs" />
|
||||||
|
<Compile Include="Utils\Xml\IcdXmlAttribute.cs" />
|
||||||
|
<Compile Include="Utils\Xml\XmlReaderExtensions.cs" />
|
||||||
|
<Compile Include="Utils\Xml\XmlUtils.cs" />
|
||||||
|
<None Include="Properties\ControlSystem.cfg" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CompactFramework.CSharp.targets" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<PostBuildEvent>if /I "$(ConfigurationName)" == "Release" Eazfuscator.NET.exe "$(TargetPath)" --msbuild-project-path "$(ProjectPath)" --msbuild-project-configuration "$(ConfigurationName)" --msbuild-project-platform "$(PlatformName)" --msbuild-solution-path "$(SolutionPath)" -n --newline-flush -v 5.2 --configuration-file="$(ProjectDir)ObfuscationSettings.cs"
|
||||||
|
rem S# Pro preparation will execute after these operations</PostBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
6
ICD.Common/ObfuscationSettings.cs
Normal file
6
ICD.Common/ObfuscationSettings.cs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
[assembly: Obfuscation(Feature = "platform api: System.Threading.Thread, System.Reflection.*, System.IO.Stream, System.Windows.Forms.*", Exclude = true)]
|
||||||
|
[assembly: Obfuscation(Feature = "rename symbol names with printable characters", Exclude = false)]
|
||||||
|
[assembly: Obfuscation(Feature = "code control flow obfuscation", Exclude = false)]
|
||||||
|
[assembly: Obfuscation(Feature = "Apply to type * when class: renaming", Exclude = true, ApplyToMembers = false)]
|
||||||
713
ICD.Common/Properties/Annotations.cs
Normal file
713
ICD.Common/Properties/Annotations.cs
Normal file
@@ -0,0 +1,713 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
#pragma warning disable 1591
|
||||||
|
// ReSharper disable UnusedMember.Global
|
||||||
|
// ReSharper disable UnusedParameter.Local
|
||||||
|
// ReSharper disable MemberCanBePrivate.Global
|
||||||
|
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
||||||
|
// ReSharper disable IntroduceOptionalParameters.Global
|
||||||
|
// ReSharper disable MemberCanBeProtected.Global
|
||||||
|
// ReSharper disable InconsistentNaming
|
||||||
|
// ReSharper disable CheckNamespace
|
||||||
|
|
||||||
|
namespace ICD.Common.Properties
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the value of the marked element could be <c>null</c> sometimes,
|
||||||
|
/// so the check for <c>null</c> is necessary before its usage
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [CanBeNull] public object Test() { return null; }
|
||||||
|
/// public void UseTest() {
|
||||||
|
/// var p = Test();
|
||||||
|
/// var s = p.ToString(); // Warning: Possible 'System.NullReferenceException'
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||||
|
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||||
|
AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class CanBeNullAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the value of the marked element could never be <c>null</c>
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [NotNull] public object Foo() {
|
||||||
|
/// return null; // Warning: Possible 'null' assignment
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Method | AttributeTargets.Parameter |
|
||||||
|
AttributeTargets.Property | AttributeTargets.Delegate |
|
||||||
|
AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class NotNullAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the marked method builds string by format pattern and (optional) arguments.
|
||||||
|
/// Parameter, which contains format string, should be given in constructor. The format string
|
||||||
|
/// should be in <see cref="string.Format(IFormatProvider,string,object[])"/>-like form
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [StringFormatMethod("message")]
|
||||||
|
/// public void ShowError(string message, params object[] args) { /* do something */ }
|
||||||
|
/// public void Foo() {
|
||||||
|
/// ShowError("Failed: {0}"); // Warning: Non-existing argument in format string
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Constructor | AttributeTargets.Method,
|
||||||
|
AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class StringFormatMethodAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <param name="formatParameterName">
|
||||||
|
/// Specifies which parameter of an annotated method should be treated as format-string
|
||||||
|
/// </param>
|
||||||
|
public StringFormatMethodAttribute(string formatParameterName)
|
||||||
|
{
|
||||||
|
FormatParameterName = formatParameterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatParameterName { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the function argument should be string literal and match one
|
||||||
|
/// of the parameters of the caller function. For example, ReSharper annotates
|
||||||
|
/// the parameter of <see cref="System.ArgumentNullException"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// public void Foo(string param) {
|
||||||
|
/// if (param == null)
|
||||||
|
/// throw new ArgumentNullException("par"); // Warning: Cannot resolve symbol
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class InvokerParameterNameAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the method is contained in a type that implements
|
||||||
|
/// <see cref="System.ComponentModel.INotifyPropertyChanged"/> interface
|
||||||
|
/// and this method is used to notify that some property value changed
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The method should be non-static and conform to one of the supported signatures:
|
||||||
|
/// <list>
|
||||||
|
/// <item><c>NotifyChanged(string)</c></item>
|
||||||
|
/// <item><c>NotifyChanged(params string[])</c></item>
|
||||||
|
/// <item><c>NotifyChanged{T}(Expression{Func{T}})</c></item>
|
||||||
|
/// <item><c>NotifyChanged{T,U}(Expression{Func{T,U}})</c></item>
|
||||||
|
/// <item><c>SetProperty{T}(ref T, T, string)</c></item>
|
||||||
|
/// </list>
|
||||||
|
/// </remarks>
|
||||||
|
/// <example><code>
|
||||||
|
/// public class Foo : INotifyPropertyChanged {
|
||||||
|
/// public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
/// [NotifyPropertyChangedInvocator]
|
||||||
|
/// protected virtual void NotifyChanged(string propertyName) { ... }
|
||||||
|
///
|
||||||
|
/// private string _name;
|
||||||
|
/// public string Name {
|
||||||
|
/// get { return _name; }
|
||||||
|
/// set { _name = value; NotifyChanged("LastName"); /* Warning */ }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// </code>
|
||||||
|
/// Examples of generated notifications:
|
||||||
|
/// <list>
|
||||||
|
/// <item><c>NotifyChanged("Property")</c></item>
|
||||||
|
/// <item><c>NotifyChanged(() => Property)</c></item>
|
||||||
|
/// <item><c>NotifyChanged((VM x) => x.Property)</c></item>
|
||||||
|
/// <item><c>SetProperty(ref myField, value, "Property")</c></item>
|
||||||
|
/// </list>
|
||||||
|
/// </example>
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class NotifyPropertyChangedInvocatorAttribute : Attribute
|
||||||
|
{
|
||||||
|
public NotifyPropertyChangedInvocatorAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotifyPropertyChangedInvocatorAttribute(string parameterName)
|
||||||
|
{
|
||||||
|
ParameterName = parameterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ParameterName { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Describes dependency between method input and output
|
||||||
|
/// </summary>
|
||||||
|
/// <syntax>
|
||||||
|
/// <p>Function Definition Table syntax:</p>
|
||||||
|
/// <list>
|
||||||
|
/// <item>FDT ::= FDTRow [;FDTRow]*</item>
|
||||||
|
/// <item>FDTRow ::= Input => Output | Output <= Input</item>
|
||||||
|
/// <item>Input ::= ParameterName: Value [, Input]*</item>
|
||||||
|
/// <item>Output ::= [ParameterName: Value]* {halt|stop|void|nothing|Value}</item>
|
||||||
|
/// <item>Value ::= true | false | null | notnull | canbenull</item>
|
||||||
|
/// </list>
|
||||||
|
/// If method has single input parameter, it's name could be omitted.<br/>
|
||||||
|
/// Using <c>halt</c> (or <c>void</c>/<c>nothing</c>, which is the same)
|
||||||
|
/// for method output means that the methos doesn't return normally.<br/>
|
||||||
|
/// <c>canbenull</c> annotation is only applicable for output parameters.<br/>
|
||||||
|
/// You can use multiple <c>[ContractAnnotation]</c> for each FDT row,
|
||||||
|
/// or use single attribute with rows separated by semicolon.<br/>
|
||||||
|
/// </syntax>
|
||||||
|
/// <examples><list>
|
||||||
|
/// <item><code>
|
||||||
|
/// [ContractAnnotation("=> halt")]
|
||||||
|
/// public void TerminationMethod()
|
||||||
|
/// </code></item>
|
||||||
|
/// <item><code>
|
||||||
|
/// [ContractAnnotation("halt <= condition: false")]
|
||||||
|
/// public void Assert(bool condition, string text) // regular assertion method
|
||||||
|
/// </code></item>
|
||||||
|
/// <item><code>
|
||||||
|
/// [ContractAnnotation("s:null => true")]
|
||||||
|
/// public bool IsNullOrEmpty(string s) // string.IsNullOrEmpty()
|
||||||
|
/// </code></item>
|
||||||
|
/// <item><code>
|
||||||
|
/// // A method that returns null if the parameter is null, and not null if the parameter is not null
|
||||||
|
/// [ContractAnnotation("null => null; notnull => notnull")]
|
||||||
|
/// public object Transform(object data)
|
||||||
|
/// </code></item>
|
||||||
|
/// <item><code>
|
||||||
|
/// [ContractAnnotation("s:null=>false; =>true,result:notnull; =>false, result:null")]
|
||||||
|
/// public bool TryParse(string s, out Person result)
|
||||||
|
/// </code></item>
|
||||||
|
/// </list></examples>
|
||||||
|
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
|
||||||
|
public sealed class ContractAnnotationAttribute : Attribute
|
||||||
|
{
|
||||||
|
public ContractAnnotationAttribute([NotNull] string contract)
|
||||||
|
: this(contract, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContractAnnotationAttribute([NotNull] string contract, bool forceFullStates)
|
||||||
|
{
|
||||||
|
Contract = contract;
|
||||||
|
ForceFullStates = forceFullStates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Contract { get; private set; }
|
||||||
|
public bool ForceFullStates { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that marked element should be localized or not
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [LocalizationRequiredAttribute(true)]
|
||||||
|
/// public class Foo {
|
||||||
|
/// private string str = "my string"; // Warning: Localizable string
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class LocalizationRequiredAttribute : Attribute
|
||||||
|
{
|
||||||
|
public LocalizationRequiredAttribute() : this(true)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalizationRequiredAttribute(bool required)
|
||||||
|
{
|
||||||
|
Required = required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Required { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the value of the marked type (or its derivatives)
|
||||||
|
/// cannot be compared using '==' or '!=' operators and <c>Equals()</c>
|
||||||
|
/// should be used instead. However, using '==' or '!=' for comparison
|
||||||
|
/// with <c>null</c> is always permitted.
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [CannotApplyEqualityOperator]
|
||||||
|
/// class NoEquality { }
|
||||||
|
/// class UsesNoEquality {
|
||||||
|
/// public void Test() {
|
||||||
|
/// var ca1 = new NoEquality();
|
||||||
|
/// var ca2 = new NoEquality();
|
||||||
|
/// if (ca1 != null) { // OK
|
||||||
|
/// bool condition = ca1 == ca2; // Warning
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Interface | AttributeTargets.Class |
|
||||||
|
AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class CannotApplyEqualityOperatorAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When applied to a target attribute, specifies a requirement for any type marked
|
||||||
|
/// with the target attribute to implement or inherit specific type or types.
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
|
||||||
|
/// public class ComponentAttribute : Attribute { }
|
||||||
|
/// [Component] // ComponentAttribute requires implementing IComponent interface
|
||||||
|
/// public class MyComponent : IComponent { }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
|
||||||
|
[BaseTypeRequired(typeof(Attribute))]
|
||||||
|
public sealed class BaseTypeRequiredAttribute : Attribute
|
||||||
|
{
|
||||||
|
public BaseTypeRequiredAttribute([NotNull] Type baseType)
|
||||||
|
{
|
||||||
|
BaseType = baseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public Type BaseType { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the marked symbol is used implicitly
|
||||||
|
/// (e.g. via reflection, in external library), so this symbol
|
||||||
|
/// will not be marked as unused (as well as by other usage inspections)
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class UsedImplicitlyAttribute : Attribute
|
||||||
|
{
|
||||||
|
public UsedImplicitlyAttribute()
|
||||||
|
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Itself)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
|
||||||
|
: this(useKindFlags, ImplicitUseTargetFlags.Itself)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
|
||||||
|
: this(ImplicitUseKindFlags.Default, targetFlags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsedImplicitlyAttribute(
|
||||||
|
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
|
||||||
|
{
|
||||||
|
UseKindFlags = useKindFlags;
|
||||||
|
TargetFlags = targetFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImplicitUseKindFlags UseKindFlags { get; private set; }
|
||||||
|
public ImplicitUseTargetFlags TargetFlags { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Should be used on attributes and causes ReSharper
|
||||||
|
/// to not mark symbols marked with such attributes as unused
|
||||||
|
/// (as well as by other usage inspections)
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
|
||||||
|
public sealed class MeansImplicitUseAttribute : Attribute
|
||||||
|
{
|
||||||
|
public MeansImplicitUseAttribute()
|
||||||
|
: this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Itself)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
|
||||||
|
: this(useKindFlags, ImplicitUseTargetFlags.Itself)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
|
||||||
|
: this(ImplicitUseKindFlags.Default, targetFlags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeansImplicitUseAttribute(
|
||||||
|
ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
|
||||||
|
{
|
||||||
|
UseKindFlags = useKindFlags;
|
||||||
|
TargetFlags = targetFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public ImplicitUseKindFlags UseKindFlags { get; private set; }
|
||||||
|
|
||||||
|
[UsedImplicitly]
|
||||||
|
public ImplicitUseTargetFlags TargetFlags { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum ImplicitUseKindFlags
|
||||||
|
{
|
||||||
|
Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
|
||||||
|
|
||||||
|
/// <summary>Only entity marked with attribute considered used</summary>
|
||||||
|
Access = 1,
|
||||||
|
|
||||||
|
/// <summary>Indicates implicit assignment to a member</summary>
|
||||||
|
Assign = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates implicit instantiation of a type with fixed constructor signature.
|
||||||
|
/// That means any unused constructor parameters won't be reported as such.
|
||||||
|
/// </summary>
|
||||||
|
InstantiatedWithFixedConstructorSignature = 4,
|
||||||
|
|
||||||
|
/// <summary>Indicates implicit instantiation of a type</summary>
|
||||||
|
InstantiatedNoFixedConstructorSignature = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Specify what is considered used implicitly
|
||||||
|
/// when marked with <see cref="MeansImplicitUseAttribute"/>
|
||||||
|
/// or <see cref="UsedImplicitlyAttribute"/>
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum ImplicitUseTargetFlags
|
||||||
|
{
|
||||||
|
Itself = 1,
|
||||||
|
|
||||||
|
/// <summary>Members of entity marked with attribute are considered used</summary>
|
||||||
|
Members = 2,
|
||||||
|
|
||||||
|
/// <summary>Entity marked with attribute and all its members considered used</summary>
|
||||||
|
WithMembers = Itself | Members
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This attribute is intended to mark publicly available API
|
||||||
|
/// which should not be removed and so is treated as used
|
||||||
|
/// </summary>
|
||||||
|
[MeansImplicitUse]
|
||||||
|
public sealed class PublicAPIAttribute : Attribute
|
||||||
|
{
|
||||||
|
public PublicAPIAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicAPIAttribute([NotNull] string comment)
|
||||||
|
{
|
||||||
|
Comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string Comment { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tells code analysis engine if the parameter is completely handled
|
||||||
|
/// when the invoked method is on stack. If the parameter is a delegate,
|
||||||
|
/// indicates that delegate is executed while the method is executed.
|
||||||
|
/// If the parameter is an enumerable, indicates that it is enumerated
|
||||||
|
/// while the method is executed
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter, Inherited = true)]
|
||||||
|
public sealed class InstantHandleAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that a method does not make any observable state changes.
|
||||||
|
/// The same as <c>System.Diagnostics.Contracts.PureAttribute</c>
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [Pure] private int Multiply(int x, int y) { return x * y; }
|
||||||
|
/// public void Foo() {
|
||||||
|
/// const int a = 2, b = 2;
|
||||||
|
/// Multiply(a, b); // Waring: Return value of pure method is not used
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
|
||||||
|
public sealed class PureAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that a parameter is a path to a file or a folder
|
||||||
|
/// within a web project. Path can be relative or absolute,
|
||||||
|
/// starting from web root (~)
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public class PathReferenceAttribute : Attribute
|
||||||
|
{
|
||||||
|
public PathReferenceAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PathReferenceAttribute([PathReference] string basePath)
|
||||||
|
{
|
||||||
|
BasePath = basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string BasePath { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASP.NET MVC attributes
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class AspMvcAreaMasterLocationFormatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcAreaMasterLocationFormatAttribute(string format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class AspMvcAreaPartialViewLocationFormatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcAreaPartialViewLocationFormatAttribute(string format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class AspMvcAreaViewLocationFormatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcAreaViewLocationFormatAttribute(string format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class AspMvcMasterLocationFormatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcMasterLocationFormatAttribute(string format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class AspMvcPartialViewLocationFormatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcPartialViewLocationFormatAttribute(string format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
|
||||||
|
public sealed class AspMvcViewLocationFormatAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcViewLocationFormatAttribute(string format)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
|
||||||
|
/// is an MVC action. If applied to a method, the MVC action name is calculated
|
||||||
|
/// implicitly from the context. Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||||
|
public sealed class AspMvcActionAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcActionAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AspMvcActionAttribute([NotNull] string anonymousProperty)
|
||||||
|
{
|
||||||
|
AnonymousProperty = anonymousProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string AnonymousProperty { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC area.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public sealed class AspMvcAreaAttribute : PathReferenceAttribute
|
||||||
|
{
|
||||||
|
public AspMvcAreaAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AspMvcAreaAttribute([NotNull] string anonymousProperty)
|
||||||
|
{
|
||||||
|
AnonymousProperty = anonymousProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string AnonymousProperty { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. If applied to a parameter, indicates that
|
||||||
|
/// the parameter is an MVC controller. If applied to a method,
|
||||||
|
/// the MVC controller name is calculated implicitly from the context.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper, String, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||||
|
public sealed class AspMvcControllerAttribute : Attribute
|
||||||
|
{
|
||||||
|
public AspMvcControllerAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public AspMvcControllerAttribute([NotNull] string anonymousProperty)
|
||||||
|
{
|
||||||
|
AnonymousProperty = anonymousProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string AnonymousProperty { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC Master.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Controller.View(String, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public sealed class AspMvcMasterAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC model type.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Controller.View(String, Object)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public sealed class AspMvcModelTypeAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. If applied to a parameter, indicates that
|
||||||
|
/// the parameter is an MVC partial view. If applied to a method,
|
||||||
|
/// the MVC partial view name is calculated implicitly from the context.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||||
|
public sealed class AspMvcPartialViewAttribute : PathReferenceAttribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Allows disabling all inspections
|
||||||
|
/// for MVC views within a class or a method.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
|
public sealed class AspMvcSupressViewErrorAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC display template.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Html.DisplayExtensions.DisplayForModel(HtmlHelper, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public sealed class AspMvcDisplayTemplateAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC editor template.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Html.EditorExtensions.EditorForModel(HtmlHelper, String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public sealed class AspMvcEditorTemplateAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. Indicates that a parameter is an MVC template.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.ComponentModel.DataAnnotations.UIHintAttribute(System.String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter)]
|
||||||
|
public sealed class AspMvcTemplateAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. If applied to a parameter, indicates that the parameter
|
||||||
|
/// is an MVC view. If applied to a method, the MVC view name is calculated implicitly
|
||||||
|
/// from the context. Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.Mvc.Controller.View(Object)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method)]
|
||||||
|
public sealed class AspMvcViewAttribute : PathReferenceAttribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ASP.NET MVC attribute. When applied to a parameter of an attribute,
|
||||||
|
/// indicates that this parameter is an MVC action name
|
||||||
|
/// </summary>
|
||||||
|
/// <example><code>
|
||||||
|
/// [ActionName("Foo")]
|
||||||
|
/// public ActionResult Login(string returnUrl) {
|
||||||
|
/// ViewBag.ReturnUrl = Url.Action("Foo"); // OK
|
||||||
|
/// return RedirectToAction("Bar"); // Error: Cannot resolve action
|
||||||
|
/// }
|
||||||
|
/// </code></example>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property)]
|
||||||
|
public sealed class AspMvcActionSelectorAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Parameter | AttributeTargets.Property |
|
||||||
|
AttributeTargets.Field, Inherited = true)]
|
||||||
|
public sealed class HtmlElementAttributesAttribute : Attribute
|
||||||
|
{
|
||||||
|
public HtmlElementAttributesAttribute()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public HtmlElementAttributesAttribute([NotNull] string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string Name { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(
|
||||||
|
AttributeTargets.Parameter | AttributeTargets.Field |
|
||||||
|
AttributeTargets.Property, Inherited = true)]
|
||||||
|
public sealed class HtmlAttributeValueAttribute : Attribute
|
||||||
|
{
|
||||||
|
public HtmlAttributeValueAttribute([NotNull] string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
[NotNull]
|
||||||
|
public string Name { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Razor attributes
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Razor attribute. Indicates that a parameter or a method is a Razor section.
|
||||||
|
/// Use this attribute for custom wrappers similar to
|
||||||
|
/// <c>System.Web.WebPages.WebPageBase.RenderSection(String)</c>
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Method, Inherited = true)]
|
||||||
|
public sealed class RazorSectionAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
7
ICD.Common/Properties/AssemblyInfo.cs
Normal file
7
ICD.Common/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
[assembly: AssemblyTitle("ICD.SimplSharp.Common")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("ICD.SimplSharp.Common")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © ICD Systems 2017")]
|
||||||
|
[assembly: AssemblyVersion("1.0.1.*")]
|
||||||
0
ICD.Common/Properties/ControlSystem.cfg
Normal file
0
ICD.Common/Properties/ControlSystem.cfg
Normal file
94
ICD.Common/Services/Logging/ILoggerService.cs
Normal file
94
ICD.Common/Services/Logging/ILoggerService.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils;
|
||||||
|
|
||||||
|
namespace ICD.Common.Services.Logging
|
||||||
|
{
|
||||||
|
public enum eSeverity
|
||||||
|
{
|
||||||
|
Emergency = 0,
|
||||||
|
Alert = 1,
|
||||||
|
Critical = 2,
|
||||||
|
Error = 3,
|
||||||
|
Warning = 4,
|
||||||
|
Notice = 5,
|
||||||
|
Informational = 6,
|
||||||
|
Debug = 7
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface ILoggerService
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
event EventHandler<LogItemEventArgs> OnEntryAdded;
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
event EventHandler<SeverityEventArgs> OnSeverityLevelChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets and sets the severity level.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
eSeverity SeverityLevel { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the log item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item">Log entry to add</param>
|
||||||
|
[PublicAPI]
|
||||||
|
void AddEntry(LogItem item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the log history.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
KeyValuePair<int, LogItem>[] GetHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for ILoggerService.
|
||||||
|
/// </summary>
|
||||||
|
public static class LoggerServiceExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the log item with string formatting.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="severity">Severity Code, 0 - 7</param>
|
||||||
|
/// <param name="message">Message Text format string</param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddEntry(this ILoggerService extends, eSeverity severity, string message)
|
||||||
|
{
|
||||||
|
LogItem item = new LogItem(severity, message);
|
||||||
|
extends.AddEntry(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the log item with string formatting.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="severity">Severity Code, 0 - 7</param>
|
||||||
|
/// <param name="message">Message Text format string</param>
|
||||||
|
/// <param name="args">objects to format into the string</param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddEntry(this ILoggerService extends, eSeverity severity, string message, params object[] args)
|
||||||
|
{
|
||||||
|
extends.AddEntry(severity, string.Format(message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddEntry(this ILoggerService extends, eSeverity severity, Exception e, string message)
|
||||||
|
{
|
||||||
|
extends.AddEntry(severity, string.Format("{0}: {1}{2}{3}{2}{4}", e.GetType().Name, message,
|
||||||
|
IcdEnvironment.NewLine, e.Message, e.StackTrace));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddEntry(this ILoggerService extends, eSeverity severity, Exception e, string message,
|
||||||
|
params object[] args)
|
||||||
|
{
|
||||||
|
extends.AddEntry(severity, e, string.Format(message, args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
126
ICD.Common/Services/Logging/LogItem.cs
Normal file
126
ICD.Common/Services/Logging/LogItem.cs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils;
|
||||||
|
|
||||||
|
namespace ICD.Common.Services.Logging
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Log Entry Item
|
||||||
|
/// </summary>
|
||||||
|
public struct LogItem
|
||||||
|
{
|
||||||
|
private readonly string m_Message;
|
||||||
|
private readonly eSeverity m_Severity;
|
||||||
|
private readonly DateTime m_Timestamp;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Accessor only for timestamp.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public DateTime Timestamp { get { return m_Timestamp; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set for severity level.
|
||||||
|
/// </summary>
|
||||||
|
public eSeverity Severity { get { return m_Severity; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set for message string.
|
||||||
|
/// </summary>
|
||||||
|
public string Message { get { return m_Message; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new LogItem object with the specified values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="severity">Severity Level, between 0 and 7</param>
|
||||||
|
/// <param name="message">Error message text</param>
|
||||||
|
public LogItem(eSeverity severity, string message)
|
||||||
|
{
|
||||||
|
m_Severity = severity;
|
||||||
|
m_Message = message;
|
||||||
|
m_Timestamp = IcdEnvironment.GetLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the text format to send to Fusion
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>text format for fusion, including timestamp, severity, and message</returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public string GetFusionLogText()
|
||||||
|
{
|
||||||
|
StringBuilder s = new StringBuilder();
|
||||||
|
|
||||||
|
s.Append(Timestamp.ToString("yyyyMMddHHmmss"));
|
||||||
|
s.Append("||");
|
||||||
|
s.Append((int)Severity);
|
||||||
|
s.Append("||");
|
||||||
|
s.Append(Message);
|
||||||
|
|
||||||
|
return s.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementing default equality.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a1"></param>
|
||||||
|
/// <param name="a2"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator ==(LogItem a1, LogItem a2)
|
||||||
|
{
|
||||||
|
return a1.Equals(a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementing default inequality.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a1"></param>
|
||||||
|
/// <param name="a2"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator !=(LogItem a1, LogItem a2)
|
||||||
|
{
|
||||||
|
return !(a1 == a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this instance is equal to the given object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (other == null || GetType() != other.GetType())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return GetHashCode() == ((LogItem)other).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the hashcode for this instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 23 + (m_Message == null ? 0 : m_Message.GetHashCode());
|
||||||
|
hash = hash * 23 + (int)m_Timestamp.Ticks;
|
||||||
|
hash = hash * 23 + (int)m_Severity;
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
16
ICD.Common/Services/Logging/LogItemEventArgs.cs
Normal file
16
ICD.Common/Services/Logging/LogItemEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using ICD.Common.EventArguments;
|
||||||
|
|
||||||
|
namespace ICD.Common.Services.Logging
|
||||||
|
{
|
||||||
|
public sealed class LogItemEventArgs : GenericEventArgs<LogItem>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
public LogItemEventArgs(LogItem item)
|
||||||
|
: base(item)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
ICD.Common/Services/Logging/SeverityEventArgs.cs
Normal file
16
ICD.Common/Services/Logging/SeverityEventArgs.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using ICD.Common.EventArguments;
|
||||||
|
|
||||||
|
namespace ICD.Common.Services.Logging
|
||||||
|
{
|
||||||
|
public sealed class SeverityEventArgs : GenericEventArgs<eSeverity>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
public SeverityEventArgs(eSeverity data)
|
||||||
|
: base(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
ICD.Common/Services/ServiceNotFoundException.cs
Normal file
28
ICD.Common/Services/ServiceNotFoundException.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Services
|
||||||
|
{
|
||||||
|
public sealed class ServiceNotFoundException : Exception
|
||||||
|
{
|
||||||
|
private const string DEFAULT_MESSAGE = "The requested service {0} was not found in the service provider";
|
||||||
|
|
||||||
|
public Type ServiceType { get; set; }
|
||||||
|
|
||||||
|
public ServiceNotFoundException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceNotFoundException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceNotFoundException(string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceNotFoundException(Type type) : base(string.Format(DEFAULT_MESSAGE, type.Name))
|
||||||
|
{
|
||||||
|
ServiceType = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
162
ICD.Common/Services/ServiceProvider.cs
Normal file
162
ICD.Common/Services/ServiceProvider.cs
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils;
|
||||||
|
|
||||||
|
namespace ICD.Common.Services
|
||||||
|
{
|
||||||
|
public sealed class ServiceProvider : IDisposable
|
||||||
|
{
|
||||||
|
#region Static
|
||||||
|
|
||||||
|
private static ServiceProvider s_Instance;
|
||||||
|
|
||||||
|
private static ServiceProvider Instance { get { return s_Instance ?? (s_Instance = new ServiceProvider()); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the registered service of the given type. Use this for required dependencies.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TService">service type to retrieve</typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ServiceNotFoundException">Thrown if a service of the given type is not registered</exception>
|
||||||
|
[PublicAPI]
|
||||||
|
[NotNull]
|
||||||
|
public static TService GetService<TService>()
|
||||||
|
{
|
||||||
|
return (TService)GetService(typeof(TService));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the registered service of the given type. Use this for required dependencies.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tService">service type to retrieve</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ServiceNotFoundException">Thrown if a service of the given type is not registered</exception>
|
||||||
|
[PublicAPI]
|
||||||
|
[NotNull]
|
||||||
|
public static object GetService(Type tService)
|
||||||
|
{
|
||||||
|
return Instance.GetServiceInstance(tService);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the registered service of the given type. Returns null if the service type was not found.
|
||||||
|
/// Use this for optional dependencies.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TService">service type to retrieve</typeparam>
|
||||||
|
/// <returns>requested service or null if that service type is not registered</returns>
|
||||||
|
[PublicAPI]
|
||||||
|
[CanBeNull]
|
||||||
|
public static TService TryGetService<TService>()
|
||||||
|
{
|
||||||
|
return (TService)TryGetService(typeof(TService));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the registered service of the given type. Returns null if the service type was not found.
|
||||||
|
/// Use this for optional dependencies.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tService">service type to retrieve</param>
|
||||||
|
/// <returns>requested service or null if that service type is not registered</returns>
|
||||||
|
[PublicAPI]
|
||||||
|
[CanBeNull]
|
||||||
|
public static object TryGetService(Type tService)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Instance.GetServiceInstance(tService);
|
||||||
|
}
|
||||||
|
catch (ServiceNotFoundException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a service instance to the type given.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TService"></typeparam>
|
||||||
|
/// <param name="service"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddService<TService>(TService service)
|
||||||
|
{
|
||||||
|
AddService(typeof(TService), service);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Registers a service instance to the type given.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tService"></param>
|
||||||
|
/// <param name="service"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddService(Type tService, object service)
|
||||||
|
{
|
||||||
|
Instance.AddServiceInstance(tService, service);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private readonly Dictionary<Type, object> m_Services = new Dictionary<Type, object>();
|
||||||
|
private readonly SafeCriticalSection m_ServicesSection = new SafeCriticalSection();
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
private object GetServiceInstance(Type tService)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_ServicesSection.Enter();
|
||||||
|
|
||||||
|
object service;
|
||||||
|
if (m_Services.TryGetValue(tService, out service) && service != null)
|
||||||
|
return service;
|
||||||
|
throw new ServiceNotFoundException(tService);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ServicesSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
private void AddServiceInstance(Type tService, object service)
|
||||||
|
{
|
||||||
|
m_ServicesSection.Enter();
|
||||||
|
m_Services[tService] = service;
|
||||||
|
m_ServicesSection.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_ServicesSection.Enter();
|
||||||
|
foreach (object service in m_Services.Values.Distinct())
|
||||||
|
{
|
||||||
|
if (!(service is IDisposable))
|
||||||
|
continue;
|
||||||
|
((IDisposable)service).Dispose();
|
||||||
|
}
|
||||||
|
m_Services.Clear();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_ServicesSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DisposeStatic()
|
||||||
|
{
|
||||||
|
if (s_Instance != null)
|
||||||
|
s_Instance.Dispose();
|
||||||
|
s_Instance = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
227
ICD.Common/Utils/AttributeUtils.cs
Normal file
227
ICD.Common/Utils/AttributeUtils.cs
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
|
#else
|
||||||
|
using System.Reflection;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Services;
|
||||||
|
using ICD.Common.Services.Logging;
|
||||||
|
using ICD.Common.Utils.Collections;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility methods for browsing code attributes.
|
||||||
|
/// Provides some basic caching for faster subsequent searches.
|
||||||
|
/// </summary>
|
||||||
|
public static class AttributeUtils
|
||||||
|
{
|
||||||
|
// Avoid caching the same assembly multiple times.
|
||||||
|
private static readonly IcdHashSet<Assembly> s_CachedAssemblies;
|
||||||
|
private static readonly IcdHashSet<Type> s_CachedTypes;
|
||||||
|
|
||||||
|
private static readonly Dictionary<Attribute, MethodInfo> s_AttributeToMethodCache;
|
||||||
|
private static readonly Dictionary<Type, IcdHashSet<Attribute>> s_TypeToAttributesCache;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
static AttributeUtils()
|
||||||
|
{
|
||||||
|
s_CachedAssemblies = new IcdHashSet<Assembly>();
|
||||||
|
s_CachedTypes = new IcdHashSet<Type>();
|
||||||
|
|
||||||
|
s_AttributeToMethodCache = new Dictionary<Attribute, MethodInfo>();
|
||||||
|
s_TypeToAttributesCache = new Dictionary<Type, IcdHashSet<Attribute>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Caching
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pre-emptively caches the given assemblies for lookup.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assemblies"></param>
|
||||||
|
public static void CacheAssemblies(IEnumerable<Assembly> assemblies)
|
||||||
|
{
|
||||||
|
if (assemblies == null)
|
||||||
|
throw new ArgumentNullException("assemblies");
|
||||||
|
|
||||||
|
foreach (Assembly assembly in assemblies)
|
||||||
|
CacheAssembly(assembly);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pre-emptively caches the given assembly for lookup.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assembly"></param>
|
||||||
|
public static void CacheAssembly(Assembly assembly)
|
||||||
|
{
|
||||||
|
if (assembly == null)
|
||||||
|
throw new ArgumentNullException("assembly");
|
||||||
|
|
||||||
|
if (s_CachedAssemblies.Contains(assembly))
|
||||||
|
return;
|
||||||
|
s_CachedAssemblies.Add(assembly);
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CType[] types = new CType[0];
|
||||||
|
#else
|
||||||
|
Type[] types = new Type[0];
|
||||||
|
#endif
|
||||||
|
try
|
||||||
|
{
|
||||||
|
types = assembly.GetTypes();
|
||||||
|
}
|
||||||
|
catch (TypeLoadException e)
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Error, e, "Failed to cache assembly {0} - {1}", assembly.GetName().Name,
|
||||||
|
e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var type in types)
|
||||||
|
CacheType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pre-emptively caches the given type for lookup.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
#if SIMPLSHARP
|
||||||
|
public static void CacheType(CType type)
|
||||||
|
#else
|
||||||
|
public static void CacheType(Type type)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
if (s_CachedTypes.Contains(type))
|
||||||
|
return;
|
||||||
|
s_CachedTypes.Add(type);
|
||||||
|
|
||||||
|
MethodInfo[] methods;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
s_TypeToAttributesCache[type] = new IcdHashSet<Attribute>(type.GetCustomAttributes<Attribute>(false));
|
||||||
|
methods = type.GetMethods();
|
||||||
|
#else
|
||||||
|
s_TypeToAttributesCache[type] = new IcdHashSet<Attribute>(type.GetTypeInfo().GetCustomAttributes<Attribute>(false));
|
||||||
|
methods = type.GetTypeInfo().GetMethods();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// GetMethods for Open Generic Types is not supported.
|
||||||
|
catch (NotSupportedException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Not sure why this happens :/
|
||||||
|
catch (InvalidProgramException)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (MethodInfo method in methods)
|
||||||
|
CacheMethod(method);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Caches the method.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="method"></param>
|
||||||
|
private static void CacheMethod(MethodInfo method)
|
||||||
|
{
|
||||||
|
if (method == null)
|
||||||
|
throw new ArgumentNullException("method");
|
||||||
|
|
||||||
|
foreach (Attribute attribute in method.GetCustomAttributes<Attribute>(false))
|
||||||
|
s_AttributeToMethodCache[attribute] = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Lookup
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the first attribute on the given class type matching the generic type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[CanBeNull]
|
||||||
|
public static T GetClassAttribute<T>(Type type)
|
||||||
|
where T : Attribute
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
return GetClassAttributes<T>(type).FirstOrDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the attributes on the given class type matching the generic type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetClassAttributes<T>(Type type)
|
||||||
|
where T : Attribute
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
return GetClassAttributes(type).OfType<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the attributes on the given class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<Attribute> GetClassAttributes(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
CacheType(type);
|
||||||
|
|
||||||
|
return s_TypeToAttributesCache.ContainsKey(type)
|
||||||
|
? s_TypeToAttributesCache[type].ToArray()
|
||||||
|
: Enumerable.Empty<Attribute>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all of the cached method attributes of the given type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetMethodAttributes<T>()
|
||||||
|
where T : Attribute
|
||||||
|
{
|
||||||
|
return s_AttributeToMethodCache.Select(p => p.Key)
|
||||||
|
.OfType<T>()
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the cached method for the given attribute.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="attribute"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static MethodInfo GetMethod(Attribute attribute)
|
||||||
|
{
|
||||||
|
if (attribute == null)
|
||||||
|
throw new ArgumentNullException("attribute");
|
||||||
|
|
||||||
|
return s_AttributeToMethodCache[attribute];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
269
ICD.Common/Utils/Collections/IcdHashSet.cs
Normal file
269
ICD.Common/Utils/Collections/IcdHashSet.cs
Normal file
@@ -0,0 +1,269 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Collections
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A collection containing only unique items.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public sealed class IcdHashSet<T> : ICollection<T>
|
||||||
|
{
|
||||||
|
private readonly Dictionary<T, object> m_Dict;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a new, empty hashset.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IcdHashSet<T> NullSet { get { return new IcdHashSet<T>(); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of items contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// The number of items contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
|
||||||
|
/// </returns>
|
||||||
|
public int Count { get { return m_Dict.Count; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// true if the <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only; otherwise, false.
|
||||||
|
/// </returns>
|
||||||
|
public bool IsReadOnly { get { return false; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public IcdHashSet()
|
||||||
|
{
|
||||||
|
m_Dict = new Dictionary<T, object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
public IcdHashSet(IEnumerable<T> items)
|
||||||
|
: this()
|
||||||
|
{
|
||||||
|
if (items == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AddRange(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public IcdHashSet<T> Union(IEnumerable<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> unionSet = new IcdHashSet<T>(this);
|
||||||
|
|
||||||
|
if (set == null)
|
||||||
|
return unionSet;
|
||||||
|
|
||||||
|
unionSet.AddRange(set);
|
||||||
|
|
||||||
|
return unionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public IcdHashSet<T> Subtract(IEnumerable<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> subtractSet = new IcdHashSet<T>(this);
|
||||||
|
|
||||||
|
if (set == null)
|
||||||
|
return subtractSet;
|
||||||
|
|
||||||
|
foreach (T item in set)
|
||||||
|
subtractSet.Remove(item);
|
||||||
|
|
||||||
|
return subtractSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public bool IsSubsetOf(IcdHashSet<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> setToCompare = set ?? NullSet;
|
||||||
|
return this.All(setToCompare.Contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public IcdHashSet<T> Intersection(IcdHashSet<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> intersectionSet = NullSet;
|
||||||
|
|
||||||
|
if (set == null)
|
||||||
|
return intersectionSet;
|
||||||
|
|
||||||
|
foreach (T item in this.Where(set.Contains))
|
||||||
|
intersectionSet.Add(item);
|
||||||
|
|
||||||
|
foreach (T item in set.Where(Contains))
|
||||||
|
intersectionSet.Add(item);
|
||||||
|
|
||||||
|
return intersectionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns items that are not common between both sets.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="set"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public IcdHashSet<T> NonIntersection(IcdHashSet<T> set)
|
||||||
|
{
|
||||||
|
return Subtract(set).Union(set.Subtract(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public bool IsProperSubsetOf(IcdHashSet<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> setToCompare = set ?? NullSet;
|
||||||
|
|
||||||
|
// Is a proper subset if A is a subset of B and A != B
|
||||||
|
return (IsSubsetOf(setToCompare) && !setToCompare.IsSubsetOf(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public bool IsSupersetOf(IcdHashSet<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> setToCompare = set ?? NullSet;
|
||||||
|
return setToCompare.IsSubsetOf(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public bool IsProperSupersetOf(IcdHashSet<T> set)
|
||||||
|
{
|
||||||
|
IcdHashSet<T> setToCompare = set ?? NullSet;
|
||||||
|
|
||||||
|
// B is a proper superset of A if B is a superset of A and A != B
|
||||||
|
return (IsSupersetOf(setToCompare) && !setToCompare.IsSupersetOf(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICollection<T> Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the item to the collection. Returns false if the item already exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Add(T item)
|
||||||
|
{
|
||||||
|
// ReSharper disable CompareNonConstrainedGenericWithNull
|
||||||
|
if (item == null)
|
||||||
|
// ReSharper restore CompareNonConstrainedGenericWithNull
|
||||||
|
throw new ArgumentNullException("item");
|
||||||
|
|
||||||
|
if (m_Dict.ContainsKey(item))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_Dict[item] = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the item to the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
void ICollection<T>.Add(T item)
|
||||||
|
{
|
||||||
|
Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds each of the items in the sequence to the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
public void AddRange(IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
foreach (T item in items)
|
||||||
|
Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
m_Dict.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the IcdHashSet contains the given item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public bool Contains(T item)
|
||||||
|
{
|
||||||
|
return m_Dict.ContainsKey(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies the items of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="array">The one-dimensional <see cref="T:System.Array"/> that is the destination of the items copied from <see cref="T:System.Collections.Generic.ICollection`1"/>. The <see cref="T:System.Array"/> must have zero-based indexing.</param><param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param><exception cref="T:System.ArgumentNullException"><paramref name="array"/> is null.</exception><exception cref="T:System.ArgumentOutOfRangeException"><paramref name="arrayIndex"/> is less than 0.</exception><exception cref="T:System.ArgumentException"><paramref name="array"/> is multidimensional.-or-<paramref name="arrayIndex"/> is equal to or greater than the length of <paramref name="array"/>.-or-The number of items in the source <see cref="T:System.Collections.Generic.ICollection`1"/> is greater than the available space from <paramref name="arrayIndex"/> to the end of the destination <paramref name="array"/>.-or-Type T cannot be cast automatically to the type of the destination <paramref name="array"/>.</exception>
|
||||||
|
public void CopyTo(T[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
m_Dict.Keys.CopyTo(array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
|
||||||
|
/// </returns>
|
||||||
|
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
|
||||||
|
public bool Remove(T item)
|
||||||
|
{
|
||||||
|
return m_Dict.Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Implementation of IEnumerable
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerator that iterates through the collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
|
||||||
|
/// </returns>
|
||||||
|
/// <filterpriority>1</filterpriority>
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
{
|
||||||
|
return m_Dict.Keys.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerator that iterates through a collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
|
||||||
|
/// </returns>
|
||||||
|
/// <filterpriority>2</filterpriority>
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
180
ICD.Common/Utils/Collections/ScrollQueue.cs
Normal file
180
ICD.Common/Utils/Collections/ScrollQueue.cs
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Collections
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ScrollQueue is a queue that never exceeds a predefined length. Old items
|
||||||
|
/// are removed as new items are added.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TContents"></typeparam>
|
||||||
|
public sealed class ScrollQueue<TContents> : IEnumerable<TContents>, ICollection
|
||||||
|
{
|
||||||
|
private readonly LinkedList<TContents> m_Collection;
|
||||||
|
private int m_MaxSize;
|
||||||
|
|
||||||
|
private readonly SafeCriticalSection m_CollectionLock;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets/sets the maximum size of the queue.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public int MaxSize
|
||||||
|
{
|
||||||
|
get { return m_MaxSize; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value == m_MaxSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_MaxSize = value;
|
||||||
|
|
||||||
|
Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of items in the collection.
|
||||||
|
/// </summary>
|
||||||
|
public int Count { get { return m_CollectionLock.Execute(() => m_Collection.Count); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The IsSynchronized Boolean property returns True if the
|
||||||
|
/// collection is designed to be thread safe; otherwise, it returns False.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsSynchronized { get { return true; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The SyncRoot property returns an object, which is used for synchronizing
|
||||||
|
/// the collection. This returns the instance of the object or returns the
|
||||||
|
/// SyncRoot of other collections if the collection contains other collections.
|
||||||
|
/// </summary>
|
||||||
|
public object SyncRoot { get { return this; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="maxSize"></param>
|
||||||
|
public ScrollQueue(int maxSize)
|
||||||
|
{
|
||||||
|
m_CollectionLock = new SafeCriticalSection();
|
||||||
|
m_Collection = new LinkedList<TContents>();
|
||||||
|
MaxSize = maxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Queue Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all items from the queue.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
m_CollectionLock.Execute(() => m_Collection.Clear());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Appends the item to the queue, trims old items that exceed max length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public void Enqueue(TContents item)
|
||||||
|
{
|
||||||
|
m_CollectionLock.Execute(() => m_Collection.AddLast(item));
|
||||||
|
Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the oldest item from the queue.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public TContents Dequeue()
|
||||||
|
{
|
||||||
|
m_CollectionLock.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TContents output = m_Collection.First.Value;
|
||||||
|
m_Collection.RemoveFirst();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_CollectionLock.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the oldest item in the queue.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public TContents Peek()
|
||||||
|
{
|
||||||
|
return m_CollectionLock.Execute(() => m_Collection.First.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Implemented Methods
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<TContents> GetEnumerator()
|
||||||
|
{
|
||||||
|
return m_CollectionLock.Execute(() => m_Collection.ToList().GetEnumerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection.CopyTo(Array myArr, int index)
|
||||||
|
{
|
||||||
|
m_CollectionLock.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (TContents item in m_Collection)
|
||||||
|
{
|
||||||
|
myArr.SetValue(item, index);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_CollectionLock.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes items that fall outside of the max size.
|
||||||
|
/// </summary>
|
||||||
|
private void Trim()
|
||||||
|
{
|
||||||
|
m_CollectionLock.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (Count > MaxSize)
|
||||||
|
m_Collection.RemoveFirst();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_CollectionLock.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
245
ICD.Common/Utils/CrestronUtils.cs
Normal file
245
ICD.Common/Utils/CrestronUtils.cs
Normal file
@@ -0,0 +1,245 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Services;
|
||||||
|
using ICD.Common.Services.Logging;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class CrestronUtils
|
||||||
|
{
|
||||||
|
private const string MODEL_NAME_REGEX = @"^(\S*)";
|
||||||
|
private const string MODEL_VERSION_REGEX = @" [[]v(\S*)";
|
||||||
|
|
||||||
|
private const string RAMFREE_COMMAND = "ramfree";
|
||||||
|
private const string RAMFREE_DIGITS_REGEX = @"^(\d*)";
|
||||||
|
|
||||||
|
private static string s_VersionResult;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the default mac address of the processor.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string DefaultMacAddress
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
const CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET param =
|
||||||
|
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_MAC_ADDRESS;
|
||||||
|
const EthernetAdapterType type = EthernetAdapterType.EthernetLANAdapter;
|
||||||
|
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||||
|
return CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the version text from the console.
|
||||||
|
/// </summary>
|
||||||
|
private static string VersionResult
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(s_VersionResult))
|
||||||
|
{
|
||||||
|
if (!CrestronConsole.SendControlSystemCommand("version", ref s_VersionResult))
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Warning, "{0} - Failed to send console command \"{1}\"",
|
||||||
|
typeof(CrestronUtils).Name, "version");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_VersionResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the model name of the processor.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ModelName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(MODEL_NAME_REGEX);
|
||||||
|
Match match = regex.Match(VersionResult);
|
||||||
|
|
||||||
|
if (match.Success)
|
||||||
|
return match.Groups[1].Value;
|
||||||
|
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Warning, "Unable to get model name from \"{0}\"", VersionResult);
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the processor firmware version.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static Version ModelVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(MODEL_VERSION_REGEX);
|
||||||
|
Match match = regex.Match(VersionResult);
|
||||||
|
|
||||||
|
if (match.Success)
|
||||||
|
return new Version(match.Groups[1].Value);
|
||||||
|
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Warning, "Unable to get model version from \"{0}\"", VersionResult);
|
||||||
|
return new Version(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ram usage in the range 0 - 1.
|
||||||
|
/// </summary>
|
||||||
|
public static float RamUsagePercent
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string ramFree = GetRamFree();
|
||||||
|
string digits = Regex.Matches(ramFree, RAMFREE_DIGITS_REGEX, RegexOptions.Multiline)[0].Groups[1].Value;
|
||||||
|
return float.Parse(digits) / 100.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of bytes of physical memory.
|
||||||
|
/// </summary>
|
||||||
|
public static ulong RamTotalBytes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string ramFree = GetRamFree();
|
||||||
|
string digits = Regex.Matches(ramFree, RAMFREE_DIGITS_REGEX, RegexOptions.Multiline)[1].Groups[1].Value;
|
||||||
|
return ulong.Parse(digits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of bytes of physical memory being used by the control system.
|
||||||
|
/// </summary>
|
||||||
|
public static ulong RamUsedBytes
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string ramFree = GetRamFree();
|
||||||
|
string digits = Regex.Matches(ramFree, RAMFREE_DIGITS_REGEX, RegexOptions.Multiline)[2].Groups[1].Value;
|
||||||
|
return ulong.Parse(digits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of bytes of physical memory not being used by the control system.
|
||||||
|
/// </summary>
|
||||||
|
public static ulong RamBytesFree
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string ramFree = GetRamFree();
|
||||||
|
string digits = Regex.Matches(ramFree, RAMFREE_DIGITS_REGEX, RegexOptions.Multiline)[3].Groups[1].Value;
|
||||||
|
return ulong.Parse(digits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total number of bytes that can be reclaimed.
|
||||||
|
/// </summary>
|
||||||
|
public static ulong RamBytesReclaimable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string ramFree = GetRamFree();
|
||||||
|
string digits = Regex.Matches(ramFree, RAMFREE_DIGITS_REGEX, RegexOptions.Multiline)[4].Groups[1].Value;
|
||||||
|
return ulong.Parse(digits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restarts this program.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void RestartProgram()
|
||||||
|
{
|
||||||
|
string consoleResult = string.Empty;
|
||||||
|
string command = string.Format("progreset -p:{0:D2}", ProgramUtils.ProgramNumber);
|
||||||
|
CrestronConsole.SendControlSystemCommand(command, ref consoleResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reboots the processor.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Reboot()
|
||||||
|
{
|
||||||
|
string consoleResult = string.Empty;
|
||||||
|
CrestronConsole.SendControlSystemCommand("reboot", ref consoleResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs CrestronInvoke but catches any unhandled exceptions to prevent the program from terminating.
|
||||||
|
/// http://www.crestronlabs.com/showthread.php?12205-Exception-in-CrestronInvoke-thread-crashes-the-program
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static object SafeInvoke(Action callback)
|
||||||
|
{
|
||||||
|
return SafeInvoke<object>(unused => callback(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs CrestronInvoke but catches any unhandled exceptions to prevent the program from terminating.
|
||||||
|
/// http://www.crestronlabs.com/showthread.php?12205-Exception-in-CrestronInvoke-thread-crashes-the-program
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="param"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static object SafeInvoke<T>(Action<T> callback, T param)
|
||||||
|
{
|
||||||
|
return CrestronInvoke.BeginInvoke(unused =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
callback(param);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Error, e, e.Message);
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the result from the ramfree console command.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string GetRamFree()
|
||||||
|
{
|
||||||
|
string ramfree = null;
|
||||||
|
if (!CrestronConsole.SendControlSystemCommand(RAMFREE_COMMAND, ref ramfree))
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Warning, "{0} - Failed to send console command \"{1}\"",
|
||||||
|
typeof(CrestronUtils).Name, RAMFREE_COMMAND);
|
||||||
|
}
|
||||||
|
return ramfree;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
400
ICD.Common/Utils/EnumUtils.cs
Normal file
400
ICD.Common/Utils/EnumUtils.cs
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using System.Globalization;
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
|
#else
|
||||||
|
using System.Reflection;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.Utils.Collections;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class EnumUtils
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<Type, IcdHashSet<object>> s_EnumValuesCache =
|
||||||
|
new Dictionary<Type, IcdHashSet<object>>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the given type is an enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static bool IsEnum(Type type)
|
||||||
|
{
|
||||||
|
return type == typeof(Enum) || type
|
||||||
|
#if !SIMPLSHARP
|
||||||
|
.GetTypeInfo()
|
||||||
|
#endif
|
||||||
|
.IsEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the given type is an enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static bool IsEnum<T>()
|
||||||
|
{
|
||||||
|
return IsEnum(typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Values
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the underlying value of the enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object GetUnderlyingValue<T>(T value)
|
||||||
|
{
|
||||||
|
if (!IsEnum(typeof(T)))
|
||||||
|
throw new InvalidOperationException(string.Format("{0} is not an enum", value.GetType().Name));
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return Convert.ChangeType(value, ToEnum(value).GetTypeCode(), CultureInfo.InvariantCulture);
|
||||||
|
#else
|
||||||
|
return Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the values from an enumeration.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetValues<T>()
|
||||||
|
{
|
||||||
|
return GetValues(typeof(T)).Cast<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the values from an enumeration.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<object> GetValues(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
// Reflection is slow and this method is called a lot, so we cache the results.
|
||||||
|
if (!s_EnumValuesCache.ContainsKey(type))
|
||||||
|
s_EnumValuesCache[type] = GetValuesUncached(type).ToHashSet();
|
||||||
|
|
||||||
|
return s_EnumValuesCache[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the values from an enumeration without performing any caching. This is slow because of reflection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static IEnumerable<object> GetValuesUncached(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
if (!IsEnum(type))
|
||||||
|
throw new InvalidOperationException(string.Format("{0} is not an enum", type.Name));
|
||||||
|
|
||||||
|
return type
|
||||||
|
#if SIMPLSHARP
|
||||||
|
.GetCType()
|
||||||
|
#else
|
||||||
|
.GetTypeInfo()
|
||||||
|
#endif
|
||||||
|
.GetFields(BindingFlags.Static | BindingFlags.Public)
|
||||||
|
.Select(x => x.GetValue(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the 0 value for the given enum type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T GetNoneValue<T>()
|
||||||
|
{
|
||||||
|
if (!IsEnum(typeof(T)))
|
||||||
|
throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return (T)(object)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the values from an enumeration except the 0 value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetValuesExceptNone<T>()
|
||||||
|
{
|
||||||
|
if (!IsEnum(typeof(T)))
|
||||||
|
throw new InvalidOperationException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return GetValuesExceptNone(typeof(T)).Cast<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the values from an enumeration except the 0 value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<object> GetValuesExceptNone(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
if (!IsEnum(type))
|
||||||
|
throw new InvalidOperationException(string.Format("{0} is not an enum", type.Name));
|
||||||
|
|
||||||
|
return GetValues(type).Where(v => (int)v != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Flags
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the given enum type has the Flags attribute set.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsFlagsEnum<T>()
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return IsFlagsEnum(typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the given enum type has the Flags attribute set.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool IsFlagsEnum(Type type)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
if (!IsEnum(type))
|
||||||
|
throw new InvalidOperationException(string.Format("{0} is not an enum", type.Name));
|
||||||
|
|
||||||
|
return type
|
||||||
|
#if !SIMPLSHARP
|
||||||
|
.GetTypeInfo()
|
||||||
|
#endif
|
||||||
|
.IsDefined(typeof(FlagsAttribute), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the overlapping values of the given enum flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="values"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T GetFlagsIntersection<T>(params T[] values)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
if (values.Length == 0)
|
||||||
|
return GetNoneValue<T>();
|
||||||
|
|
||||||
|
int output = (int)(object)values.First();
|
||||||
|
foreach (T item in values.Skip(1))
|
||||||
|
output &= (int)(object)item;
|
||||||
|
|
||||||
|
return (T)Enum.ToObject(typeof(T), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all of the set flags on the given enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetFlags<T>(T value)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return GetValues<T>().Where(e => HasFlag(value, e));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all of the set flags on the given enum except 0.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetFlagsExceptNone<T>(T value)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
T none = GetNoneValue<T>();
|
||||||
|
return GetFlags(value).Except(none);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an enum value of the given type with every flag set.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T GetFlagsAllValue<T>()
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
int output = GetValues<T>().Aggregate(0, (current, value) => current | (int)(object)value);
|
||||||
|
return (T)Enum.ToObject(typeof(T), output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the enum contains the given flag.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="flag"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool HasFlag<T>(T value, T flag)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return ToEnum(value).HasFlag(ToEnum(flag));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the enum contains all of the given flags.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="flags"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool HasFlags<T>(T value, T flags)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return ToEnum(value).HasFlags(ToEnum(flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if only a single flag is set on the given enum value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool HasSingleFlag<T>(T value)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return (int)(object)value != (int)(object)GetNoneValue<T>() && !HasMultipleFlags(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the enum has more than 1 flag set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool HasMultipleFlags<T>(T value)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return HasMultipleFlags((int)(object)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the enum has more than 1 flag set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static bool HasMultipleFlags(int value)
|
||||||
|
{
|
||||||
|
return ((value & (value - 1)) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Conversion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shorthand for parsing string to enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="ignoreCase"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T Parse<T>(string data, bool ignoreCase)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (T)Enum.Parse(typeof(T), data, ignoreCase);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new FormatException(
|
||||||
|
string.Format("Failed to parse {0} as {1}", StringUtils.ToRepresentation(data), typeof(T).Name), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shorthand for parsing a string to enum. Returns false if the parse failed.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <param name="ignoreCase"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryParse<T>(string data, bool ignoreCase, out T result)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
result = default(T);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = Parse<T>(data, ignoreCase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the given enum value to an Enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Enum ToEnum<T>(T value)
|
||||||
|
{
|
||||||
|
if (!IsEnum<T>())
|
||||||
|
throw new ArgumentException(string.Format("{0} is not an enum", typeof(T).Name));
|
||||||
|
|
||||||
|
return ToEnum((object)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the given enum value to an Enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Enum ToEnum(object value)
|
||||||
|
{
|
||||||
|
return (Enum)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
47
ICD.Common/Utils/Extensions/CollectionExtensions.cs
Normal file
47
ICD.Common/Utils/Extensions/CollectionExtensions.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for working with ICollections.
|
||||||
|
/// </summary>
|
||||||
|
public static class CollectionExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Removes items matching the predicate.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="predicate"></param>
|
||||||
|
public static void RemoveAll<T>(this ICollection<T> extends, Func<T, bool> predicate)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (predicate == null)
|
||||||
|
throw new ArgumentNullException("predicate");
|
||||||
|
|
||||||
|
extends.RemoveAll(extends.Where(predicate).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all of the items from the other collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
public static void RemoveAll<T>(this ICollection<T> extends, IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (other == null)
|
||||||
|
throw new ArgumentNullException("other");
|
||||||
|
|
||||||
|
foreach (T item in other)
|
||||||
|
extends.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
ICD.Common/Utils/Extensions/DateTimeExtensions.cs
Normal file
24
ICD.Common/Utils/Extensions/DateTimeExtensions.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for DateTime.
|
||||||
|
/// </summary>
|
||||||
|
public static class DateTimeExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a string representation of the DateTime with millisecond precision.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToLongTimeStringWithMilliseconds(this DateTime extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
// Todo - Better handle different cultures
|
||||||
|
return extends.ToString("HH:mm:ss:fff");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
340
ICD.Common/Utils/Extensions/DictionaryExtensions.cs
Normal file
340
ICD.Common/Utils/Extensions/DictionaryExtensions.cs
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class DictionaryExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the first key with a value matching the given value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns>False if value is not found in the dictionary.</returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool RemoveValue<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TKey key = extends.GetKey(value);
|
||||||
|
return extends.Remove(key);
|
||||||
|
}
|
||||||
|
catch (ArgumentOutOfRangeException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all keys with the given value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void RemoveAllValues<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
foreach (TKey key in extends.GetKeys(value).ToArray())
|
||||||
|
extends.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the key is present in the dictionary return the value, otherwise returns default value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static TValue GetDefault<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||||
|
if (key == null)
|
||||||
|
throw new ArgumentNullException("key");
|
||||||
|
|
||||||
|
return extends.GetDefault(key, default(TValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the key is present in the dictionary return the value, otherwise return the default value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="defaultValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static TValue GetDefault<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key, TValue defaultValue)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||||
|
if (key == null)
|
||||||
|
throw new ArgumentNullException("key");
|
||||||
|
|
||||||
|
return extends.ContainsKey(key) ? extends[key] : defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If the key is present in the dictionary return the value, otherwise add the default value to the dictionary and return it.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="key"></param>
|
||||||
|
/// <param name="defaultValue"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static TValue GetOrAddDefault<TKey, TValue>(this IDictionary<TKey, TValue> extends, TKey key,
|
||||||
|
TValue defaultValue)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||||
|
if (key == null)
|
||||||
|
throw new ArgumentNullException("key");
|
||||||
|
|
||||||
|
extends[key] = extends.GetDefault(key, defaultValue);
|
||||||
|
return extends[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a key for the given value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">The value does not exist in the dictionary.</exception>
|
||||||
|
[PublicAPI]
|
||||||
|
public static TKey GetKey<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return extends.GetKeys(value).First();
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException)
|
||||||
|
{
|
||||||
|
string message = string.Format("Unable to find Key with Value matching {0}", value);
|
||||||
|
throw new KeyNotFoundException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the keys that match the given value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<TKey> GetKeys<TKey, TValue>(this IDictionary<TKey, TValue> extends, TValue value)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.Where(kvp => EqualityComparer<TValue>.Default.Equals(kvp.Value, value))
|
||||||
|
.Select(kvp => kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Updates the dictionary with items from the other dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Update<TKey, TValue>(this IDictionary<TKey, TValue> extends, IDictionary<TKey, TValue> other)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (other == null)
|
||||||
|
throw new ArgumentNullException("other");
|
||||||
|
|
||||||
|
foreach (KeyValuePair<TKey, TValue> pair in other)
|
||||||
|
extends[pair.Key] = pair.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the sequence of items to the dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <param name="getKey"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> extends, IEnumerable<TValue> items,
|
||||||
|
Func<TValue, TKey> getKey)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
if (getKey == null)
|
||||||
|
throw new ArgumentNullException("getKey");
|
||||||
|
|
||||||
|
foreach (TValue item in items)
|
||||||
|
extends.Add(getKey(item), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the sequence of items to the dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <param name="getValue"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> extends, IEnumerable<TKey> items,
|
||||||
|
Func<TKey, TValue> getValue)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
if (getValue == null)
|
||||||
|
throw new ArgumentNullException("getValue");
|
||||||
|
|
||||||
|
foreach (TKey item in items)
|
||||||
|
extends.Add(item, getValue(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the sequence of items to the dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void AddRange<TKey, TValue>(this Dictionary<TKey, TValue> extends,
|
||||||
|
IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
foreach (KeyValuePair<TKey, TValue> item in items)
|
||||||
|
extends.Add(item.Key, item.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares the keys and values of the dictionary to determine equality.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool DictionaryEqual<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||||
|
IDictionary<TKey, TValue> other)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.DictionaryEqual(other, EqualityComparer<TValue>.Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares the keys and values of the dictionary to determine equality.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <param name="valueComparer"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool DictionaryEqual<TKey, TValue>(this IDictionary<TKey, TValue> extends,
|
||||||
|
IDictionary<TKey, TValue> other,
|
||||||
|
IEqualityComparer<TValue> valueComparer)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends == other)
|
||||||
|
return true;
|
||||||
|
if (other == null)
|
||||||
|
return false;
|
||||||
|
if (extends.Count != other.Count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
foreach (KeyValuePair<TKey, TValue> kvp in extends)
|
||||||
|
{
|
||||||
|
TValue secondValue;
|
||||||
|
if (!other.TryGetValue(kvp.Key, out secondValue))
|
||||||
|
return false;
|
||||||
|
if (!valueComparer.Equals(kvp.Value, secondValue))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the KeyValuePairs in key order.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<KeyValuePair<TKey, TValue>> OrderByKey<TKey, TValue>(
|
||||||
|
this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.OrderBy(kvp => kvp.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a sequence of values ordered by the dictionary keys.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<TValue> OrderValuesByKey<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
71
ICD.Common/Utils/Extensions/EnumExtensions.cs
Normal file
71
ICD.Common/Utils/Extensions/EnumExtensions.cs
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class EnumExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Check to see if a flags enumeration has a specific flag set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends">Flags enumeration to check</param>
|
||||||
|
/// <param name="value">Flag to check for</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool HasFlag(this Enum extends, Enum value)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException("value");
|
||||||
|
|
||||||
|
if (EnumUtils.HasMultipleFlags(value))
|
||||||
|
throw new ArgumentException("Value has multiple flags", "value");
|
||||||
|
|
||||||
|
return extends.HasFlags(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check to see if a flags enumeration has all of the given flags set.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool HasFlags(this Enum extends, Enum value)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (value == null)
|
||||||
|
throw new ArgumentNullException("value");
|
||||||
|
|
||||||
|
// Not as good as the .NET 4 version of this function, but should be good enough
|
||||||
|
if (extends.GetType() != value.GetType())
|
||||||
|
{
|
||||||
|
string message = string.Format("Enumeration type mismatch. The flag is of type '{0}', was expecting '{1}'.",
|
||||||
|
value.GetType(), extends.GetType());
|
||||||
|
throw new ArgumentException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong num = Convert.ToUInt64(value);
|
||||||
|
return (Convert.ToUInt64(extends) & num) == num;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Casts the enum to the given type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static T Cast<T>(this Enum extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return (T)Enum.ToObject(typeof(T), extends);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
717
ICD.Common/Utils/Extensions/EnumerableExtensions.cs
Normal file
717
ICD.Common/Utils/Extensions/EnumerableExtensions.cs
Normal file
@@ -0,0 +1,717 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils.Collections;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class EnumerableExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the first item in the sequence. Returns the provided default item if there
|
||||||
|
/// are no elements in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="defaultItem"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T FirstOrDefault<T>(this IEnumerable<T> extends, T defaultItem)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.FirstOrDefault(i => true, defaultItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the first element in the sequence matching the predicate. Returns the provided
|
||||||
|
/// default item if there are no elements matching the predicate in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="predicate"></param>
|
||||||
|
/// <param name="defaultItem"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T FirstOrDefault<T>(this IEnumerable<T> extends, Func<T, bool> predicate, T defaultItem)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (predicate == null)
|
||||||
|
throw new ArgumentNullException("predicate");
|
||||||
|
|
||||||
|
foreach (T item in extends.Where(predicate))
|
||||||
|
return item;
|
||||||
|
return defaultItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if there is at least 1 item in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="item">Outputs the first item in the sequence.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryFirstOrDefault<T>(this IEnumerable<T> extends, out T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.TryFirstOrDefault(i => true, out item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if there is at least 1 item in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="predicate"></param>
|
||||||
|
/// <param name="item">Outputs the first item in the sequence.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryFirstOrDefault<T>(this IEnumerable<T> extends, Func<T, bool> predicate, out T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (predicate == null)
|
||||||
|
throw new ArgumentNullException("predicate");
|
||||||
|
|
||||||
|
item = default(T);
|
||||||
|
|
||||||
|
using (IEnumerator<T> iterator = extends.GetEnumerator())
|
||||||
|
{
|
||||||
|
while (iterator.MoveNext())
|
||||||
|
{
|
||||||
|
if (!predicate(iterator.Current))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
item = iterator.Current;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the true if an element with the given index is in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool TryElementAt<T>(this IEnumerable<T> extends, int index, out T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
item = default(T);
|
||||||
|
|
||||||
|
if (index < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
T[] itemArray = extends as T[] ?? extends.ToArray();
|
||||||
|
if (index >= itemArray.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
item = itemArray[index];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two sequences for identical values, ignoring order.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ScrambledEquals<T>(this IEnumerable<T> extends, IEnumerable<T> other)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("other");
|
||||||
|
|
||||||
|
return extends.ScrambledEquals(other, EqualityComparer<T>.Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compares two sequences for identical values, ignoring order.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <param name="comparer"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool ScrambledEquals<T>(this IEnumerable<T> extends, IEnumerable<T> other, IEqualityComparer<T> comparer)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("other");
|
||||||
|
|
||||||
|
if (comparer == null)
|
||||||
|
throw new ArgumentNullException("comparer");
|
||||||
|
|
||||||
|
Dictionary<T, int> count = new Dictionary<T, int>(comparer);
|
||||||
|
|
||||||
|
foreach (T item in extends)
|
||||||
|
{
|
||||||
|
if (count.ContainsKey(item))
|
||||||
|
count[item]++;
|
||||||
|
else
|
||||||
|
count.Add(item, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (T item in other)
|
||||||
|
{
|
||||||
|
if (count.ContainsKey(item))
|
||||||
|
count[item]--;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count.Values.All(c => c == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the index that matches the predicate.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="match"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int FindIndex<T>(this IEnumerable<T> extends, Predicate<T> match)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (match == null)
|
||||||
|
throw new ArgumentNullException("match");
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
foreach (T item in extends)
|
||||||
|
{
|
||||||
|
if (match(item))
|
||||||
|
return index;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows for selection of multiple results for each item in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TSource"></typeparam>
|
||||||
|
/// <typeparam name="TResult"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="selectors"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<TResult> SelectMulti<TSource, TResult>(this IEnumerable<TSource> extends,
|
||||||
|
params Func<TSource, TResult>[] selectors)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (selectors == null)
|
||||||
|
throw new ArgumentNullException("selectors");
|
||||||
|
|
||||||
|
return extends.SelectMany(source => selectors, (source, selector) => selector(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enumerates each item in the sequence.
|
||||||
|
/// Useful for processing a LINQ query without creating a new collection.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Execute<T>(this IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
extends.ForEach(item => { });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs the action for each item in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void ForEach<T>(this IEnumerable<T> extends, Action<T> action)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (action == null)
|
||||||
|
throw new ArgumentNullException("action");
|
||||||
|
|
||||||
|
extends.ForEach((item, index) => action(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs the action for each item in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="action"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void ForEach<T>(this IEnumerable<T> extends, Action<T, int> action)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (action == null)
|
||||||
|
throw new ArgumentNullException("action");
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
foreach (T item in extends)
|
||||||
|
action(item, index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
/// <summary>
|
||||||
|
/// Prepends the item to the start of the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> extends, T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.PrependMany(new[] {item});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Prepends the items to the start of the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<T> PrependMany<T>(this IEnumerable<T> extends, params T[] items)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
foreach (T item in items)
|
||||||
|
yield return item;
|
||||||
|
foreach (T each in extends)
|
||||||
|
yield return each;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
/// <summary>
|
||||||
|
/// Appends the item to the end of the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> Append<T>(this IEnumerable<T> extends, T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.AppendMany(new[] {item});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Appends the items to the end of the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<T> AppendMany<T>(this IEnumerable<T> extends, params T[] items)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
foreach (T each in extends)
|
||||||
|
yield return each;
|
||||||
|
foreach (T item in items)
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default ordering for the items in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> Order<T>(this IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.OrderBy(i => i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns every item in the sequence except the given item.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> Except<T>(this IEnumerable<T> extends, T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.Except(new[] {item});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the sequence as a IcdHashSet.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IcdHashSet<T> ToHashSet<T>(this IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return new IcdHashSet<T>(extends);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the sequence as an index:value dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static Dictionary<int, T> ToDictionary<T>(this IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
Dictionary<int, T> output = new Dictionary<int, T>();
|
||||||
|
extends.ForEach((item, index) => output.Add(index, item));
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the sequence as an index:value dictionary.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static Dictionary<uint, T> ToDictionaryUInt<T>(this IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
Dictionary<uint, T> output = new Dictionary<uint, T>();
|
||||||
|
extends.ForEach((item, index) => output.Add((uint)index, item));
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Turns an enumerable of KeyValuePairs back into a dictionary
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TKey"></typeparam>
|
||||||
|
/// <typeparam name="TValue"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.ToDictionary(x => x.Key, x => x.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns other if the list is empty.
|
||||||
|
/// Returns other if the list is non-empty and there are two different elements.
|
||||||
|
/// Returns the element of the list if it is non-empty and all elements are the same.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static T Unanimous<T>(this IEnumerable<T> extends, T other)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
T[] array = extends as T[] ?? extends.ToArray();
|
||||||
|
return array.Unanimous() ? array.First() : other;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns false if the list is empty.
|
||||||
|
/// Returns false if the list is non-empty and there are two different elements.
|
||||||
|
/// Returns true if the list is non-empty and all elements are the same.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool Unanimous<T>(this IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
T[] array = extends as T[] ?? extends.ToArray();
|
||||||
|
|
||||||
|
if (array.Length == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
T val = array.First();
|
||||||
|
return array.All(x => EqualityComparer<T>.Default.Equals(x, val));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Partitions a sequence into sequences of the given length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="partitionSize"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> extends, int partitionSize)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
using (IEnumerator<T> enumerator = extends.GetEnumerator())
|
||||||
|
{
|
||||||
|
while (enumerator.MoveNext())
|
||||||
|
yield return YieldBatchElements(enumerator, partitionSize - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<T> YieldBatchElements<T>(IEnumerator<T> source, int partitionSize)
|
||||||
|
{
|
||||||
|
if (source == null)
|
||||||
|
throw new ArgumentNullException("source");
|
||||||
|
|
||||||
|
// Important to enumerate through partitionSize items before returning
|
||||||
|
// Otherwise enumerable.Partition(3).Skip(1) will do unwanted things.
|
||||||
|
List<T> output = new List<T> {source.Current};
|
||||||
|
|
||||||
|
for (int i = 0; i < partitionSize && source.MoveNext(); i++)
|
||||||
|
output.Add(source.Current);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the minimal element of the given sequence, based on
|
||||||
|
/// the given projection.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If more than one element has the minimal projected value, the first
|
||||||
|
/// one encountered will be returned. This overload uses the default comparer
|
||||||
|
/// for the projected type. This operator uses immediate execution, but
|
||||||
|
/// only buffers a single result (the current minimal element).
|
||||||
|
/// </remarks>
|
||||||
|
/// <typeparam name="TSource">Type of the source sequence</typeparam>
|
||||||
|
/// <typeparam name="TKey">Type of the projected element</typeparam>
|
||||||
|
/// <param name="source">Source sequence</param>
|
||||||
|
/// <param name="selector">Selector to use to pick the results to compare</param>
|
||||||
|
/// <returns>The minimal element, according to the projection.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null</exception>
|
||||||
|
/// <exception cref="InvalidOperationException"><paramref name="source"/> is empty</exception>
|
||||||
|
[PublicAPI]
|
||||||
|
public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source,
|
||||||
|
Func<TSource, TKey> selector)
|
||||||
|
{
|
||||||
|
if (source == null)
|
||||||
|
throw new ArgumentNullException("source");
|
||||||
|
|
||||||
|
if (selector == null)
|
||||||
|
throw new ArgumentNullException("selector");
|
||||||
|
|
||||||
|
return source.MinBy(selector, Comparer<TKey>.Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the minimal element of the given sequence, based on
|
||||||
|
/// the given projection and the specified comparer for projected values.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// If more than one element has the minimal projected value, the first
|
||||||
|
/// one encountered will be returned. This operator uses immediate execution, but
|
||||||
|
/// only buffers a single result (the current minimal element).
|
||||||
|
/// </remarks>
|
||||||
|
/// <typeparam name="TSource">Type of the source sequence</typeparam>
|
||||||
|
/// <typeparam name="TKey">Type of the projected element</typeparam>
|
||||||
|
/// <param name="source">Source sequence</param>
|
||||||
|
/// <param name="selector">Selector to use to pick the results to compare</param>
|
||||||
|
/// <param name="comparer">Comparer to use to compare projected values</param>
|
||||||
|
/// <returns>The minimal element, according to the projection.</returns>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="source"/>, <paramref name="selector"/>
|
||||||
|
/// or <paramref name="comparer"/> is null</exception>
|
||||||
|
/// <exception cref="InvalidOperationException"><paramref name="source"/> is empty</exception>
|
||||||
|
[PublicAPI]
|
||||||
|
public static TSource MinBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> selector,
|
||||||
|
IComparer<TKey> comparer)
|
||||||
|
{
|
||||||
|
if (source == null)
|
||||||
|
throw new ArgumentNullException("source");
|
||||||
|
|
||||||
|
if (selector == null)
|
||||||
|
throw new ArgumentNullException("selector");
|
||||||
|
|
||||||
|
if (comparer == null)
|
||||||
|
throw new ArgumentNullException("comparer");
|
||||||
|
|
||||||
|
using (IEnumerator<TSource> sourceIterator = source.GetEnumerator())
|
||||||
|
{
|
||||||
|
if (!sourceIterator.MoveNext())
|
||||||
|
throw new InvalidOperationException("Sequence contains no elements");
|
||||||
|
TSource min = sourceIterator.Current;
|
||||||
|
TKey minKey = selector(min);
|
||||||
|
while (sourceIterator.MoveNext())
|
||||||
|
{
|
||||||
|
TSource candidate = sourceIterator.Current;
|
||||||
|
TKey candidateProjected = selector(candidate);
|
||||||
|
if (comparer.Compare(candidateProjected, minKey) >= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
min = candidate;
|
||||||
|
minKey = candidateProjected;
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes any null elements from an enumerable of nullable value types
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<T> ExceptNulls<T>(this IEnumerable<T?> extends)
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.Where(e => e.HasValue).Select(e => e.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the sum of a sequence of byte values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static byte Sum(this IEnumerable<byte> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return (byte)extends.Select(i => (int)i).Sum();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Skips duplicate, consecutive items.
|
||||||
|
/// E.g.
|
||||||
|
/// [1, 2, 2, 3, 1, 1]
|
||||||
|
/// Becomes
|
||||||
|
/// [1, 2, 3, 1]
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<T> Consolidate<T>(IEnumerable<T> extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return Consolidate(extends, Comparer<T>.Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Skips duplicate, consecutive items.
|
||||||
|
/// E.g.
|
||||||
|
/// [1, 2, 2, 3, 1, 1]
|
||||||
|
/// Becomes
|
||||||
|
/// [1, 2, 3, 1]
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="comparer"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<T> Consolidate<T>(IEnumerable<T> extends, IComparer<T> comparer)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (comparer == null)
|
||||||
|
throw new ArgumentNullException("comparer");
|
||||||
|
|
||||||
|
bool first = true;
|
||||||
|
T last = default(T);
|
||||||
|
|
||||||
|
foreach (T item in extends)
|
||||||
|
{
|
||||||
|
if (!first && comparer.Compare(last, item) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
first = false;
|
||||||
|
last = item;
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if all items in the sequence match the predicate.
|
||||||
|
/// Returns false if the sequence is empty.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="predicate"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool AnyAndAll<T>(this IEnumerable<T> extends, Func<T, bool> predicate)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (predicate == null)
|
||||||
|
throw new ArgumentNullException("predicate");
|
||||||
|
|
||||||
|
bool any = false;
|
||||||
|
foreach (T item in extends)
|
||||||
|
{
|
||||||
|
any = true;
|
||||||
|
if (!predicate(item))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return any;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
35
ICD.Common/Utils/Extensions/EventHandlerExtensions.cs
Normal file
35
ICD.Common/Utils/Extensions/EventHandlerExtensions.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for EventHandlers.
|
||||||
|
/// </summary>
|
||||||
|
public static class EventHandlerExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Raises the event safely. Simply skips if the handler is null.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
public static void Raise(this EventHandler extends, object sender)
|
||||||
|
{
|
||||||
|
if (extends != null)
|
||||||
|
extends(sender, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises the event safely. Simply skips if the handler is null.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
public static void Raise<T>(this EventHandler<T> extends, object sender, T args)
|
||||||
|
where T : EventArgs
|
||||||
|
{
|
||||||
|
if (extends != null)
|
||||||
|
extends(sender, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
87
ICD.Common/Utils/Extensions/HashSetExtensions.cs
Normal file
87
ICD.Common/Utils/Extensions/HashSetExtensions.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#if STANDARD
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ICD.NetStandard.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class HashSetExtensions
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
public static HashSet<T> Subtract<T>(this HashSet<T> extends, IEnumerable<T> set)
|
||||||
|
{
|
||||||
|
HashSet<T> subtractSet = new HashSet<T>(extends);
|
||||||
|
|
||||||
|
if (set == null)
|
||||||
|
return subtractSet;
|
||||||
|
|
||||||
|
foreach (T item in set)
|
||||||
|
subtractSet.Remove(item);
|
||||||
|
|
||||||
|
return subtractSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool IsSubsetOf<T>(this HashSet<T> extends, HashSet<T> set)
|
||||||
|
{
|
||||||
|
HashSet<T> setToCompare = set ?? new HashSet<T>();
|
||||||
|
return extends.All(setToCompare.Contains);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static HashSet<T> Intersection<T>(this HashSet<T> extends, HashSet<T> set)
|
||||||
|
{
|
||||||
|
HashSet<T> intersectionSet = new HashSet<T>();
|
||||||
|
|
||||||
|
if (set == null)
|
||||||
|
return intersectionSet;
|
||||||
|
|
||||||
|
foreach (T item in extends.Where(set.Contains))
|
||||||
|
intersectionSet.Add(item);
|
||||||
|
|
||||||
|
foreach (T item in set.Where(extends.Contains))
|
||||||
|
intersectionSet.Add(item);
|
||||||
|
|
||||||
|
return intersectionSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns items that are not common between both sets.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="set"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static HashSet<T> NonIntersection<T>(this HashSet<T> extends, HashSet<T> set)
|
||||||
|
{
|
||||||
|
return new HashSet<T>(extends.Subtract(set).Union(set.Subtract(extends)));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool IsProperSubsetOf<T>(this HashSet<T> extends, HashSet<T> set)
|
||||||
|
{
|
||||||
|
HashSet<T> setToCompare = set ?? new HashSet<T>();
|
||||||
|
|
||||||
|
// Is a proper subset if A is a subset of B and A != B
|
||||||
|
return (extends.IsSubsetOf(setToCompare) && !setToCompare.IsSubsetOf(extends));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool IsSupersetOf<T>(this HashSet<T> extends, HashSet<T> set)
|
||||||
|
{
|
||||||
|
HashSet<T> setToCompare = set ?? new HashSet<T>();
|
||||||
|
return setToCompare.IsSubsetOf(extends);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool IsProperSupersetOf<T>(this HashSet<T> extends, HashSet<T> set)
|
||||||
|
{
|
||||||
|
HashSet<T> setToCompare = set ?? new HashSet<T>();
|
||||||
|
|
||||||
|
// B is a proper superset of A if B is a superset of A and A != B
|
||||||
|
return (extends.IsSupersetOf(setToCompare) && !setToCompare.IsSupersetOf(extends));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
107
ICD.Common/Utils/Extensions/JsonExtensions.cs
Normal file
107
ICD.Common/Utils/Extensions/JsonExtensions.cs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for working with JSON.
|
||||||
|
/// </summary>
|
||||||
|
public static class JsonExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the object value.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="serializer"></param>
|
||||||
|
/// <param name="converter"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void WriteObject(this JsonWriter extends, object value, JsonSerializer serializer,
|
||||||
|
JsonConverter converter)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (serializer == null)
|
||||||
|
throw new ArgumentNullException("serializer");
|
||||||
|
|
||||||
|
if (converter == null)
|
||||||
|
throw new ArgumentNullException("converter");
|
||||||
|
|
||||||
|
JObject jObject = JObject.FromObject(value, serializer);
|
||||||
|
jObject.WriteTo(extends, converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current value as an integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static int GetValueAsInt(this JsonReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends.TokenType == JsonToken.Integer)
|
||||||
|
return (int)(long)extends.Value;
|
||||||
|
|
||||||
|
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value, JsonToken.Integer);
|
||||||
|
throw new InvalidCastException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current value as a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string GetValueAsString(this JsonReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends.TokenType == JsonToken.String || extends.TokenType == JsonToken.Null)
|
||||||
|
return extends.Value as string;
|
||||||
|
|
||||||
|
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value, JsonToken.String);
|
||||||
|
throw new InvalidCastException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current value as a bool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool GetValueAsBool(this JsonReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends.TokenType == JsonToken.Boolean)
|
||||||
|
return (bool)extends.Value;
|
||||||
|
|
||||||
|
string message = string.Format("Token {0} {1} is not {2}", extends.TokenType, extends.Value, JsonToken.Boolean);
|
||||||
|
throw new InvalidCastException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the current value as an enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static T GetValueAsEnum<T>(this JsonReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (extends.TokenType == JsonToken.String)
|
||||||
|
return EnumUtils.Parse<T>(extends.GetValueAsString(), true);
|
||||||
|
return (T)(object)extends.GetValueAsInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
ICD.Common/Utils/Extensions/QueueExtensions.cs
Normal file
47
ICD.Common/Utils/Extensions/QueueExtensions.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class QueueExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enqueues each item in the sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
public static void EnqueueRange<T>(this Queue<T> extends, IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
foreach (T item in items)
|
||||||
|
extends.Enqueue(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dequeues the next item in the queue. Returns false if the queue is empty.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Dequeue<T>(this Queue<T> extends, out T item)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
item = default(T);
|
||||||
|
|
||||||
|
if (extends.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
item = extends.Dequeue();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
ICD.Common/Utils/Extensions/ReflectionExtensions.cs
Normal file
32
ICD.Common/Utils/Extensions/ReflectionExtensions.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Extension methods for use with reflection objects.
|
||||||
|
/// </summary>
|
||||||
|
public static class ReflectionExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the custom attributes attached to the member.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="inherits"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo extends, bool inherits)
|
||||||
|
where T : Attribute
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.GetCustomAttributes(typeof(T), inherits).Cast<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
36
ICD.Common/Utils/Extensions/StringBuilderExtensions.cs
Normal file
36
ICD.Common/Utils/Extensions/StringBuilderExtensions.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class StringBuilderExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Empties the StringBuilder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
public static void Clear(this StringBuilder extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
extends.Remove(0, extends.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current string value of the StringBuilder and clears the
|
||||||
|
/// StringBuilder for further use.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string Pop(this StringBuilder extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string output = extends.ToString();
|
||||||
|
extends.Clear();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
256
ICD.Common/Utils/Extensions/StringExtensions.cs
Normal file
256
ICD.Common/Utils/Extensions/StringExtensions.cs
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class StringExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the first appearance of an item from the given sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <param name="first"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static int IndexOf(this string extends, IEnumerable<string> items, out string first)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
int index = -1;
|
||||||
|
first = null;
|
||||||
|
|
||||||
|
foreach (string item in items)
|
||||||
|
{
|
||||||
|
int thisIndex = extends.IndexOf(item, StringComparison.Ordinal);
|
||||||
|
if (thisIndex == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (index != -1 && thisIndex >= index)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
index = thisIndex;
|
||||||
|
first = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the string starts with the given character.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="character"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool StartsWith(this string extends, char character)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.StartsWith(character.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the string ends with the given character.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="character"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool EndsWith(this string extends, char character)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.EndsWith(character.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits the string by the given delimiter, returning up to the given number of substrings.
|
||||||
|
/// E.g. "a:b:c".Split(':', 2) returns ["a", "b:c"]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="delimeter"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<string> Split(this string extends, char delimeter, int count)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (count < 2)
|
||||||
|
{
|
||||||
|
yield return extends;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = extends.IndexOf(delimeter);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
yield return extends;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
string first = extends.Substring(0, index);
|
||||||
|
string second = extends.Substring(index + 1);
|
||||||
|
count--;
|
||||||
|
|
||||||
|
yield return first;
|
||||||
|
foreach (string item in second.Split(delimeter, count))
|
||||||
|
yield return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string into chunks of the given length.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="chunkSize"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<string> Split(this string extends, int chunkSize)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (chunkSize <= 0)
|
||||||
|
throw new InvalidOperationException("chunkSize must be greater than 0");
|
||||||
|
|
||||||
|
return Enumerable.Range(0, extends.Length / chunkSize)
|
||||||
|
.Select(i => extends.Substring(i * chunkSize, chunkSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string by a given substring.
|
||||||
|
/// Taken from
|
||||||
|
/// https://social.msdn.microsoft.com/Forums/en-US/914a350f-e0e9-45e0-91a4-6b4b2168e780/string-split-function
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="delimeter"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<string> Split(this string extends, string delimeter)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (delimeter == null)
|
||||||
|
throw new ArgumentNullException("delimeter");
|
||||||
|
|
||||||
|
int dSum = 0;
|
||||||
|
int sSum = 0;
|
||||||
|
int length = extends.Length;
|
||||||
|
int delimiterLength = delimeter.Length;
|
||||||
|
|
||||||
|
if (delimiterLength == 0 || length == 0 || length < delimiterLength)
|
||||||
|
{
|
||||||
|
yield return extends;
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] cd = delimeter.ToCharArray();
|
||||||
|
char[] cs = extends.ToCharArray();
|
||||||
|
|
||||||
|
for (int i = 0; i < delimiterLength; i++)
|
||||||
|
{
|
||||||
|
dSum += cd[i];
|
||||||
|
sSum += cs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
int start = 0;
|
||||||
|
for (int i = start; i < length - delimiterLength; i++)
|
||||||
|
{
|
||||||
|
if (i >= start && dSum == sSum && extends.Substring(i, delimiterLength) == delimeter)
|
||||||
|
{
|
||||||
|
yield return extends.Substring(start, i - start);
|
||||||
|
start = i + delimiterLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
sSum += cs[i + delimiterLength] - cs[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dSum == sSum && extends.Substring(length - delimiterLength, delimiterLength) == delimeter)
|
||||||
|
{
|
||||||
|
yield return extends.Substring(start, length - delimiterLength - start);
|
||||||
|
yield return string.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
yield return extends.Substring(start, length - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Splits a string by the given substrings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="delimeters"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<string> Split(this string extends, IEnumerable<string> delimeters)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (delimeters == null)
|
||||||
|
throw new ArgumentNullException("delimeters");
|
||||||
|
|
||||||
|
string[] delimitersArray = delimeters as string[] ?? delimeters.ToArray();
|
||||||
|
return delimitersArray.Length == 0
|
||||||
|
? new[] {extends}
|
||||||
|
: extends.Split(delimitersArray.First())
|
||||||
|
.SelectMany(s => s.Split(delimitersArray.Skip(1)))
|
||||||
|
.Where(s => !string.IsNullOrEmpty(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes whitespace from the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string RemoveWhitespace(this string extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return new string(extends.Where(c => !Char.IsWhiteSpace(c)).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the given characters from the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="characters"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string Remove(this string extends, IEnumerable<char> characters)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (characters == null)
|
||||||
|
throw new ArgumentNullException("characters");
|
||||||
|
|
||||||
|
return new string(extends.Where(c => !characters.Contains(c)).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the string only contains numbers.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool IsNumeric(this string extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.All(char.IsDigit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
ICD.Common/Utils/Extensions/TimeSpanExtensions.cs
Normal file
32
ICD.Common/Utils/Extensions/TimeSpanExtensions.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class TimeSpanExtensions
|
||||||
|
{
|
||||||
|
public static string ToReadableString(this TimeSpan extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
if (extends.Days > 0)
|
||||||
|
builder.AppendFormat("{0} days, ", extends.Days);
|
||||||
|
if (extends.Hours > 0)
|
||||||
|
builder.AppendFormat("{0} hours, ", extends.Hours);
|
||||||
|
if (extends.Minutes > 0)
|
||||||
|
builder.AppendFormat("{0} minutes, ", extends.Minutes);
|
||||||
|
if (extends.Seconds > 0)
|
||||||
|
builder.AppendFormat("{0} seconds, ", extends.Seconds);
|
||||||
|
if (extends.Milliseconds > 0)
|
||||||
|
{
|
||||||
|
builder.AppendFormat("{0}.{1} ms", extends.Milliseconds,
|
||||||
|
((double)extends.Ticks / TimeSpan.TicksPerMillisecond) - extends.TotalMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
ICD.Common/Utils/Extensions/TypeExtensions.cs
Normal file
17
ICD.Common/Utils/Extensions/TypeExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
#else
|
||||||
|
using System.Reflection;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Extensions
|
||||||
|
{
|
||||||
|
public static class TypeExtensions
|
||||||
|
{
|
||||||
|
public static bool IsAssignableTo(this Type from, Type to)
|
||||||
|
{
|
||||||
|
return to.IsAssignableFrom(from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
ICD.Common/Utils/IO/IcdDirectory.cs
Normal file
69
ICD.Common/Utils/IO/IcdDirectory.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public static class IcdDirectory
|
||||||
|
{
|
||||||
|
public static string GetApplicationDirectory()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return Directory.GetApplicationDirectory();
|
||||||
|
#else
|
||||||
|
return Directory.GetCurrentDirectory();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Exists(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Directory.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetFiles(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Directory.GetFiles(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetDirectories(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Directory.GetDirectories(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Delete(string path, bool recursive)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
Directory.Delete(path, recursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CreateDirectory(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDirectoryRoot(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Directory.GetDirectoryRoot(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
ICD.Common/Utils/IO/IcdEncodingStringWriter.cs
Normal file
39
ICD.Common/Utils/IO/IcdEncodingStringWriter.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public sealed class IcdEncodingStringWriter : IcdStringWriter
|
||||||
|
{
|
||||||
|
public IcdEncodingStringWriter(StringBuilder output, Encoding encoding)
|
||||||
|
: base(new EncodingStringWriter(output, encoding))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class EncodingStringWriter : StringWriter
|
||||||
|
{
|
||||||
|
private readonly Encoding m_Encoding;
|
||||||
|
|
||||||
|
public override Encoding Encoding { get { return m_Encoding; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <param name="encoding"></param>
|
||||||
|
public EncodingStringWriter(StringBuilder builder, Encoding encoding)
|
||||||
|
: base(builder)
|
||||||
|
{
|
||||||
|
if (encoding == null)
|
||||||
|
throw new ArgumentNullException("encoding");
|
||||||
|
|
||||||
|
m_Encoding = encoding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
ICD.Common/Utils/IO/IcdFile.cs
Normal file
60
ICD.Common/Utils/IO/IcdFile.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using ICD.Common.Properties;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public static class IcdFile
|
||||||
|
{
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ReadToEnd(string path, Encoding encoding)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
if (encoding == null)
|
||||||
|
throw new ArgumentNullException("encoding");
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return File.ReadToEnd(path, encoding);
|
||||||
|
#else
|
||||||
|
return File.ReadAllText(path, encoding);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool Exists(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return File.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Copy(string pathFrom, string pathTo)
|
||||||
|
{
|
||||||
|
if (pathFrom == null)
|
||||||
|
throw new ArgumentNullException("pathFrom");
|
||||||
|
|
||||||
|
if (pathTo == null)
|
||||||
|
throw new ArgumentNullException("pathTo");
|
||||||
|
|
||||||
|
File.Copy(pathFrom, pathTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Delete(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
ICD.Common/Utils/IO/IcdFileStream.cs
Normal file
47
ICD.Common/Utils/IO/IcdFileStream.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public sealed class IcdFileStream : IcdStream
|
||||||
|
{
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
public FileStream WrappedFileStream { get { return WrappedStream as FileStream; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileStrean"></param>
|
||||||
|
public IcdFileStream(FileStream fileStrean)
|
||||||
|
: base(fileStrean)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IcdFileStream OpenWrite(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return new IcdFileStream(File.OpenWrite(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
WrappedFileStream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
WrappedFileStream.Close();
|
||||||
|
#else
|
||||||
|
WrappedFileStream.Dispose();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
ICD.Common/Utils/IO/IcdMemoryStream.cs
Normal file
47
ICD.Common/Utils/IO/IcdMemoryStream.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public sealed class IcdMemoryStream : IcdStream
|
||||||
|
{
|
||||||
|
public int Position { get; set; }
|
||||||
|
|
||||||
|
public MemoryStream WrappedMemoryStream { get { return WrappedStream as MemoryStream; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public IcdMemoryStream()
|
||||||
|
: this(new MemoryStream())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="memoryStream"></param>
|
||||||
|
public IcdMemoryStream(MemoryStream memoryStream)
|
||||||
|
: base(memoryStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
WrappedMemoryStream.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
WrappedMemoryStream.Close();
|
||||||
|
#else
|
||||||
|
WrappedMemoryStream.Dispose();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
58
ICD.Common/Utils/IO/IcdPath.cs
Normal file
58
ICD.Common/Utils/IO/IcdPath.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public static class IcdPath
|
||||||
|
{
|
||||||
|
public static string GetFileNameWithoutExtension(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Path.GetFileNameWithoutExtension(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetDirectoryName(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Path.GetDirectoryName(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetExtension(string path)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
return Path.GetExtension(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Combine(string a, string b)
|
||||||
|
{
|
||||||
|
if (a == null)
|
||||||
|
throw new ArgumentNullException("a");
|
||||||
|
|
||||||
|
if (b == null)
|
||||||
|
throw new ArgumentNullException("b");
|
||||||
|
|
||||||
|
return Path.Combine(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ChangeExtension(string path, string ext)
|
||||||
|
{
|
||||||
|
if (path == null)
|
||||||
|
throw new ArgumentNullException("path");
|
||||||
|
|
||||||
|
if (ext == null)
|
||||||
|
throw new ArgumentNullException("ext");
|
||||||
|
|
||||||
|
return Path.ChangeExtension(path, ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
ICD.Common/Utils/IO/IcdStream.cs
Normal file
33
ICD.Common/Utils/IO/IcdStream.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public class IcdStream : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Stream m_Stream;
|
||||||
|
|
||||||
|
public Stream WrappedStream { get { return m_Stream; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream"></param>
|
||||||
|
public IcdStream(Stream stream)
|
||||||
|
{
|
||||||
|
if (stream == null)
|
||||||
|
throw new ArgumentNullException("stream");
|
||||||
|
|
||||||
|
m_Stream = stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_Stream.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
ICD.Common/Utils/IO/IcdStreamReader.cs
Normal file
41
ICD.Common/Utils/IO/IcdStreamReader.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#elif STANDARD
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public sealed class IcdStreamReader : IDisposable
|
||||||
|
{
|
||||||
|
private readonly StreamReader m_StreamReader;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="memoryStream"></param>
|
||||||
|
public IcdStreamReader(IcdMemoryStream memoryStream)
|
||||||
|
{
|
||||||
|
if (memoryStream == null)
|
||||||
|
throw new ArgumentNullException("memoryStream");
|
||||||
|
|
||||||
|
m_StreamReader = new StreamReader(memoryStream.WrappedMemoryStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
~IcdStreamReader()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadToEnd()
|
||||||
|
{
|
||||||
|
return m_StreamReader.ReadToEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_StreamReader.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
ICD.Common/Utils/IO/IcdStringReader.cs
Normal file
24
ICD.Common/Utils/IO/IcdStringReader.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public sealed class IcdStringReader : IcdTextReader
|
||||||
|
{
|
||||||
|
public StringReader WrappedStringReader { get { return WrappedTextReader as StringReader; } }
|
||||||
|
|
||||||
|
public IcdStringReader(string value)
|
||||||
|
: this(new StringReader(value))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private IcdStringReader(StringReader stringReader)
|
||||||
|
: base(stringReader)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
ICD.Common/Utils/IO/IcdStringWriter.cs
Normal file
32
ICD.Common/Utils/IO/IcdStringWriter.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System.Text;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public class IcdStringWriter : IcdTextWriter
|
||||||
|
{
|
||||||
|
public StringWriter WrappedStringWriter { get { return WrappedTextWriter as StringWriter; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stringWriter"></param>
|
||||||
|
public IcdStringWriter(StringWriter stringWriter)
|
||||||
|
: base(stringWriter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stringBuilder"></param>
|
||||||
|
public IcdStringWriter(StringBuilder stringBuilder)
|
||||||
|
: this(new StringWriter(stringBuilder))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
ICD.Common/Utils/IO/IcdTextReader.cs
Normal file
21
ICD.Common/Utils/IO/IcdTextReader.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public class IcdTextReader
|
||||||
|
{
|
||||||
|
private readonly TextReader m_TextReader;
|
||||||
|
|
||||||
|
public TextReader WrappedTextReader { get { return m_TextReader; } }
|
||||||
|
|
||||||
|
protected IcdTextReader(TextReader textReader)
|
||||||
|
{
|
||||||
|
m_TextReader = textReader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
ICD.Common/Utils/IO/IcdTextWriter.cs
Normal file
38
ICD.Common/Utils/IO/IcdTextWriter.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronIO;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.IO
|
||||||
|
{
|
||||||
|
public class IcdTextWriter : IDisposable
|
||||||
|
{
|
||||||
|
private readonly TextWriter m_TextWriter;
|
||||||
|
|
||||||
|
public TextWriter WrappedTextWriter { get { return m_TextWriter; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textWriter"></param>
|
||||||
|
protected IcdTextWriter(TextWriter textWriter)
|
||||||
|
{
|
||||||
|
if (textWriter == null)
|
||||||
|
throw new ArgumentNullException("textWriter");
|
||||||
|
|
||||||
|
m_TextWriter = textWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
~IcdTextWriter()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_TextWriter.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
ICD.Common/Utils/IStateDisposable.cs
Normal file
15
ICD.Common/Utils/IStateDisposable.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides features for managing the disposed state of an IDisposable.
|
||||||
|
/// </summary>
|
||||||
|
public interface IStateDisposable : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this instance has been disposed.
|
||||||
|
/// </summary>
|
||||||
|
bool IsDisposed { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
109
ICD.Common/Utils/IcdConsole.cs
Normal file
109
ICD.Common/Utils/IcdConsole.cs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public sealed class IcdConsole
|
||||||
|
{
|
||||||
|
public enum eAccessLevel
|
||||||
|
{
|
||||||
|
Operator = 0,
|
||||||
|
Programmer = 1,
|
||||||
|
Administrator = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps CrestronConsole.ConsoleCommandResponse for S+ compatibility.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void ConsoleCommandResponseLine(string message, params object[] args)
|
||||||
|
{
|
||||||
|
ConsoleCommandResponse(message + IcdEnvironment.NewLine, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wraps CrestronConsole.ConsoleCommandResponse for S+ compatibility.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
/// <param name="args"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void ConsoleCommandResponse(string message, params object[] args)
|
||||||
|
{
|
||||||
|
message = string.Format(message, args);
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CrestronConsole.ConsoleCommandResponse(message);
|
||||||
|
}
|
||||||
|
catch (NotSupportedException)
|
||||||
|
{
|
||||||
|
CrestronConsole.Print(message);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
System.Console.Write(message, args);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintLine(string message)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CrestronConsole.PrintLine(message);
|
||||||
|
#else
|
||||||
|
System.Console.WriteLine(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void PrintLine(string message, params object[] args)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CrestronConsole.PrintLine(message, args);
|
||||||
|
#else
|
||||||
|
System.Console.WriteLine(message, args);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Print(string message)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CrestronConsole.Print(message);
|
||||||
|
#else
|
||||||
|
System.Console.Write(message);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Print(string message, params object[] args)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CrestronConsole.Print(message, args);
|
||||||
|
#else
|
||||||
|
System.Console.Write(message, args);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool SendControlSystemCommand(string command, ref string result)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return CrestronConsole.SendControlSystemCommand(command, ref result);
|
||||||
|
#else
|
||||||
|
result = string.Empty;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddNewConsoleCommand(Action<string> callback, string command, string help, eAccessLevel accessLevel)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CrestronConsole.AddNewConsoleCommand(str => callback(str), command, help, (ConsoleAccessLevelEnum)(int)accessLevel);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
118
ICD.Common/Utils/IcdEnvironment.SimplSharp.cs
Normal file
118
ICD.Common/Utils/IcdEnvironment.SimplSharp.cs
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static partial class IcdEnvironment
|
||||||
|
{
|
||||||
|
public static string NewLine { get { return CrestronEnvironment.NewLine; } }
|
||||||
|
|
||||||
|
public static eRuntimeEnvironment RuntimeEnvironment
|
||||||
|
{
|
||||||
|
get { return GetRuntimeEnvironment(CrestronEnvironment.RuntimeEnvironment); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static constructor.
|
||||||
|
/// </summary>
|
||||||
|
static IcdEnvironment()
|
||||||
|
{
|
||||||
|
CrestronEnvironment.ProgramStatusEventHandler += CrestronEnvironmentOnProgramStatusEventHandler;
|
||||||
|
CrestronEnvironment.EthernetEventHandler += CrestronEnvironmentOnEthernetEventHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the network address(es) of the processor.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<string> NetworkAddresses
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
const CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET param =
|
||||||
|
CrestronEthernetHelper.ETHERNET_PARAMETER_TO_GET.GET_CURRENT_IP_ADDRESS;
|
||||||
|
const EthernetAdapterType type = EthernetAdapterType.EthernetLANAdapter;
|
||||||
|
short id = CrestronEthernetHelper.GetAdapterdIdForSpecifiedAdapterType(type);
|
||||||
|
yield return CrestronEthernetHelper.GetEthernetParameter(param, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public static DateTime GetLocalTime()
|
||||||
|
{
|
||||||
|
return CrestronEnvironment.GetLocalTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static eEthernetEventType GetEthernetEventType(Crestron.SimplSharp.eEthernetEventType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Crestron.SimplSharp.eEthernetEventType.LinkDown:
|
||||||
|
return eEthernetEventType.LinkDown;
|
||||||
|
case Crestron.SimplSharp.eEthernetEventType.LinkUp:
|
||||||
|
return eEthernetEventType.LinkUp;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException("type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static eEthernetAdapterType GetEthernetAdapterType(EthernetAdapterType ethernetAdapter)
|
||||||
|
{
|
||||||
|
return (eEthernetAdapterType)(int)ethernetAdapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static eProgramStatusEventType GetProgramStatusEventType(Crestron.SimplSharp.eProgramStatusEventType type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Crestron.SimplSharp.eProgramStatusEventType.Stopping:
|
||||||
|
return eProgramStatusEventType.Stopping;
|
||||||
|
case Crestron.SimplSharp.eProgramStatusEventType.Paused:
|
||||||
|
return eProgramStatusEventType.Paused;
|
||||||
|
case Crestron.SimplSharp.eProgramStatusEventType.Resumed:
|
||||||
|
return eProgramStatusEventType.Resumed;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException("type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static eRuntimeEnvironment GetRuntimeEnvironment(Crestron.SimplSharp.eRuntimeEnvironment runtimeEnvironment)
|
||||||
|
{
|
||||||
|
switch (runtimeEnvironment)
|
||||||
|
{
|
||||||
|
case Crestron.SimplSharp.eRuntimeEnvironment.SIMPL:
|
||||||
|
return eRuntimeEnvironment.SimplSharp;
|
||||||
|
case Crestron.SimplSharp.eRuntimeEnvironment.SimplSharpPro:
|
||||||
|
return eRuntimeEnvironment.SimplSharpPro;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException("runtimeEnvironment");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private static void CrestronEnvironmentOnEthernetEventHandler(EthernetEventArgs args)
|
||||||
|
{
|
||||||
|
EthernetEventCallback handler = OnEthernetEvent;
|
||||||
|
if (handler != null)
|
||||||
|
handler(GetEthernetAdapterType(args.EthernetAdapter), GetEthernetEventType(args.EthernetEventType));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CrestronEnvironmentOnProgramStatusEventHandler(Crestron.SimplSharp.eProgramStatusEventType type)
|
||||||
|
{
|
||||||
|
ProgramStatusCallback handler = OnProgramStatusEvent;
|
||||||
|
if (handler != null)
|
||||||
|
handler(GetProgramStatusEventType(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
34
ICD.Common/Utils/IcdEnvironment.Standard.cs
Normal file
34
ICD.Common/Utils/IcdEnvironment.Standard.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#if STANDARD
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Net.Sockets;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static partial class IcdEnvironment
|
||||||
|
{
|
||||||
|
public static string NewLine { get { return Environment.NewLine; } }
|
||||||
|
|
||||||
|
public static DateTime GetLocalTime()
|
||||||
|
{
|
||||||
|
return DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static eRuntimeEnvironment RuntimeEnvironment { get { return eRuntimeEnvironment.Standard; } }
|
||||||
|
|
||||||
|
public static IEnumerable<string> NetworkAddresses
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return NetworkInterface.GetAllNetworkInterfaces()
|
||||||
|
.Where(ni => ni.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 || ni.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
|
||||||
|
.SelectMany(ni => ni.GetIPProperties().UnicastAddresses
|
||||||
|
.Where(ua => ua.Address.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
.Select(ua => ua.Address.ToString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
57
ICD.Common/Utils/IcdEnvironment.cs
Normal file
57
ICD.Common/Utils/IcdEnvironment.cs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static partial class IcdEnvironment
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enumeration to define the various runtime environments a SIMPL# module can run in.
|
||||||
|
/// </summary>
|
||||||
|
public enum eRuntimeEnvironment
|
||||||
|
{
|
||||||
|
SimplSharp,
|
||||||
|
SimplSharpPro,
|
||||||
|
Standard
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for the Program Event Types
|
||||||
|
/// </summary>
|
||||||
|
public enum eProgramStatusEventType
|
||||||
|
{
|
||||||
|
Stopping,
|
||||||
|
Paused,
|
||||||
|
Resumed,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum for the Ethernet Event Types
|
||||||
|
/// </summary>
|
||||||
|
public enum eEthernetEventType
|
||||||
|
{
|
||||||
|
LinkDown,
|
||||||
|
LinkUp,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enums for the Ethernet Adapter Type
|
||||||
|
/// </summary>
|
||||||
|
[Flags]
|
||||||
|
public enum eEthernetAdapterType
|
||||||
|
{
|
||||||
|
EthernetUnknownAdapter = 0,
|
||||||
|
EthernetLanAdapter = 1,
|
||||||
|
EthernetCsAdapter = 2,
|
||||||
|
EthernetWifiAdapter = 4,
|
||||||
|
EthernetLan2Adapter = 8,
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void ProgramStatusCallback(eProgramStatusEventType type);
|
||||||
|
|
||||||
|
public delegate void EthernetEventCallback(eEthernetAdapterType adapter, eEthernetEventType type);
|
||||||
|
|
||||||
|
public static event ProgramStatusCallback OnProgramStatusEvent;
|
||||||
|
|
||||||
|
public static event EthernetEventCallback OnEthernetEvent;
|
||||||
|
}
|
||||||
|
}
|
||||||
210
ICD.Common/Utils/IcdErrorLog.cs
Normal file
210
ICD.Common/Utils/IcdErrorLog.cs
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class IcdErrorLog
|
||||||
|
{
|
||||||
|
private const string CONSOLE_RED = "\x1B[31;1m";
|
||||||
|
private const string CONSOLE_GREEN = "\x1B[32;1m";
|
||||||
|
private const string CONSOLE_YELLOW = "\x1B[33;1m";
|
||||||
|
private const string CONSOLE_BLUE = "\x1B[34;1m";
|
||||||
|
//private const string CONSOLE_MAGENTA = "\x1B[35;1m";
|
||||||
|
private const string CONSOLE_CYAN = "\x1B[36;1m";
|
||||||
|
//private const string CONSOLE_WHITE = "\x1B[37;1m";
|
||||||
|
private const string CONSOLE_YELLOW_ON_RED_BACKGROUND = "\x1B[93;41m";
|
||||||
|
private const string CONSOLE_RESET = "\x1B[0m";
|
||||||
|
|
||||||
|
private static readonly SafeCriticalSection s_LoggingSection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static constructor.
|
||||||
|
/// </summary>
|
||||||
|
static IcdErrorLog()
|
||||||
|
{
|
||||||
|
s_LoggingSection = new SafeCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Error(string message)
|
||||||
|
{
|
||||||
|
s_LoggingSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
message = FormatConsoleColor(message, CONSOLE_RED);
|
||||||
|
Crestron.SimplSharp.ErrorLog.Error(message);
|
||||||
|
#else
|
||||||
|
System.Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
System.Console.Error.WriteLine(message);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_LoggingSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Error(string message, params object[] args)
|
||||||
|
{
|
||||||
|
Error(string.Format(message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Warn(string message)
|
||||||
|
{
|
||||||
|
s_LoggingSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
message = FormatConsoleColor(message, CONSOLE_YELLOW);
|
||||||
|
Crestron.SimplSharp.ErrorLog.Warn(message);
|
||||||
|
#else
|
||||||
|
System.Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
System.Console.Error.WriteLine(message);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_LoggingSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Warn(string message, params object[] args)
|
||||||
|
{
|
||||||
|
Warn(string.Format(message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Notice(string message)
|
||||||
|
{
|
||||||
|
s_LoggingSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
message = FormatConsoleColor(message, CONSOLE_BLUE);
|
||||||
|
Crestron.SimplSharp.ErrorLog.Notice(message);
|
||||||
|
#else
|
||||||
|
System.Console.ForegroundColor = ConsoleColor.Blue;
|
||||||
|
System.Console.Error.WriteLine(message);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_LoggingSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Notice(string message, params object[] args)
|
||||||
|
{
|
||||||
|
Notice(string.Format(message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Ok(string message)
|
||||||
|
{
|
||||||
|
s_LoggingSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
message = FormatConsoleColor(message, CONSOLE_GREEN);
|
||||||
|
Crestron.SimplSharp.ErrorLog.Ok(message);
|
||||||
|
#else
|
||||||
|
System.Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
System.Console.Error.WriteLine(message);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_LoggingSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Ok(string message, params object[] args)
|
||||||
|
{
|
||||||
|
Ok(string.Format(message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Exception(Exception ex, string message)
|
||||||
|
{
|
||||||
|
s_LoggingSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
message = FormatConsoleColor(message, CONSOLE_YELLOW_ON_RED_BACKGROUND);
|
||||||
|
Crestron.SimplSharp.ErrorLog.Exception(message, ex);
|
||||||
|
#else
|
||||||
|
System.Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
|
System.Console.BackgroundColor = ConsoleColor.Red;
|
||||||
|
System.Console.Error.WriteLine("{0}: {1}", ex.GetType().Name, message);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
System.Console.Error.WriteLine(ex.StackTrace);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_LoggingSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Exception(Exception ex, string message, params object[] args)
|
||||||
|
{
|
||||||
|
message = string.Format(message, args);
|
||||||
|
Exception(ex, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Info(string message)
|
||||||
|
{
|
||||||
|
s_LoggingSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
message = FormatConsoleColor(message, CONSOLE_CYAN);
|
||||||
|
Crestron.SimplSharp.ErrorLog.Info(message);
|
||||||
|
#else
|
||||||
|
System.Console.ForegroundColor = ConsoleColor.Cyan;
|
||||||
|
System.Console.Error.WriteLine(message);
|
||||||
|
System.Console.ResetColor();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
s_LoggingSection.Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Info(string message, params object[] args)
|
||||||
|
{
|
||||||
|
Info(string.Format(message, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats the text with the given console color.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <param name="color"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static string FormatConsoleColor(string text, string color)
|
||||||
|
{
|
||||||
|
return string.Format("{0}{1}{2}", color, text, CONSOLE_RESET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
ICD.Common/Utils/IcdZip.cs
Normal file
40
ICD.Common/Utils/IcdZip.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using System;
|
||||||
|
using System.IO.Compression;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utils for managing archives.
|
||||||
|
/// </summary>
|
||||||
|
public static class IcdZip
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Unzips the archive at the given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="outputPath"></param>
|
||||||
|
public static bool Unzip(string path, string outputPath)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return CrestronZIP.Unzip(path, outputPath) == CrestronZIP.ResultCode.ZR_OK;
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (ZipArchive archive = ZipFile.Open(path, ZipArchiveMode.Read))
|
||||||
|
archive.ExtractToDirectory(outputPath);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
78
ICD.Common/Utils/Json/AbstractGenericJsonConverter.cs
Normal file
78
ICD.Common/Utils/Json/AbstractGenericJsonConverter.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Json
|
||||||
|
{
|
||||||
|
public abstract class AbstractGenericJsonConverter<T> : JsonConverter
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the JSON representation of the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <param name="serializer">The calling serializer.</param>
|
||||||
|
public override sealed void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
writer.WriteNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
WriteJson(writer, (T)value, serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the JSON representation of the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer">The <see cref="T:Newtonsoft.Json.JsonWriter"/> to write to.</param>
|
||||||
|
/// <param name="value">The value.</param>
|
||||||
|
/// <param name="serializer">The calling serializer.</param>
|
||||||
|
[PublicAPI]
|
||||||
|
public abstract void WriteJson(JsonWriter writer, T value, JsonSerializer serializer);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the JSON representation of the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
|
||||||
|
/// <param name="objectType">Type of the object.</param>
|
||||||
|
/// <param name="existingValue">The existing value of object being read.</param>
|
||||||
|
/// <param name="serializer">The calling serializer.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The object value.
|
||||||
|
/// </returns>
|
||||||
|
public override sealed object ReadJson(JsonReader reader, Type objectType, object existingValue,
|
||||||
|
JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
if (reader.TokenType == JsonToken.Null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return ReadJson(reader, (T)existingValue, serializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the JSON representation of the object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="reader">The <see cref="T:Newtonsoft.Json.JsonReader"/> to read from.</param>
|
||||||
|
/// <param name="existingValue">The existing value of object being read.</param>
|
||||||
|
/// <param name="serializer">The calling serializer.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The object value.
|
||||||
|
/// </returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public abstract T ReadJson(JsonReader reader, T existingValue, JsonSerializer serializer);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether this instance can convert the specified object type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="objectType">Type of the object.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
|
||||||
|
/// </returns>
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(T);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
86
ICD.Common/Utils/Json/JsonItemWrapper.cs
Normal file
86
ICD.Common/Utils/Json/JsonItemWrapper.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Json
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple wrapper for serialization of an object and its type.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class JsonItemWrapper
|
||||||
|
{
|
||||||
|
private const string TYPE_TOKEN = "t";
|
||||||
|
private const string ITEM_TOKEN = "i";
|
||||||
|
|
||||||
|
private readonly string m_ItemTypeString;
|
||||||
|
private readonly object m_Item;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the string representation of the item type. Returns null if the item is null.
|
||||||
|
/// </summary>
|
||||||
|
public string ItemTypeString { get { return m_ItemTypeString; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Type of the item. Returns null if the item is null.
|
||||||
|
/// </summary>
|
||||||
|
public Type ItemType
|
||||||
|
{
|
||||||
|
get { return string.IsNullOrEmpty(m_ItemTypeString) ? null : Type.GetType(m_ItemTypeString); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the wrapped item.
|
||||||
|
/// </summary>
|
||||||
|
public object Item { get { return string.IsNullOrEmpty(m_ItemTypeString) ? null : m_Item; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
public JsonItemWrapper(object item)
|
||||||
|
{
|
||||||
|
m_ItemTypeString = item == null ? null : item.GetType().FullName;
|
||||||
|
m_Item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Writes the JsonItemWrapper as a JObject.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer"></param>
|
||||||
|
public void Write(JsonWriter writer)
|
||||||
|
{
|
||||||
|
if (writer == null)
|
||||||
|
throw new ArgumentNullException("writer");
|
||||||
|
|
||||||
|
writer.WriteStartObject();
|
||||||
|
|
||||||
|
writer.WritePropertyName(TYPE_TOKEN);
|
||||||
|
writer.WriteValue(m_ItemTypeString);
|
||||||
|
|
||||||
|
writer.WritePropertyName(ITEM_TOKEN);
|
||||||
|
writer.WriteValue(JsonConvert.SerializeObject(m_Item));
|
||||||
|
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the JToken back to the wrapped object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="token"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static object ReadToObject(JToken token)
|
||||||
|
{
|
||||||
|
if (token == null)
|
||||||
|
throw new ArgumentNullException("token");
|
||||||
|
|
||||||
|
string typeString = (string)token.SelectToken(TYPE_TOKEN);
|
||||||
|
if (string.IsNullOrEmpty(typeString))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
string itemString = (string)token.SelectToken(ITEM_TOKEN);
|
||||||
|
Type type = Type.GetType(typeString);
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject(itemString, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
79
ICD.Common/Utils/Json/JsonUtils.cs
Normal file
79
ICD.Common/Utils/Json/JsonUtils.cs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Json
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility methods for working with JSON.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static class JsonUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pretty-prints the JSON document.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="json"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Print(string json)
|
||||||
|
{
|
||||||
|
int indent = 0;
|
||||||
|
bool quoted = false;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < json.Length; i++)
|
||||||
|
{
|
||||||
|
char ch = json[i];
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '{':
|
||||||
|
case '[':
|
||||||
|
sb.Append(ch);
|
||||||
|
if (!quoted)
|
||||||
|
{
|
||||||
|
sb.Append(IcdEnvironment.NewLine);
|
||||||
|
Enumerable.Range(0, ++indent).ForEach(item => sb.Append('\t'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '}':
|
||||||
|
case ']':
|
||||||
|
if (!quoted)
|
||||||
|
{
|
||||||
|
sb.Append(IcdEnvironment.NewLine);
|
||||||
|
Enumerable.Range(0, --indent).ForEach(item => sb.Append('\t'));
|
||||||
|
}
|
||||||
|
sb.Append(ch);
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
sb.Append(ch);
|
||||||
|
bool escaped = false;
|
||||||
|
int index = i;
|
||||||
|
while (index > 0 && json[--index] == '\\')
|
||||||
|
escaped = !escaped;
|
||||||
|
if (!escaped)
|
||||||
|
quoted = !quoted;
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
sb.Append(ch);
|
||||||
|
if (!quoted)
|
||||||
|
{
|
||||||
|
sb.Append(IcdEnvironment.NewLine);
|
||||||
|
Enumerable.Range(0, indent).ForEach(item => sb.Append('\t'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
sb.Append(ch);
|
||||||
|
if (!quoted)
|
||||||
|
sb.Append(" ");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sb.Append(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IcdConsole.PrintLine(sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
220
ICD.Common/Utils/MathUtils.cs
Normal file
220
ICD.Common/Utils/MathUtils.cs
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Utils.Collections;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utility methods for math operations.
|
||||||
|
/// </summary>
|
||||||
|
public static class MathUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Clamps the number between the two values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="min"></param>
|
||||||
|
/// <param name="max"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int Clamp(int number, int min, int max)
|
||||||
|
{
|
||||||
|
return (int)Clamp((double)number, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clamps the number between the two values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="min"></param>
|
||||||
|
/// <param name="max"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ushort Clamp(ushort number, ushort min, ushort max)
|
||||||
|
{
|
||||||
|
return (ushort)Clamp((double)number, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clamps the number between the two values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="min"></param>
|
||||||
|
/// <param name="max"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static float Clamp(float number, float min, float max)
|
||||||
|
{
|
||||||
|
return (float)Clamp((double)number, min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clamps the number between the two values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="min"></param>
|
||||||
|
/// <param name="max"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double Clamp(double number, double min, double max)
|
||||||
|
{
|
||||||
|
return min < max
|
||||||
|
? Math.Min(Math.Max(number, min), max)
|
||||||
|
: Math.Min(Math.Max(number, max), min);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value after the input range has been mapped to a new range
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStart">Input start.</param>
|
||||||
|
/// <param name="inputEnd">Input end.</param>
|
||||||
|
/// <param name="outputStart">Output start.</param>
|
||||||
|
/// <param name="outputEnd">Output end.</param>
|
||||||
|
/// <param name="value">Value.</param>
|
||||||
|
/// <returns>The newly mapped value</returns>
|
||||||
|
public static double MapRange(double inputStart, double inputEnd, double outputStart, double outputEnd, double value)
|
||||||
|
{
|
||||||
|
double slope = (outputEnd - outputStart) / (inputEnd - inputStart);
|
||||||
|
return outputStart + slope * (value - inputStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value after the input range has been mapped to a new range
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStart">Input start.</param>
|
||||||
|
/// <param name="inputEnd">Input end.</param>
|
||||||
|
/// <param name="outputStart">Output start.</param>
|
||||||
|
/// <param name="outputEnd">Output end.</param>
|
||||||
|
/// <param name="value">Value.</param>
|
||||||
|
/// <returns>The newly mapped value</returns>
|
||||||
|
public static float MapRange(float inputStart, float inputEnd, float outputStart, float outputEnd, float value)
|
||||||
|
{
|
||||||
|
return (float)MapRange((double)inputStart, inputEnd, outputStart, outputEnd, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value after the input range has been mapped to a new range
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStart">Input start.</param>
|
||||||
|
/// <param name="inputEnd">Input end.</param>
|
||||||
|
/// <param name="outputStart">Output start.</param>
|
||||||
|
/// <param name="outputEnd">Output end.</param>
|
||||||
|
/// <param name="value">Value.</param>
|
||||||
|
/// <returns>The newly mapped value</returns>
|
||||||
|
public static int MapRange(int inputStart, int inputEnd, int outputStart, int outputEnd, int value)
|
||||||
|
{
|
||||||
|
return (int)MapRange((double)inputStart, inputEnd, outputStart, outputEnd, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value after the input range has been mapped to a new range
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="inputStart">Input start.</param>
|
||||||
|
/// <param name="inputEnd">Input end.</param>
|
||||||
|
/// <param name="outputStart">Output start.</param>
|
||||||
|
/// <param name="outputEnd">Output end.</param>
|
||||||
|
/// <param name="value">Value.</param>
|
||||||
|
/// <returns>The newly mapped value</returns>
|
||||||
|
public static ushort MapRange(ushort inputStart, ushort inputEnd, ushort outputStart, ushort outputEnd, ushort value)
|
||||||
|
{
|
||||||
|
return (ushort)MapRange((double)inputStart, inputEnd, outputStart, outputEnd, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the date in the given range to the float range 0.0f to 1.0f.
|
||||||
|
/// 0.5f - The date is half way between the end points.
|
||||||
|
/// less than 0.0f - the date is before the start.
|
||||||
|
/// greater than 1.0f - the date is after the end.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="start"></param>
|
||||||
|
/// <param name="end"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static double MapRange(DateTime start, DateTime end, DateTime value)
|
||||||
|
{
|
||||||
|
return MapRange(new TimeSpan(start.Ticks).TotalSeconds,
|
||||||
|
new TimeSpan(end.Ticks).TotalSeconds,
|
||||||
|
0.0f, 1.0f, new TimeSpan(value.Ticks).TotalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the digit count for the given number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetNumberOfDigits(int number)
|
||||||
|
{
|
||||||
|
int output = number.ToString().Length;
|
||||||
|
if (number < 0)
|
||||||
|
output--;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the digit count for the given number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetNumberOfDigits(uint number)
|
||||||
|
{
|
||||||
|
return number.ToString().Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Takes a sequence of numbers:
|
||||||
|
/// 1, 3, 5, 6, 7, 8, 9, 10, 12
|
||||||
|
/// And calculates the continuous ranges:
|
||||||
|
/// (1, 1), (3, 3), (5, 10), (12, 12)
|
||||||
|
/// </summary>
|
||||||
|
public static IEnumerable<int[]> GetRanges(IEnumerable<int> numbers)
|
||||||
|
{
|
||||||
|
if (numbers == null)
|
||||||
|
throw new ArgumentNullException("numbers");
|
||||||
|
|
||||||
|
int[] currentRange = null;
|
||||||
|
|
||||||
|
foreach (int number in numbers.Order())
|
||||||
|
{
|
||||||
|
if (currentRange == null)
|
||||||
|
currentRange = new[] {number, number};
|
||||||
|
else if (currentRange[1] == number - 1)
|
||||||
|
currentRange = new[] {currentRange[0], number};
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yield return currentRange;
|
||||||
|
currentRange = new[] {number, number};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentRange != null)
|
||||||
|
yield return currentRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rounds the given number to the nearest item in the given sequence.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="nearest"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int RoundToNearest(int number, IEnumerable<int> nearest)
|
||||||
|
{
|
||||||
|
if (nearest == null)
|
||||||
|
throw new ArgumentNullException("nearest");
|
||||||
|
|
||||||
|
return nearest.Aggregate((x, y) => Math.Abs(x - number) < Math.Abs(y - number) ? x : y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a new, unique id given a sequence of existing ids.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="existingIds"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static int GetNewId(IEnumerable<int> existingIds)
|
||||||
|
{
|
||||||
|
if (existingIds == null)
|
||||||
|
throw new ArgumentNullException("existingIds");
|
||||||
|
|
||||||
|
IcdHashSet<int> existing = existingIds.ToHashSet();
|
||||||
|
return Enumerable.Range(1, int.MaxValue).First(i => !existing.Contains(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
232
ICD.Common/Utils/PathUtils.cs
Normal file
232
ICD.Common/Utils/PathUtils.cs
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Services;
|
||||||
|
using ICD.Common.Services.Logging;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
using ICD.Common.Utils.IO;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides util methods for working with file/directory paths.
|
||||||
|
/// </summary>
|
||||||
|
public static class PathUtils
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path to the root directory of the processor.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string RootPath { get { return IcdDirectory.GetDirectoryRoot("\\"); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path to the NVRAM directory.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string NvramPath { get { return Join(RootPath, "NVRAM"); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the absolute path to the configuration directory.
|
||||||
|
/// </summary>
|
||||||
|
/// <value></value>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ProgramConfigPath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string directoryName = string.Format("Program{0:D2}Config", ProgramUtils.ProgramNumber);
|
||||||
|
return Join(NvramPath, directoryName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the absolute path to the common configuration directory.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string CommonConfigPath { get { return Join(NvramPath, "CommonConfig"); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the absolute path to the common config library directory.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string CommonLibPath { get { return Join(CommonConfigPath, "Lib"); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the absolute path to the program config library directory.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ProgramLibPath { get { return Join(ProgramConfigPath, "Lib"); } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a path from the given path nodes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string Join(params string[] items)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return items.Skip(1).Aggregate(items.First(), IcdPath.Combine);
|
||||||
|
}
|
||||||
|
catch (ArgumentException e)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Failed to join path: " + StringUtils.ArrayFormat(items), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the full path for the given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetFullPath(string path)
|
||||||
|
{
|
||||||
|
return Join(IcdDirectory.GetApplicationDirectory(), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces the filename while leaving the directory and extension intact.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <param name="newName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ChangeFilenameWithoutExt(string path, string newName)
|
||||||
|
{
|
||||||
|
string dir = IcdPath.GetDirectoryName(path);
|
||||||
|
string ext = IcdPath.GetExtension(path);
|
||||||
|
|
||||||
|
return Join(dir, newName + ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the extension from the given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetPathWithoutExtension(string path)
|
||||||
|
{
|
||||||
|
string dir = IcdPath.GetDirectoryName(path);
|
||||||
|
string filename = IcdPath.GetFileNameWithoutExtension(path);
|
||||||
|
|
||||||
|
return Join(dir, filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recurses over the file paths at the given directory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<string> RecurseFilePaths(string path)
|
||||||
|
{
|
||||||
|
if (!IcdDirectory.Exists(path))
|
||||||
|
yield break;
|
||||||
|
|
||||||
|
Queue<string> queue = new Queue<string>();
|
||||||
|
queue.Enqueue(path);
|
||||||
|
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
path = queue.Dequeue();
|
||||||
|
|
||||||
|
// Get the subdirectories
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (string subDir in IcdDirectory.GetDirectories(path))
|
||||||
|
queue.Enqueue(subDir);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>().AddEntry(eSeverity.Error, e, e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the files
|
||||||
|
string[] files;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
files = IcdDirectory.GetFiles(path);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>().AddEntry(eSeverity.Error, e, e.Message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string filePath in files)
|
||||||
|
yield return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches the program config path, common config path, and application path to
|
||||||
|
/// find the first config that exists with the given local path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetDefaultConfigPath(params string[] localPath)
|
||||||
|
{
|
||||||
|
string local = Join(localPath);
|
||||||
|
|
||||||
|
// Program slot configuration
|
||||||
|
string programPath = Join(ProgramConfigPath, local);
|
||||||
|
if (PathExists(programPath))
|
||||||
|
return programPath;
|
||||||
|
|
||||||
|
// Common program configuration
|
||||||
|
string commonPath = Join(CommonConfigPath, local);
|
||||||
|
return PathExists(commonPath)
|
||||||
|
? commonPath
|
||||||
|
: Join(IcdDirectory.GetApplicationDirectory(), local); // Installation defaults
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Appends the local path to the program config path.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetProgramConfigPath(params string[] localPath)
|
||||||
|
{
|
||||||
|
string local = Join(localPath);
|
||||||
|
return Join(ProgramConfigPath, local);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches the application path, program config path and common config path to
|
||||||
|
/// find the first IR driver that exists with the given local path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetIrDriversPath(params string[] localPath)
|
||||||
|
{
|
||||||
|
return GetDefaultConfigPath(localPath.Prepend("IRDrivers").ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches the application path, program config path and common config path to
|
||||||
|
/// find the first SSL Driver that exists with the given local path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localPath"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string GetSslCertificatesPath(params string[] localPath)
|
||||||
|
{
|
||||||
|
return GetDefaultConfigPath(localPath.Prepend("SSLCertificates").ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the given path exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool PathExists(string path)
|
||||||
|
{
|
||||||
|
return IcdFile.Exists(path) || IcdDirectory.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
86
ICD.Common/Utils/PrettyPrint.cs
Normal file
86
ICD.Common/Utils/PrettyPrint.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Utils for printing various data types in human readable structures.
|
||||||
|
/// </summary>
|
||||||
|
public static class PrettyPrint
|
||||||
|
{
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void PrintLine<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
|
||||||
|
{
|
||||||
|
if (dictionary == null)
|
||||||
|
throw new ArgumentNullException("dictionary");
|
||||||
|
|
||||||
|
IcdConsole.PrintLine(ToString(dictionary));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static void PrintLine<T>(IEnumerable<T> sequence)
|
||||||
|
{
|
||||||
|
if (sequence == null)
|
||||||
|
throw new ArgumentNullException("sequence");
|
||||||
|
|
||||||
|
IcdConsole.PrintLine(ToString(sequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToString<TKey, TValue>(IDictionary<TKey, TValue> dictionary)
|
||||||
|
{
|
||||||
|
if (dictionary == null)
|
||||||
|
throw new ArgumentNullException("dictionary");
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.AppendLine("{");
|
||||||
|
|
||||||
|
foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
|
||||||
|
{
|
||||||
|
builder.Append('\t');
|
||||||
|
builder.Append(ToString(kvp.Key));
|
||||||
|
builder.Append(" : ");
|
||||||
|
builder.Append(ToString(kvp.Value));
|
||||||
|
builder.Append(',');
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append("}");
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToString<T>(IEnumerable<T> sequence)
|
||||||
|
{
|
||||||
|
if (sequence == null)
|
||||||
|
throw new ArgumentNullException("sequence");
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.AppendLine("[");
|
||||||
|
|
||||||
|
foreach (T item in sequence)
|
||||||
|
{
|
||||||
|
builder.Append('\t');
|
||||||
|
builder.Append(ToString(item));
|
||||||
|
builder.Append(',');
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append("]");
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToString<T>(T value)
|
||||||
|
{
|
||||||
|
// ReSharper disable once CompareNonConstrainedGenericWithNull
|
||||||
|
return StringUtils.ToRepresentation(value == null ? null : value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
178
ICD.Common/Utils/ProgramUtils.cs
Normal file
178
ICD.Common/Utils/ProgramUtils.cs
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Services;
|
||||||
|
using ICD.Common.Services.Logging;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class ProgramUtils
|
||||||
|
{
|
||||||
|
private const string APPLICATION_NAME_KEY = "Application Name";
|
||||||
|
private const string APPLICATION_NAME_SIMPL_KEY = "System Name";
|
||||||
|
private const string PROGRAM_FILE_KEY = "Program File";
|
||||||
|
|
||||||
|
private const string COMPILED_ON_KEY = "Compiled On";
|
||||||
|
private const string COMPILER_REVISION_KEY = "Compiler Revision";
|
||||||
|
private const string COMPILER_REVISION_SIMPL_KEY = "Compiler Rev";
|
||||||
|
|
||||||
|
private static Dictionary<string, string> s_ProgComments;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Lazy-load the prog-comments map.
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<string, string> ProgComments
|
||||||
|
{
|
||||||
|
get { return s_ProgComments ?? (s_ProgComments = ParseProgComments()); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the program number.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static uint ProgramNumber
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return InitialParametersClass.ApplicationNumber;
|
||||||
|
#else
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the program number in the format XX, eg slot 1 is 01.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ProgramNumberFormatted { get { return string.Format("{0:D2}", ProgramNumber); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the compile date of the program.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string CompiledDate { get { return ProgComments.GetDefault(COMPILED_ON_KEY, null); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the compiler revision version.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static Version CompilerRevision
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string output;
|
||||||
|
|
||||||
|
if (ProgComments.TryGetValue(COMPILER_REVISION_KEY, out output))
|
||||||
|
return new Version(output);
|
||||||
|
|
||||||
|
if (ProgComments.TryGetValue(COMPILER_REVISION_SIMPL_KEY, out output))
|
||||||
|
return new Version(output);
|
||||||
|
|
||||||
|
return new Version(0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the program dll.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ProgramFile { get { return ProgComments.GetDefault(PROGRAM_FILE_KEY, null); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the application.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ApplicationName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
string output;
|
||||||
|
|
||||||
|
if (ProgComments.TryGetValue(APPLICATION_NAME_KEY, out output))
|
||||||
|
return output;
|
||||||
|
|
||||||
|
ProgComments.TryGetValue(APPLICATION_NAME_SIMPL_KEY, out output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fakes program info, e.g. "Min Firmware Version : 1.009.0029"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void PrintProgramInfoLine(string name, object value)
|
||||||
|
{
|
||||||
|
name = (name ?? string.Empty).Trim();
|
||||||
|
|
||||||
|
switch (IcdEnvironment.RuntimeEnvironment)
|
||||||
|
{
|
||||||
|
case IcdEnvironment.eRuntimeEnvironment.SimplSharp:
|
||||||
|
int length = Math.Min(13, name.Length);
|
||||||
|
name = name.Substring(0, length).PadRight(13);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IcdEnvironment.eRuntimeEnvironment.SimplSharpPro:
|
||||||
|
int proLength = Math.Min(26 - 1, name.Length);
|
||||||
|
name = name.Substring(0, proLength).PadRight(26);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IcdEnvironment.eRuntimeEnvironment.Standard:
|
||||||
|
name += ' ';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
IcdConsole.PrintLine("{0}: {1}", name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the prog comments and pulls program information.
|
||||||
|
/// </summary>
|
||||||
|
private static Dictionary<string, string> ParseProgComments()
|
||||||
|
{
|
||||||
|
Dictionary<string, string> output = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string progInfo = string.Empty;
|
||||||
|
string command = string.Format("progcomments:{0}", ProgramNumber);
|
||||||
|
|
||||||
|
if (!IcdConsole.SendControlSystemCommand(command, ref progInfo))
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>().AddEntry(eSeverity.Warning, "Failed to parse prog comments");
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string line in progInfo.Split(new[] {"\n\r", "\r\n", "\n", "\r"}))
|
||||||
|
{
|
||||||
|
string[] pair = line.Split(':', 2).ToArray();
|
||||||
|
string key = pair[0].Trim();
|
||||||
|
string value = pair[1].Trim();
|
||||||
|
output[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>()
|
||||||
|
.AddEntry(eSeverity.Error, e, "Failed to parse prog comments - {0}", e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
232
ICD.Common/Utils/ReflectionUtils.cs
Normal file
232
ICD.Common/Utils/ReflectionUtils.cs
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.Reflection;
|
||||||
|
using Activator = Crestron.SimplSharp.Reflection.Activator;
|
||||||
|
#else
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.Extensions.DependencyModel;
|
||||||
|
using System.Runtime.Loader;
|
||||||
|
using Activator = System.Activator;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class ReflectionUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Instantiates the given type using the constructor matching the given values.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="values"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static object Instantiate(Type type, params object[] values)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CType[] types = values.Select(v => (CType)v.GetType())
|
||||||
|
.ToArray();
|
||||||
|
ConstructorInfo constructor = ((CType)type).GetConstructor(types);
|
||||||
|
#else
|
||||||
|
Type[] types = values.Select(v => v.GetType())
|
||||||
|
.ToArray();
|
||||||
|
ConstructorInfo constructor = type.GetTypeInfo().GetConstructor(types);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (constructor != null)
|
||||||
|
return constructor.Invoke(values);
|
||||||
|
|
||||||
|
string message = string.Format("Unable to find constructor for {0}", type.Name);
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the parameters match the method parameters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="method"></param>
|
||||||
|
/// <param name="parameters"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool MatchesMethodParameters(MethodBase method, IEnumerable<object> parameters)
|
||||||
|
{
|
||||||
|
if (method == null)
|
||||||
|
throw new ArgumentNullException("method");
|
||||||
|
|
||||||
|
if (parameters == null)
|
||||||
|
throw new ArgumentNullException("parameters");
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CType[] methodTypes
|
||||||
|
#else
|
||||||
|
Type[] methodTypes
|
||||||
|
#endif
|
||||||
|
= method.GetParameters().Select(p => p.ParameterType).ToArray();
|
||||||
|
return ParametersMatchTypes(methodTypes, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the if the parameter match the property parameter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="property"></param>
|
||||||
|
/// <param name="parameter"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool MatchesPropertyParameter(PropertyInfo property, object parameter)
|
||||||
|
{
|
||||||
|
if (property == null)
|
||||||
|
throw new ArgumentNullException("property");
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
CType propertyType
|
||||||
|
#else
|
||||||
|
Type propertyType
|
||||||
|
#endif
|
||||||
|
= property.PropertyType;
|
||||||
|
return ParametersMatchTypes(new[] {propertyType}, new[] {parameter});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the parameters array is compatible with the given property types array.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="types"></param>
|
||||||
|
/// <param name="parameters"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
#if SIMPLSHARP
|
||||||
|
private static bool ParametersMatchTypes(IEnumerable<CType> types, IEnumerable<object> parameters)
|
||||||
|
{
|
||||||
|
if (types == null)
|
||||||
|
throw new ArgumentNullException("types");
|
||||||
|
|
||||||
|
CType[] typesArray = types as CType[] ?? types.ToArray();
|
||||||
|
#else
|
||||||
|
private static bool ParametersMatchTypes(IEnumerable<Type> types, IEnumerable<object> parameters)
|
||||||
|
{
|
||||||
|
if (types == null)
|
||||||
|
throw new ArgumentNullException("types");
|
||||||
|
|
||||||
|
Type[] typesArray = types as Type[] ?? types.ToArray();
|
||||||
|
#endif
|
||||||
|
if (parameters == null)
|
||||||
|
throw new ArgumentNullException("parameters");
|
||||||
|
|
||||||
|
object[] parametersArray = parameters as object[] ?? parameters.ToArray();
|
||||||
|
|
||||||
|
if (parametersArray.Length != typesArray.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Compares each pair of items in the two arrays.
|
||||||
|
return !parametersArray.Where((t, index) => !ParameterMatchesType(typesArray[index], t)).Any();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the parameter can be assigned to the given type.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="parameter"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
#if SIMPLSHARP
|
||||||
|
private static bool ParameterMatchesType(CType type, object parameter)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
// Can the parameter be assigned a null value?
|
||||||
|
if (parameter == null)
|
||||||
|
return (type.IsClass || !type.IsValueType || Nullable.GetUnderlyingType(type) != null);
|
||||||
|
|
||||||
|
return type.IsInstanceOfType(parameter);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
private static bool ParameterMatchesType(Type type, object parameter)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
TypeInfo info = type.GetTypeInfo();
|
||||||
|
// Can the parameter be assigned a null value?
|
||||||
|
if (parameter == null)
|
||||||
|
return (info.IsClass || !info.IsValueType || Nullable.GetUnderlyingType(type) != null);
|
||||||
|
|
||||||
|
return info.IsInstanceOfType(parameter);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same as doing default(Type).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
#if SIMPLSHARP
|
||||||
|
public static object GetDefaultValue(CType type)
|
||||||
|
#else
|
||||||
|
public static object GetDefaultValue(Type type)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
throw new ArgumentNullException("type");
|
||||||
|
|
||||||
|
return type
|
||||||
|
#if !SIMPLSHARP
|
||||||
|
.GetTypeInfo()
|
||||||
|
#endif
|
||||||
|
.IsValueType
|
||||||
|
? Activator.CreateInstance(type)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of the given type, calling the default constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static T CreateInstance<T>()
|
||||||
|
where T : new()
|
||||||
|
{
|
||||||
|
return Activator.CreateInstance<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the custom attributes added to the given assembly.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="assembly"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<object> GetCustomAttributes<T>(Assembly assembly)
|
||||||
|
where T : Attribute
|
||||||
|
{
|
||||||
|
if (assembly == null)
|
||||||
|
throw new ArgumentNullException("assembly");
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return assembly.GetCustomAttributes(typeof(T), false);
|
||||||
|
#else
|
||||||
|
return assembly.GetCustomAttributes<T>();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the assembly at the given path.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Assembly LoadAssemblyFromPath(string path)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return Assembly.LoadFrom(path);
|
||||||
|
#else
|
||||||
|
string fileNameWithOutExtension = Path.GetFileNameWithoutExtension(path);
|
||||||
|
|
||||||
|
bool inCompileLibraries = DependencyContext.Default.CompileLibraries.Any(l => l.Name.Equals(fileNameWithOutExtension, StringComparison.OrdinalIgnoreCase));
|
||||||
|
bool inRuntimeLibraries = DependencyContext.Default.RuntimeLibraries.Any(l => l.Name.Equals(fileNameWithOutExtension, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
return inCompileLibraries || inRuntimeLibraries
|
||||||
|
? Assembly.Load(new AssemblyName(fileNameWithOutExtension))
|
||||||
|
: AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
ICD.Common/Utils/SafeCriticalSection.SimplSharp.cs
Normal file
65
ICD.Common/Utils/SafeCriticalSection.SimplSharp.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// CCriticalSection tends to get disposed before the parent is done with it.
|
||||||
|
/// This class is an attempt to gracefully handle the ObjectDisposedExceptions we see on
|
||||||
|
/// program termination, ocassionally causing the program to restart instead of stop.
|
||||||
|
/// </summary>
|
||||||
|
public sealed partial class SafeCriticalSection
|
||||||
|
{
|
||||||
|
private readonly CCriticalSection m_CriticalSection;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public SafeCriticalSection()
|
||||||
|
{
|
||||||
|
m_CriticalSection = new CCriticalSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Block until ownership of the critical section can be obtained.
|
||||||
|
/// </summary>
|
||||||
|
public void Enter()
|
||||||
|
{
|
||||||
|
if (m_CriticalSection == null || m_CriticalSection.Disposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_CriticalSection.Enter();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Release ownership of the critical section.
|
||||||
|
/// </summary>
|
||||||
|
public void Leave()
|
||||||
|
{
|
||||||
|
if (m_CriticalSection == null || m_CriticalSection.Disposed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_CriticalSection.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempt to enter the critical section without blocking.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// True, calling thread has ownership of the critical section; otherwise, false.
|
||||||
|
/// </returns>
|
||||||
|
public bool TryEnter()
|
||||||
|
{
|
||||||
|
if (m_CriticalSection == null || m_CriticalSection.Disposed)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return m_CriticalSection.TryEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
51
ICD.Common/Utils/SafeCriticalSection.Standard.cs
Normal file
51
ICD.Common/Utils/SafeCriticalSection.Standard.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
#if !SIMPLSHARP
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public sealed partial class SafeCriticalSection
|
||||||
|
{
|
||||||
|
private readonly Mutex m_Mutex;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public SafeCriticalSection()
|
||||||
|
{
|
||||||
|
m_Mutex = new Mutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Block until ownership of the critical section can be obtained.
|
||||||
|
/// </summary>
|
||||||
|
public void Enter()
|
||||||
|
{
|
||||||
|
m_Mutex.WaitOne();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Release ownership of the critical section.
|
||||||
|
/// </summary>
|
||||||
|
public void Leave()
|
||||||
|
{
|
||||||
|
m_Mutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempt to enter the critical section without blocking.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// True, calling thread has ownership of the critical section; otherwise, false.
|
||||||
|
/// </returns>
|
||||||
|
public bool TryEnter()
|
||||||
|
{
|
||||||
|
return m_Mutex.WaitOne(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
49
ICD.Common/Utils/SafeCriticalSection.cs
Normal file
49
ICD.Common/Utils/SafeCriticalSection.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public sealed partial class SafeCriticalSection
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Enters the critical section, executes the callback and leaves the section.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
public void Execute(Action callback)
|
||||||
|
{
|
||||||
|
if (callback == null)
|
||||||
|
throw new ArgumentNullException("callback");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Enter();
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enters the critical section, executes the callback and leaves the section.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public T Execute<T>(Func<T> callback)
|
||||||
|
{
|
||||||
|
if (callback == null)
|
||||||
|
throw new ArgumentNullException("callback");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Enter();
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Leave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
ICD.Common/Utils/SafeMutex.cs
Normal file
74
ICD.Common/Utils/SafeMutex.cs
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
#else
|
||||||
|
using System.Threading;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Like the CCriticalSection, the CMutex tends to get disposed before the parent is
|
||||||
|
/// done with it. This class is an attempt to gracefully handle the ObjectDisposedExceptions
|
||||||
|
/// we see on program termination, ocassionally causing the program to restart instead of stop.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SafeMutex
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
private readonly CMutex m_Mutex;
|
||||||
|
#else
|
||||||
|
private readonly Mutex m_Mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public SafeMutex()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Mutex = new CMutex();
|
||||||
|
#else
|
||||||
|
m_Mutex = new Mutex();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Waits the given number of milliseconds to aquire the mutex.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeout"></param>
|
||||||
|
/// <returns>True if the mutex was aquired.</returns>
|
||||||
|
public bool WaitForMutex(int timeout)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return m_Mutex.WaitForMutex(timeout);
|
||||||
|
#else
|
||||||
|
return m_Mutex.WaitOne(timeout);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the mutex.
|
||||||
|
/// </summary>
|
||||||
|
public void ReleaseMutex()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Mutex.ReleaseMutex();
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
477
ICD.Common/Utils/StringUtils.cs
Normal file
477
ICD.Common/Utils/StringUtils.cs
Normal file
@@ -0,0 +1,477 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class StringUtils
|
||||||
|
{
|
||||||
|
private const ushort ASCII_READABLE_START = 32;
|
||||||
|
private const ushort ASCII_READABLE_END = 126;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number as a string in the format "\\x00"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="numeric"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToHexLiteral(int numeric)
|
||||||
|
{
|
||||||
|
return string.Format("\\x{0:X2}", numeric);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the character as a string in the format "\\x00"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="c"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToHexLiteral(char c)
|
||||||
|
{
|
||||||
|
return ToHexLiteral(Convert.ToInt32(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string as a string in the format "\\x00\\x00..."
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToHexLiteral(string input)
|
||||||
|
{
|
||||||
|
string[] strings = input.Select(c => ToHexLiteral(c)).ToArray();
|
||||||
|
return string.Join("", strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a character in the string format "\\x00" to char.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="character"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static char FromHexLiteralCharacter(string character)
|
||||||
|
{
|
||||||
|
string hexValue = character.Substring(2);
|
||||||
|
return (char)Convert.ToByte(hexValue, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a string in the format "\\x00\\x00..." to hex representation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string FromHexLiteral(string data)
|
||||||
|
{
|
||||||
|
return string.Join("", data.Split(4).Select(s => FromHexLiteralCharacter(s).ToString()).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the char to a human readable character, otherwise returns a hex string
|
||||||
|
/// in the format "\x00"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="c"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToMixedReadableHexLiteral(char c)
|
||||||
|
{
|
||||||
|
int numeric = Convert.ToInt32(c);
|
||||||
|
|
||||||
|
if (numeric >= ASCII_READABLE_START && numeric <= ASCII_READABLE_END)
|
||||||
|
return c.ToString();
|
||||||
|
|
||||||
|
return ToHexLiteral(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the input string to a string in the format "\x00\x00" with human
|
||||||
|
/// readable characters where possible e.g. "Hello World!x\0D"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToMixedReadableHexLiteral(string input)
|
||||||
|
{
|
||||||
|
string[] strings = input.Select(c => ToMixedReadableHexLiteral(c)).ToArray();
|
||||||
|
return string.Join("", strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts bytes to an ascii string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToString(IEnumerable<byte> bytes)
|
||||||
|
{
|
||||||
|
byte[] cast = bytes as byte[] ?? bytes.ToArray();
|
||||||
|
return Encoding.UTF8.GetString(cast, 0, cast.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts bytes to an ascii string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes"></param>
|
||||||
|
/// <param name="length"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ToString(IEnumerable<byte> bytes, int length)
|
||||||
|
{
|
||||||
|
byte[] cast = bytes as byte[] ?? bytes.ToArray();
|
||||||
|
return Encoding.UTF8.GetString(cast, 0, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts an ascii string to bytes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static byte[] ToBytes(string input)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetBytes(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to parse the string as an integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool TryParse(string value, out int result)
|
||||||
|
{
|
||||||
|
return TryConvert(Convert.ToInt32, value, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to parse the string as an unsigned integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool TryParse(string value, out uint result)
|
||||||
|
{
|
||||||
|
return TryConvert(Convert.ToUInt32, value, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to parse the string as a float.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool TryParse(string value, out float result)
|
||||||
|
{
|
||||||
|
return TryConvert(Convert.ToSingle, value, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to parse the string as a bool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool TryParse(string value, out bool result)
|
||||||
|
{
|
||||||
|
return TryConvert(Convert.ToBoolean, value, out result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempts to parse the string via the given conversion function.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="convertFunc"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <param name="result"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static bool TryConvert<T>(Func<string, T> convertFunc, string value, out T result)
|
||||||
|
{
|
||||||
|
if (convertFunc == null)
|
||||||
|
throw new ArgumentNullException("convertFunc");
|
||||||
|
|
||||||
|
result = default(T);
|
||||||
|
bool retVal = false;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = convertFunc(value);
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
catch (InvalidCastException)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the object.ToString() with spaces before capital letters.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string NiceName(object obj)
|
||||||
|
{
|
||||||
|
return NiceName(obj.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts spaces before capital letters.
|
||||||
|
///
|
||||||
|
/// http://stackoverflow.com/questions/4488969/split-a-string-by-capital-letters
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string NiceName(string name)
|
||||||
|
{
|
||||||
|
Regex regex = new Regex(@"
|
||||||
|
(?<=[A-Z])(?=[A-Z][a-z]) |
|
||||||
|
(?<=[^A-Z])(?=[A-Z]) |
|
||||||
|
(?<=[A-Za-z])(?=[^A-Za-z])", RegexOptions.IgnorePatternWhitespace);
|
||||||
|
|
||||||
|
return regex.Replace(name, " ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// String.Format({0:######}) is unreliable if the number starts with a 0.
|
||||||
|
/// This method fills an input pattern #### from right to left with characters
|
||||||
|
/// from the number.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="phoneFormat"></param>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string SafeNumericFormat(string phoneFormat, string number)
|
||||||
|
{
|
||||||
|
phoneFormat = Reverse(phoneFormat);
|
||||||
|
number = Reverse(number);
|
||||||
|
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
foreach (char c in phoneFormat)
|
||||||
|
{
|
||||||
|
if (index >= number.Length)
|
||||||
|
{
|
||||||
|
if (c == '#')
|
||||||
|
break;
|
||||||
|
|
||||||
|
builder.Append(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '#')
|
||||||
|
{
|
||||||
|
builder.Append(number[index]);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
builder.Append(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Reverse(builder.ToString()).TrimStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reverses the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string Reverse(string input)
|
||||||
|
{
|
||||||
|
char[] charArray = input.ToCharArray();
|
||||||
|
Array.Reverse(charArray);
|
||||||
|
return new string(charArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Repeats the char the given number of times.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string Repeat(char input, int count)
|
||||||
|
{
|
||||||
|
return Repeat(input.ToString(), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Repeats the string the given number of times.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <param name="count"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string Repeat(string input, int count)
|
||||||
|
{
|
||||||
|
return count == 0 ? string.Empty : new StringBuilder().Insert(0, input, count).ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns each item.ToString() in the format "[item1, item2, item3...]"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ArrayFormat<T>(IEnumerable<T> items)
|
||||||
|
{
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
return string.Format("[{0}]", string.Join(", ", items.Select(i => i.ToString()).ToArray()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given a sequence of numbers, generates a human readable list of numeric ranges.
|
||||||
|
/// E.g. [1, 2, 3, 5, 6] becomes "[1-3, 5-6]".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ArrayRangeFormat(IEnumerable<int> items)
|
||||||
|
{
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
string[] ranges = MathUtils.GetRanges(items)
|
||||||
|
.Select(r => r[0] == r[1]
|
||||||
|
? r[0].ToString()
|
||||||
|
: string.Format("{0}-{1}", r[0], r[1]))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return ArrayFormat(ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Given a sequence of numbers, generates a human readable list of numeric ranges.
|
||||||
|
/// E.g. [1, 2, 3, 5, 6] becomes "[1-3, 5-6]".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string ArrayRangeFormat(IEnumerable<ushort> items)
|
||||||
|
{
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
return ArrayRangeFormat(items.Select(i => (int)i));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a pair of numbers in the format [a - b]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string RangeFormat(object a, object b)
|
||||||
|
{
|
||||||
|
return string.Format("[{0} - {1}]", a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Capitalizes the first character of the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string UppercaseFirst(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
return input;
|
||||||
|
|
||||||
|
return char.ToUpper(input[0]) + input.Substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats an IPID to "0xFF"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToIpIdString(byte ipid)
|
||||||
|
{
|
||||||
|
return string.Format("0x{0:X2}", ipid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Formats "0xFF" to an IPID.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static byte FromIpIdString(string value)
|
||||||
|
{
|
||||||
|
value = value.Replace("0x", "");
|
||||||
|
return Convert.ToByte(value, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all whitespace from the string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string RemoveWhitespace(string text)
|
||||||
|
{
|
||||||
|
return text == null ? null : new string(text.Where(c => !Char.IsWhiteSpace(c)).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the password as a series of *s
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="password"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string PasswordFormat(string password)
|
||||||
|
{
|
||||||
|
return password == null ? null : Repeat('*', password.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pads the given string with quotations for readable type clarity. If the string is null, returns "NULL".
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToRepresentation(string value)
|
||||||
|
{
|
||||||
|
return value == null ? "NULL" : string.Format("\"{0}\"", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the items in the format "x, y, and z"
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="items"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string SerialComma(IEnumerable<string> items)
|
||||||
|
{
|
||||||
|
if (items == null)
|
||||||
|
throw new ArgumentNullException("items");
|
||||||
|
|
||||||
|
string previous = null;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
foreach (string item in items)
|
||||||
|
{
|
||||||
|
if (previous != null)
|
||||||
|
builder.AppendFormat("{0}, ", previous);
|
||||||
|
previous = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previous != null)
|
||||||
|
{
|
||||||
|
if (builder.Length > 0)
|
||||||
|
builder.AppendFormat("and {0}", previous);
|
||||||
|
else
|
||||||
|
builder.Append(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
193
ICD.Common/Utils/TableBuilder.cs
Normal file
193
ICD.Common/Utils/TableBuilder.cs
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// TableBuilder provides a way to format a collection of strings to a table.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class TableBuilder
|
||||||
|
{
|
||||||
|
private const char HORIZONTAL = '-';
|
||||||
|
private const char VERTICAL = '|';
|
||||||
|
|
||||||
|
private readonly List<string[]> m_Rows;
|
||||||
|
private readonly SafeCriticalSection m_RowsSection;
|
||||||
|
private readonly string[] m_Columns;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the columns.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public string[] Columns { get { return m_Columns; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of columns.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public int ColumnsCount { get { return m_Columns.Length; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="columns"></param>
|
||||||
|
public TableBuilder(params string[] columns)
|
||||||
|
{
|
||||||
|
m_Rows = new List<string[]>();
|
||||||
|
m_RowsSection = new SafeCriticalSection();
|
||||||
|
m_Columns = columns;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clears all of the rows.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public void ClearRows()
|
||||||
|
{
|
||||||
|
m_RowsSection.Execute(() => m_Rows.Clear());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calls ToString() for each item and adds the row to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="row"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public void AddRow(params object[] row)
|
||||||
|
{
|
||||||
|
string[] stringRow = row.Select(o => string.Format("{0}", o))
|
||||||
|
.ToArray();
|
||||||
|
AddRow(stringRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds the row to the builder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="row"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public void AddRow(params string[] row)
|
||||||
|
{
|
||||||
|
if (row != null && row.Length != m_Columns.Length)
|
||||||
|
throw new ArgumentException("Row must match columns length.");
|
||||||
|
|
||||||
|
m_RowsSection.Execute(() => m_Rows.Add(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds an empty row to the builder.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public void AddEmptyRow()
|
||||||
|
{
|
||||||
|
AddRow(new string[m_Columns.Length]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public void AddSeparator()
|
||||||
|
{
|
||||||
|
AddRow(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[PublicAPI]
|
||||||
|
public void AddHeader(params string[] row)
|
||||||
|
{
|
||||||
|
if (row.Length != m_Columns.Length)
|
||||||
|
throw new ArgumentException("Row must match columns length.");
|
||||||
|
|
||||||
|
AddSeparator();
|
||||||
|
AddRow(row);
|
||||||
|
AddSeparator();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the output string.
|
||||||
|
/// </summary>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
m_RowsSection.Enter();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
int[] columnWidths = GetColumnWidths();
|
||||||
|
|
||||||
|
AppendRow(sb, m_Columns, columnWidths);
|
||||||
|
AppendSeparator(sb, columnWidths);
|
||||||
|
|
||||||
|
foreach (string[] row in m_Rows)
|
||||||
|
{
|
||||||
|
if (row == null)
|
||||||
|
AppendSeparator(sb, columnWidths);
|
||||||
|
else
|
||||||
|
AppendRow(sb, row, columnWidths);
|
||||||
|
}
|
||||||
|
|
||||||
|
AppendSeparator(sb, columnWidths);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
m_RowsSection.Leave();
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private int[] GetColumnWidths()
|
||||||
|
{
|
||||||
|
int[] columnWidths = new int[m_Columns.Length];
|
||||||
|
for (int index = 0; index < m_Columns.Length; index++)
|
||||||
|
columnWidths[index] = GetColumnWidth(index);
|
||||||
|
|
||||||
|
return columnWidths;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int GetColumnWidth(int index)
|
||||||
|
{
|
||||||
|
int titleLength = m_Columns[index].Length + 1;
|
||||||
|
if (m_Rows.Count == 0)
|
||||||
|
return titleLength;
|
||||||
|
|
||||||
|
int maxColumnWidth = m_Rows.Except((string[])null)
|
||||||
|
.Max(x => x[index] != null ? x[index].Length : 0) + 1;
|
||||||
|
|
||||||
|
return (titleLength > maxColumnWidth) ? titleLength : maxColumnWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AppendRow(StringBuilder builder, IList<string> row, IList<int> columnWidths)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < row.Count; index++)
|
||||||
|
{
|
||||||
|
if (index > 0)
|
||||||
|
builder.Append(' ');
|
||||||
|
|
||||||
|
string value = row[index] ?? string.Empty;
|
||||||
|
builder.Append(value.PadRight(columnWidths[index]));
|
||||||
|
|
||||||
|
if (index < row.Count - 1)
|
||||||
|
builder.Append(VERTICAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AppendSeparator(StringBuilder sb, ICollection<int> columnWidths)
|
||||||
|
{
|
||||||
|
int length = columnWidths.Sum() + (columnWidths.Count - 1) * 2;
|
||||||
|
string line = new string(HORIZONTAL, length);
|
||||||
|
|
||||||
|
sb.AppendLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
67
ICD.Common/Utils/Timers/IcdStopwatch.cs
Normal file
67
ICD.Common/Utils/Timers/IcdStopwatch.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using System.Diagnostics;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Timers
|
||||||
|
{
|
||||||
|
public sealed class IcdStopwatch
|
||||||
|
{
|
||||||
|
private readonly Stopwatch m_Stopwatch;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
public long ElapsedMilliseconds { get { return m_Stopwatch.ElapsedMilliseconds; } }
|
||||||
|
|
||||||
|
public bool IsRunning { get { return m_Stopwatch.IsRunning; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public IcdStopwatch()
|
||||||
|
: this(new Stopwatch())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stopwatch"></param>
|
||||||
|
public IcdStopwatch(Stopwatch stopwatch)
|
||||||
|
{
|
||||||
|
m_Stopwatch = stopwatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IcdStopwatch StartNew()
|
||||||
|
{
|
||||||
|
return new IcdStopwatch(Stopwatch.StartNew());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
m_Stopwatch.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
m_Stopwatch.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
m_Stopwatch.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
166
ICD.Common/Utils/Timers/IcdTimer.cs
Normal file
166
ICD.Common/Utils/Timers/IcdTimer.cs
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.EventArguments;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Timers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IcdTimer provides events for time increments as well as timer elapsed.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class IcdTimer : IDisposable
|
||||||
|
{
|
||||||
|
private const long DEFAULT_HEARTBEAT_INTERVAL = 500;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the timer is restarted/stopped.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<BoolEventArgs> OnIsRunningChanged;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the timer has elapsed.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler OnElapsed;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the milliseconds count changes. Useful for updating UIs.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler OnMillisecondsChanged;
|
||||||
|
|
||||||
|
private readonly IcdStopwatch m_Stopwatch;
|
||||||
|
|
||||||
|
private readonly SafeTimer m_Heartbeat;
|
||||||
|
private long m_LastHeartbeatMilliseconds;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the timer is stopped.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsStopped { get { return !m_Stopwatch.IsRunning; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the timer is running.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsRunning { get { return m_Stopwatch.IsRunning; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the timer has elapsed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsElapsed { get { return Milliseconds > Length; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the number of milliseconds that have passed since the timer started.
|
||||||
|
/// </summary>
|
||||||
|
public long Milliseconds { get { return m_Stopwatch.ElapsedMilliseconds; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of milliseconds before the timer is elapsed.
|
||||||
|
/// </summary>
|
||||||
|
public long Length { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the remaining number of milliseconds until the timer is elapsed. Returns 0 if the timer has elapsed.
|
||||||
|
/// </summary>
|
||||||
|
public long Remaining { get { return Math.Max(Length - Milliseconds, 0); } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the remaining number of seconds until the timer is elapsed. Returns 0 if the timer has elapsed.
|
||||||
|
/// </summary>
|
||||||
|
public long RemainingSeconds { get { return (long)Math.Ceiling(Remaining / 1000.0f); } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public IcdTimer()
|
||||||
|
: this(DEFAULT_HEARTBEAT_INTERVAL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an IcdTimer with the specified heartbeat interval for the internal timer.
|
||||||
|
/// This allows a finer resolution for timing than the default 500ms.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="heartbeatInterval"></param>
|
||||||
|
public IcdTimer(long heartbeatInterval)
|
||||||
|
{
|
||||||
|
m_Heartbeat = new SafeTimer(HeartbeatCallback, heartbeatInterval, heartbeatInterval);
|
||||||
|
m_Stopwatch = new IcdStopwatch();
|
||||||
|
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Release resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
OnIsRunningChanged = null;
|
||||||
|
OnElapsed = null;
|
||||||
|
OnMillisecondsChanged = null;
|
||||||
|
|
||||||
|
m_Stopwatch.Stop();
|
||||||
|
m_Heartbeat.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Restarts the timer.
|
||||||
|
/// </summary>
|
||||||
|
public void Restart(long length)
|
||||||
|
{
|
||||||
|
Length = length;
|
||||||
|
|
||||||
|
m_Stopwatch.Reset();
|
||||||
|
m_Stopwatch.Start();
|
||||||
|
|
||||||
|
RaiseOnIsRunningChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops the timer.
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
m_Stopwatch.Stop();
|
||||||
|
|
||||||
|
RaiseOnIsRunningChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the heartbeat timer elapses.
|
||||||
|
/// </summary>
|
||||||
|
private void HeartbeatCallback()
|
||||||
|
{
|
||||||
|
if (Milliseconds == m_LastHeartbeatMilliseconds)
|
||||||
|
return;
|
||||||
|
|
||||||
|
OnMillisecondsChanged.Raise(this);
|
||||||
|
|
||||||
|
if (m_LastHeartbeatMilliseconds <= Length && IsElapsed)
|
||||||
|
OnElapsed.Raise(this);
|
||||||
|
|
||||||
|
m_LastHeartbeatMilliseconds = Milliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raises the OnIsRunningChanged event.
|
||||||
|
/// </summary>
|
||||||
|
private void RaiseOnIsRunningChanged()
|
||||||
|
{
|
||||||
|
OnIsRunningChanged.Raise(this, new BoolEventArgs(IsRunning));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
100
ICD.Common/Utils/Timers/Repeater.cs
Normal file
100
ICD.Common/Utils/Timers/Repeater.cs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
using System;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
using ICD.Common.Utils.Extensions;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Timers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Simple class for implementing things like volume ramps, where a button has an
|
||||||
|
/// immediate effect, and then begins ramping after a brief delay.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public sealed class Repeater : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on the initial repeat.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public event EventHandler OnInitialRepeat;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raised on each subsequent repeat.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public event EventHandler OnRepeat;
|
||||||
|
|
||||||
|
private readonly SafeTimer m_RepeatTimer;
|
||||||
|
|
||||||
|
private readonly long m_BeforeRepeat;
|
||||||
|
private readonly long m_BetweenRepeat;
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="beforeRepeat">The delay before the second increment</param>
|
||||||
|
/// <param name="betweenRepeat">The delay between each subsequent repeat</param>
|
||||||
|
public Repeater(long beforeRepeat, long betweenRepeat)
|
||||||
|
{
|
||||||
|
m_RepeatTimer = SafeTimer.Stopped(RepeatCallback);
|
||||||
|
|
||||||
|
m_BeforeRepeat = beforeRepeat;
|
||||||
|
m_BetweenRepeat = betweenRepeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Destructor.
|
||||||
|
/// </summary>
|
||||||
|
~Repeater()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Release resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_RepeatTimer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Begin repeating.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
OnInitialRepeat.Raise(this);
|
||||||
|
|
||||||
|
m_RepeatTimer.Reset(m_BeforeRepeat, m_BetweenRepeat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop repeating volume.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
m_RepeatTimer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called for every repeat.
|
||||||
|
/// </summary>
|
||||||
|
private void RepeatCallback()
|
||||||
|
{
|
||||||
|
OnRepeat.Raise(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
180
ICD.Common/Utils/Timers/SafeTimer.cs
Normal file
180
ICD.Common/Utils/Timers/SafeTimer.cs
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
#else
|
||||||
|
using System.Threading;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.Services;
|
||||||
|
using ICD.Common.Services.Logging;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Timers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// SafeTimer wraps CTimer to hide some of the jank.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class SafeTimer : IStateDisposable
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
private readonly CTimer m_Timer;
|
||||||
|
#else
|
||||||
|
private readonly Timer m_Timer;
|
||||||
|
private int m_DueTime, m_RepeatPeriod;
|
||||||
|
#endif
|
||||||
|
private readonly Action m_Callback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this instance has been disposed.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDisposed { get; private set; }
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a timer that is called every repeatPeriod in milliseconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="repeatPeriod"></param>
|
||||||
|
public SafeTimer(Action callback, long repeatPeriod)
|
||||||
|
: this(callback, 0, repeatPeriod)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a timer that is called in dueTime milliseconds and then every
|
||||||
|
/// repeatPeriod milliseconds afterwards.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <param name="dueTime"></param>
|
||||||
|
/// <param name="repeatPeriod"></param>
|
||||||
|
public SafeTimer(Action callback, long dueTime, long repeatPeriod)
|
||||||
|
{
|
||||||
|
m_Callback = callback;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Timer = new CTimer(SafeCallback, null, dueTime, repeatPeriod);
|
||||||
|
#else
|
||||||
|
m_DueTime = (int)dueTime;
|
||||||
|
m_RepeatPeriod = (int)repeatPeriod;
|
||||||
|
m_Timer = new Timer(SafeCallback, null, m_DueTime, m_RepeatPeriod);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a timer that is initially stopped.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static SafeTimer Stopped(Action callback)
|
||||||
|
{
|
||||||
|
SafeTimer output = new SafeTimer(callback, 0);
|
||||||
|
output.Stop();
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Release resources.
|
||||||
|
/// </summary>
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
m_Timer.Dispose();
|
||||||
|
IsDisposed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stops the timer.
|
||||||
|
/// </summary>
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Timer.Stop();
|
||||||
|
#else
|
||||||
|
m_Timer.Change(Timeout.Infinite, Timeout.Infinite);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Immediately calls the callback and resets the timer
|
||||||
|
/// </summary>
|
||||||
|
public void Trigger()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Timer.Reset();
|
||||||
|
#else
|
||||||
|
m_Timer.Change(0, m_RepeatPeriod);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback is called after the dueTime milliseconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dueTime"></param>
|
||||||
|
public void Reset(long dueTime)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Timer.Reset(dueTime);
|
||||||
|
#else
|
||||||
|
m_DueTime = (int)dueTime;
|
||||||
|
m_Timer.Change(m_DueTime, m_RepeatPeriod);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback is called after the dueTime milliseconds and every repeatPeriod milliseconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dueTime"></param>
|
||||||
|
/// <param name="repeatPeriod"></param>
|
||||||
|
public void Reset(long dueTime, long repeatPeriod)
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Timer.Reset(dueTime, repeatPeriod);
|
||||||
|
#else
|
||||||
|
m_DueTime = (int)dueTime;
|
||||||
|
m_RepeatPeriod = (int)repeatPeriod;
|
||||||
|
m_Timer.Change(m_DueTime, m_RepeatPeriod);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Only executes the callback if the timer has not been disposed.
|
||||||
|
/// Catches any exceptions and logs them.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="unused"></param>
|
||||||
|
private void SafeCallback(object unused)
|
||||||
|
{
|
||||||
|
// Essentially the meat of this class. There's some weirdness with the garbage collector where
|
||||||
|
// the reference to the timer will be cleared, and eventually the CTimer will call the callback
|
||||||
|
// despite being stopped/disposed.
|
||||||
|
if (m_Timer == null
|
||||||
|
#if SIMPLSHARP
|
||||||
|
|| m_Timer.Disposed
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Callback();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LogException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogException(Exception e)
|
||||||
|
{
|
||||||
|
string message = string.Format("{0} failed to execute callback - {1}", GetType().Name, e.Message);
|
||||||
|
ServiceProvider.TryGetService<ILoggerService>().AddEntry(eSeverity.Error, e, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
56
ICD.Common/Utils/TryUtils.cs
Normal file
56
ICD.Common/Utils/TryUtils.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils
|
||||||
|
{
|
||||||
|
public static class TryUtils
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TResult">return type</typeparam>
|
||||||
|
/// <param name="function"></param>
|
||||||
|
/// <param name="val"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool Try<TResult>(Func<TResult> function, out TResult val)
|
||||||
|
{
|
||||||
|
if (function == null)
|
||||||
|
throw new ArgumentNullException("function");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
val = function();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
val = default(TResult);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Try<T1, TResult>(Func<T1, TResult> function, T1 param1, out TResult val)
|
||||||
|
{
|
||||||
|
if (function == null)
|
||||||
|
throw new ArgumentNullException("function");
|
||||||
|
|
||||||
|
return Try(() => function(param1), out val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Try<T1, T2, TResult>(Func<T1, T2, TResult> function, T1 param1, T2 param2, out TResult val)
|
||||||
|
{
|
||||||
|
if (function == null)
|
||||||
|
throw new ArgumentNullException("function");
|
||||||
|
|
||||||
|
return Try(() => function(param1, param2), out val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Try<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function, T1 param1, T2 param2, T3 param3,
|
||||||
|
out TResult val)
|
||||||
|
{
|
||||||
|
if (function == null)
|
||||||
|
throw new ArgumentNullException("function");
|
||||||
|
|
||||||
|
return Try(() => function(param1, param2, param3), out val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
ICD.Common/Utils/Xml/IcdXmlAttribute.cs
Normal file
75
ICD.Common/Utils/Xml/IcdXmlAttribute.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IcdXmlAttribute represents an attribute="value" pair from xml.
|
||||||
|
/// </summary>
|
||||||
|
public struct IcdXmlAttribute
|
||||||
|
{
|
||||||
|
private readonly string m_Name;
|
||||||
|
private readonly string m_Value;
|
||||||
|
|
||||||
|
public string Name { get { return m_Name; } }
|
||||||
|
public string Value { get { return m_Value; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <param name="value"></param>
|
||||||
|
public IcdXmlAttribute(string name, string value)
|
||||||
|
{
|
||||||
|
m_Name = name;
|
||||||
|
m_Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementing default equality.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a1"></param>
|
||||||
|
/// <param name="a2"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator ==(IcdXmlAttribute a1, IcdXmlAttribute a2)
|
||||||
|
{
|
||||||
|
return a1.Equals(a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementing default inequality.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a1"></param>
|
||||||
|
/// <param name="a2"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool operator !=(IcdXmlAttribute a1, IcdXmlAttribute a2)
|
||||||
|
{
|
||||||
|
return !(a1 == a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if this instance is equal to the given object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override bool Equals(object other)
|
||||||
|
{
|
||||||
|
if (other == null || GetType() != other.GetType())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return GetHashCode() == ((IcdXmlAttribute)other).GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the hashcode for this instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked
|
||||||
|
{
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 23 + (m_Name == null ? 0 : m_Name.GetHashCode());
|
||||||
|
hash = hash * 23 + (m_Value == null ? 0 : m_Value.GetHashCode());
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
101
ICD.Common/Utils/Xml/IcdXmlConvert.cs
Normal file
101
ICD.Common/Utils/Xml/IcdXmlConvert.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronXml;
|
||||||
|
#else
|
||||||
|
using System.Xml;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public static class IcdXmlConvert
|
||||||
|
{
|
||||||
|
public static string ToString(int value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(bool value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(float value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(double value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(decimal value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(long value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(ulong value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(Guid value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(TimeSpan value)
|
||||||
|
{
|
||||||
|
return XmlConvert.ToString(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(int? value)
|
||||||
|
{
|
||||||
|
return value.HasValue ? ToString(value.Value) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(object child)
|
||||||
|
{
|
||||||
|
if (child == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (child is bool)
|
||||||
|
return ToString((bool)child);
|
||||||
|
if (child is byte)
|
||||||
|
return ToString((byte)child);
|
||||||
|
if (child is decimal)
|
||||||
|
return ToString((decimal)child);
|
||||||
|
if (child is char)
|
||||||
|
return ToString((char)child);
|
||||||
|
if (child is double)
|
||||||
|
return ToString((double)child);
|
||||||
|
if (child is Guid)
|
||||||
|
return ToString((Guid)child);
|
||||||
|
if (child is float)
|
||||||
|
return ToString((float)child);
|
||||||
|
if (child is int)
|
||||||
|
return ToString((int)child);
|
||||||
|
if (child is long)
|
||||||
|
return ToString((long)child);
|
||||||
|
if (child is sbyte)
|
||||||
|
return ToString((sbyte)child);
|
||||||
|
if (child is short)
|
||||||
|
return ToString((short)child);
|
||||||
|
if (child is TimeSpan)
|
||||||
|
return ToString((TimeSpan)child);
|
||||||
|
if (child is uint)
|
||||||
|
return ToString((uint)child);
|
||||||
|
if (child is ulong)
|
||||||
|
return ToString((ulong)child);
|
||||||
|
if (child is ushort)
|
||||||
|
return ToString((ushort)child);
|
||||||
|
|
||||||
|
return child.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
ICD.Common/Utils/Xml/IcdXmlDocument.cs
Normal file
40
ICD.Common/Utils/Xml/IcdXmlDocument.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.CrestronXml;
|
||||||
|
|
||||||
|
#else
|
||||||
|
using System.Xml;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public sealed class IcdXmlDocument
|
||||||
|
{
|
||||||
|
private readonly XmlDocument m_Document;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
public IcdXmlDocument()
|
||||||
|
{
|
||||||
|
m_Document = new XmlDocument();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void LoadXml(string xml)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_Document.LoadXml(xml);
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
throw new IcdXmlException(e.Message, e, e.LineNumber, e.LinePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteContentTo(IcdXmlTextWriter writer)
|
||||||
|
{
|
||||||
|
m_Document.WriteContentTo(writer.WrappedWriter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
ICD.Common/Utils/Xml/IcdXmlException.cs
Normal file
24
ICD.Common/Utils/Xml/IcdXmlException.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public sealed class IcdXmlException : Exception
|
||||||
|
{
|
||||||
|
private int m_LineNumber;
|
||||||
|
private int m_LinePosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
/// <param name="inner"></param>
|
||||||
|
/// <param name="lineNumber"></param>
|
||||||
|
/// <param name="linePosition"></param>
|
||||||
|
public IcdXmlException(string message, Exception inner, int lineNumber, int linePosition)
|
||||||
|
: base(message, inner)
|
||||||
|
{
|
||||||
|
m_LineNumber = lineNumber;
|
||||||
|
m_LinePosition = linePosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
128
ICD.Common/Utils/Xml/IcdXmlReader.cs
Normal file
128
ICD.Common/Utils/Xml/IcdXmlReader.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
using System;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp;
|
||||||
|
using Crestron.SimplSharp.CrestronXml;
|
||||||
|
#else
|
||||||
|
using System.Xml;
|
||||||
|
using System.IO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public sealed class IcdXmlReader : IDisposable
|
||||||
|
{
|
||||||
|
private readonly XmlReader m_Reader;
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
public bool HasAttributes { get { return m_Reader.HasAttributes; } }
|
||||||
|
|
||||||
|
public string Name { get { return m_Reader.Name; } }
|
||||||
|
|
||||||
|
public string Value { get { return m_Reader.Value; } }
|
||||||
|
|
||||||
|
public XmlNodeType NodeType { get { return m_Reader.NodeType; } }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="xml"></param>
|
||||||
|
public IcdXmlReader(string xml)
|
||||||
|
{
|
||||||
|
if (xml == null)
|
||||||
|
throw new ArgumentNullException("xml");
|
||||||
|
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Reader = new XmlReader(xml);
|
||||||
|
#else
|
||||||
|
m_Reader = XmlReader.Create(new StringReader(xml));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
~IcdXmlReader()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public bool MoveToNextAttribute()
|
||||||
|
{
|
||||||
|
return m_Reader.MoveToNextAttribute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MoveToElement()
|
||||||
|
{
|
||||||
|
m_Reader.MoveToElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetAttribute(string name)
|
||||||
|
{
|
||||||
|
return m_Reader.GetAttribute(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadString()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
return m_Reader.ReadString();
|
||||||
|
#else
|
||||||
|
return m_Reader.ReadElementContentAsString();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Read()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return m_Reader.Read();
|
||||||
|
}
|
||||||
|
catch (XmlException e)
|
||||||
|
{
|
||||||
|
throw new IcdXmlException(e.Message, e, e.LineNumber, e.LinePosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
#if SIMPLSHARP
|
||||||
|
m_Reader.Dispose(true);
|
||||||
|
#else
|
||||||
|
m_Reader.Dispose();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Skip()
|
||||||
|
{
|
||||||
|
m_Reader.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadElementContentAsString()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadElementContentAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadOuterXml()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadOuterXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ReadInnerXml()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadInnerXml();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ReadElementContentAsLong()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadElementContentAsLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ReadElementContentAsFloat()
|
||||||
|
{
|
||||||
|
return m_Reader.ReadElementContentAsFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
94
ICD.Common/Utils/Xml/IcdXmlTextWriter.SimplSharp.cs
Normal file
94
ICD.Common/Utils/Xml/IcdXmlTextWriter.SimplSharp.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#if SIMPLSHARP
|
||||||
|
using System.Text;
|
||||||
|
using Crestron.SimplSharp.CrestronXml;
|
||||||
|
using ICD.Common.Utils.IO;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public sealed partial class IcdXmlTextWriter
|
||||||
|
{
|
||||||
|
private readonly XmlTextWriter m_Writer;
|
||||||
|
|
||||||
|
public XmlWriter WrappedWriter { get { return m_Writer; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream"></param>
|
||||||
|
/// <param name="encoding"></param>
|
||||||
|
public IcdXmlTextWriter(IcdStream stream, Encoding encoding)
|
||||||
|
: this(new XmlTextWriter(stream.WrappedStream, encoding))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textWriter"></param>
|
||||||
|
public IcdXmlTextWriter(IcdTextWriter textWriter)
|
||||||
|
: this(new XmlTextWriter(textWriter.WrappedTextWriter))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer"></param>
|
||||||
|
public IcdXmlTextWriter(XmlTextWriter writer)
|
||||||
|
{
|
||||||
|
m_Writer = writer;
|
||||||
|
m_Writer.Formatting = Crestron.SimplSharp.CrestronXml.Formatting.Indented;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void WriteStartElement(string elementName)
|
||||||
|
{
|
||||||
|
m_Writer.WriteStartElement(elementName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteElementString(string elementName, string value)
|
||||||
|
{
|
||||||
|
m_Writer.WriteElementString(elementName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteEndElement()
|
||||||
|
{
|
||||||
|
m_Writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteComment(string comment)
|
||||||
|
{
|
||||||
|
m_Writer.WriteComment(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_Writer.Dispose(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteAttributeString(string attributeName, string value)
|
||||||
|
{
|
||||||
|
m_Writer.WriteAttributeString(attributeName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
m_Writer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
m_Writer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteRaw(string xml)
|
||||||
|
{
|
||||||
|
m_Writer.WriteRaw(xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
102
ICD.Common/Utils/Xml/IcdXmlTextWriter.Standard.cs
Normal file
102
ICD.Common/Utils/Xml/IcdXmlTextWriter.Standard.cs
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using ICD.Common.Utils.IO;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public sealed partial class IcdXmlTextWriter
|
||||||
|
{
|
||||||
|
private readonly XmlWriter m_Writer;
|
||||||
|
|
||||||
|
public XmlWriter WrappedWriter { get { return m_Writer; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stream"></param>
|
||||||
|
/// <param name="encoding"></param>
|
||||||
|
public IcdXmlTextWriter(IcdStream stream, Encoding encoding)
|
||||||
|
: this(XmlWriter.Create(stream.WrappedStream, GetSettings(encoding)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textWriter"></param>
|
||||||
|
public IcdXmlTextWriter(IcdTextWriter textWriter)
|
||||||
|
: this(XmlWriter.Create(textWriter.WrappedTextWriter))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="writer"></param>
|
||||||
|
public IcdXmlTextWriter(XmlWriter writer)
|
||||||
|
{
|
||||||
|
m_Writer = writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void WriteStartElement(string elementName)
|
||||||
|
{
|
||||||
|
m_Writer.WriteStartElement(elementName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteElementString(string elementName, string value)
|
||||||
|
{
|
||||||
|
m_Writer.WriteElementString(elementName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteEndElement()
|
||||||
|
{
|
||||||
|
m_Writer.WriteEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteComment(string comment)
|
||||||
|
{
|
||||||
|
m_Writer.WriteComment(comment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
m_Writer.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteAttributeString(string attributeName, string value)
|
||||||
|
{
|
||||||
|
m_Writer.WriteAttributeString(attributeName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Flush()
|
||||||
|
{
|
||||||
|
m_Writer.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteRaw(string xml)
|
||||||
|
{
|
||||||
|
m_Writer.WriteRaw(xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private static XmlWriterSettings GetSettings(Encoding encoding)
|
||||||
|
{
|
||||||
|
return new XmlWriterSettings
|
||||||
|
{
|
||||||
|
Encoding = encoding,
|
||||||
|
Indent = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
8
ICD.Common/Utils/Xml/IcdXmlTextWriter.cs
Normal file
8
ICD.Common/Utils/Xml/IcdXmlTextWriter.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public sealed partial class IcdXmlTextWriter : IDisposable
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
315
ICD.Common/Utils/Xml/XmlReaderExtensions.cs
Normal file
315
ICD.Common/Utils/Xml/XmlReaderExtensions.cs
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
#if SIMPLSHARP
|
||||||
|
using Crestron.SimplSharp.CrestronXml;
|
||||||
|
#else
|
||||||
|
using System.Xml;
|
||||||
|
#endif
|
||||||
|
using ICD.Common.EventArguments;
|
||||||
|
using ICD.Common.Properties;
|
||||||
|
|
||||||
|
namespace ICD.Common.Utils.Xml
|
||||||
|
{
|
||||||
|
public static class XmlReaderExtensions
|
||||||
|
{
|
||||||
|
#region Attributes
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the attribute exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool HasAttribute(this IcdXmlReader extends, string name)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
return extends.GetAttribute(name) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the attributes for the current element without moving the reader.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<IcdXmlAttribute> GetAttributes(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
if (!extends.HasAttributes)
|
||||||
|
return new IcdXmlAttribute[0];
|
||||||
|
|
||||||
|
List<IcdXmlAttribute> attributes = new List<IcdXmlAttribute>();
|
||||||
|
while (extends.MoveToNextAttribute())
|
||||||
|
attributes.Add(new IcdXmlAttribute(extends.Name, extends.Value));
|
||||||
|
|
||||||
|
// Move back to element.
|
||||||
|
extends.MoveToElement();
|
||||||
|
|
||||||
|
return attributes.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the attribute with the given name.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static string GetAttributeAsString(this IcdXmlReader extends, string name)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string output = extends.GetAttribute(name);
|
||||||
|
if (output == null)
|
||||||
|
throw new FormatException(string.Format("Missing attribute \"{0}\"", name));
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the attribute with the given name and returns as an integer.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static int GetAttributeAsInt(this IcdXmlReader extends, string name)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string value = extends.GetAttributeAsString(name);
|
||||||
|
return int.Parse(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the attribute with the given name and returns as a bool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool GetAttributeAsBool(this IcdXmlReader extends, string name)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string value = extends.GetAttributeAsString(name);
|
||||||
|
return bool.Parse(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Recurse
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Recurses through the entire XML, calling the callback for each Element/Text node.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="callback"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void Recurse(this IcdXmlReader extends, Action<XmlRecursionEventArgs> callback)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
XmlUtils.Recurse(extends.ReadString(), callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Skip
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Skips over insignificant whitespace.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static void SkipInsignificantWhitespace(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
while (extends.NodeType == XmlNodeType.Whitespace && extends.Read())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Skips the current node to the next element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
[PublicAPI]
|
||||||
|
public static bool SkipToNextElement(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
while (extends.Read() && extends.NodeType != XmlNodeType.Element)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return extends.NodeType == XmlNodeType.Element;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Get Child Element
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the current node has child elements.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool HasChildElements(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
while (extends.Read() && extends.NodeType != XmlNodeType.EndElement)
|
||||||
|
{
|
||||||
|
if (extends.NodeType == XmlNodeType.Element)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the child elements for the current element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IEnumerable<IcdXmlReader> GetChildElements(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
foreach (IcdXmlReader output in extends.GetChildElementsAsString().Select(child => new IcdXmlReader(child)))
|
||||||
|
{
|
||||||
|
output.SkipToNextElement();
|
||||||
|
yield return output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the child elements for the current element.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static IEnumerable<string> GetChildElementsAsString(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
// Step into the first child.
|
||||||
|
extends.SkipToNextElement();
|
||||||
|
|
||||||
|
while (extends.NodeType == XmlNodeType.Element || extends.NodeType == XmlNodeType.Comment)
|
||||||
|
{
|
||||||
|
switch (extends.NodeType)
|
||||||
|
{
|
||||||
|
case XmlNodeType.Comment:
|
||||||
|
extends.Skip();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XmlNodeType.Element:
|
||||||
|
yield return extends.ReadOuterXml();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
extends.SkipInsignificantWhitespace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Read Element Content
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the element content in the format 0xXX as a byte.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static byte ReadElementContentAsByte(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string content = extends.ReadElementContentAsString();
|
||||||
|
return (byte)Convert.ToInt64(content, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the element content as a uint.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static uint ReadElementContentAsUint(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string content = extends.ReadElementContentAsString();
|
||||||
|
return uint.Parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the element content as a uint.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static int ReadElementContentAsInt(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string content = extends.ReadElementContentAsString();
|
||||||
|
return int.Parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the element content as a ushort.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static ushort ReadElementContentAsUShort(this IcdXmlReader extends)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string content = extends.ReadElementContentAsString();
|
||||||
|
return ushort.Parse(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the element content as an enum.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="extends"></param>
|
||||||
|
/// <param name="ignoreCase"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public static T ReadElementContentAsEnum<T>(this IcdXmlReader extends, bool ignoreCase)
|
||||||
|
{
|
||||||
|
if (extends == null)
|
||||||
|
throw new ArgumentNullException("extends");
|
||||||
|
|
||||||
|
string content = extends.ReadElementContentAsString();
|
||||||
|
return EnumUtils.Parse<T>(content, ignoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
1013
ICD.Common/Utils/Xml/XmlUtils.cs
Normal file
1013
ICD.Common/Utils/Xml/XmlUtils.cs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user