Fix extension methods
This commit is contained in:
@@ -17,9 +17,9 @@ namespace Umbraco.Cms.Core
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The successful attempt.</returns>
|
||||
public static Attempt<TResult> Succeed<TResult>(TResult result)
|
||||
public static Attempt<TResult?> Succeed<TResult>(TResult? result)
|
||||
{
|
||||
return Attempt<TResult>.Succeed(result);
|
||||
return Attempt<TResult?>.Succeed(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Cms.Core
|
||||
public struct Attempt<TResult>
|
||||
{
|
||||
// private - use Succeed() or Fail() methods to create attempts
|
||||
private Attempt(bool success, TResult result, Exception exception)
|
||||
private Attempt(bool? success, TResult? result, Exception? exception)
|
||||
{
|
||||
Success = success;
|
||||
Result = result;
|
||||
@@ -20,22 +20,22 @@ namespace Umbraco.Cms.Core
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this <see cref="Attempt{TResult}"/> was successful.
|
||||
/// </summary>
|
||||
public bool Success { get; }
|
||||
public bool? Success { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the exception associated with an unsuccessful attempt.
|
||||
/// </summary>
|
||||
public Exception Exception { get; }
|
||||
public Exception? Exception { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attempt result.
|
||||
/// </summary>
|
||||
public TResult Result { get; }
|
||||
public TResult? Result { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the attempt result, if successful, else a default value.
|
||||
/// </summary>
|
||||
public TResult ResultOr(TResult value) => Success ? Result : value;
|
||||
public TResult? ResultOr(TResult? value) => Success.HasValue && Success.Value ? Result : value;
|
||||
|
||||
// optimize, use a singleton failed attempt
|
||||
private static readonly Attempt<TResult> Failed = new Attempt<TResult>(false, default(TResult), null);
|
||||
@@ -54,7 +54,7 @@ namespace Umbraco.Cms.Core
|
||||
/// </summary>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The successful attempt.</returns>
|
||||
public static Attempt<TResult> Succeed(TResult result)
|
||||
public static Attempt<TResult> Succeed(TResult? result)
|
||||
{
|
||||
return new Attempt<TResult>(true, result, null);
|
||||
}
|
||||
@@ -73,7 +73,7 @@ namespace Umbraco.Cms.Core
|
||||
/// </summary>
|
||||
/// <param name="exception">The exception causing the failure of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail(Exception exception)
|
||||
public static Attempt<TResult> Fail(Exception? exception)
|
||||
{
|
||||
return new Attempt<TResult>(false, default(TResult), exception);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ namespace Umbraco.Cms.Core
|
||||
/// <param name="condition">A value indicating whether the attempt is successful.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The attempt.</returns>
|
||||
public static Attempt<TResult> If(bool condition, TResult result)
|
||||
public static Attempt<TResult> If(bool condition, TResult? result)
|
||||
{
|
||||
return new Attempt<TResult>(condition, result, null);
|
||||
}
|
||||
@@ -125,7 +125,7 @@ namespace Umbraco.Cms.Core
|
||||
/// </summary>
|
||||
/// <param name="a"></param>
|
||||
/// <returns></returns>
|
||||
public static implicit operator bool(Attempt<TResult> a)
|
||||
public static implicit operator bool?(Attempt<TResult> a)
|
||||
{
|
||||
return a.Success;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
return _rootDir;
|
||||
}
|
||||
|
||||
var codeBase = executingAssembly.CodeBase;
|
||||
var codeBase = executingAssembly.Location;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
var baseDirectory = Path.GetDirectoryName(path);
|
||||
@@ -45,7 +44,7 @@ namespace Umbraco.Extensions
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetAssemblyFile(this Assembly assembly)
|
||||
{
|
||||
var codeBase = assembly.CodeBase;
|
||||
var codeBase = assembly.Location;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
@@ -58,7 +57,7 @@ namespace Umbraco.Extensions
|
||||
/// <returns></returns>
|
||||
public static bool IsAppCodeAssembly(this Assembly assembly)
|
||||
{
|
||||
if (assembly.FullName.StartsWith("App_Code"))
|
||||
if (assembly.FullName!.StartsWith("App_Code"))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -82,7 +81,7 @@ namespace Umbraco.Extensions
|
||||
public static bool IsGlobalAsaxAssembly(this Assembly assembly)
|
||||
{
|
||||
//only way I can figure out how to test is by the name
|
||||
return assembly.FullName.StartsWith("App_global.asax");
|
||||
return assembly.FullName!.StartsWith("App_global.asax");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -90,12 +89,17 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetAssemblyFile(this AssemblyName assemblyName)
|
||||
public static FileInfo? GetAssemblyFile(this AssemblyName assemblyName)
|
||||
{
|
||||
var codeBase = assemblyName.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
if (!string.IsNullOrEmpty(codeBase))
|
||||
{
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
public static class ClaimsIdentityExtensions
|
||||
{
|
||||
public static T GetUserId<T>(this IIdentity identity)
|
||||
public static T? GetUserId<T>(this IIdentity identity)
|
||||
{
|
||||
var strId = identity.GetUserId();
|
||||
var converted = strId.TryConvertTo<T>();
|
||||
@@ -27,11 +27,11 @@ namespace Umbraco.Extensions
|
||||
/// <returns>
|
||||
/// The string value of the user id if found otherwise null
|
||||
/// </returns>
|
||||
public static string GetUserId(this IIdentity identity)
|
||||
public static string? GetUserId(this IIdentity identity)
|
||||
{
|
||||
if (identity == null) throw new ArgumentNullException(nameof(identity));
|
||||
|
||||
string userId = null;
|
||||
string? userId = null;
|
||||
if (identity is ClaimsIdentity claimsIdentity)
|
||||
{
|
||||
userId = claimsIdentity.FindFirstValue(ClaimTypes.NameIdentifier)
|
||||
@@ -48,11 +48,11 @@ namespace Umbraco.Extensions
|
||||
/// <returns>
|
||||
/// The string value of the user name if found otherwise null
|
||||
/// </returns>
|
||||
public static string GetUserName(this IIdentity identity)
|
||||
public static string? GetUserName(this IIdentity identity)
|
||||
{
|
||||
if (identity == null) throw new ArgumentNullException(nameof(identity));
|
||||
|
||||
string username = null;
|
||||
string? username = null;
|
||||
if (identity is ClaimsIdentity claimsIdentity)
|
||||
{
|
||||
username = claimsIdentity.FindFirstValue(ClaimTypes.Name)
|
||||
@@ -70,7 +70,7 @@ namespace Umbraco.Extensions
|
||||
/// <returns>
|
||||
/// The string value of the claim if found otherwise null
|
||||
/// </returns>
|
||||
public static string FindFirstValue(this ClaimsIdentity identity, string claimType)
|
||||
public static string? FindFirstValue(this ClaimsIdentity identity, string claimType)
|
||||
{
|
||||
if (identity == null) throw new ArgumentNullException(nameof(identity));
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="identity"></param>
|
||||
/// <param name="verifiedIdentity">Verified identity wrapped in a ClaimsIdentity with BackOfficeAuthentication type</param>
|
||||
/// <returns>True if ClaimsIdentity</returns>
|
||||
public static bool VerifyBackOfficeIdentity(this ClaimsIdentity identity, out ClaimsIdentity verifiedIdentity)
|
||||
public static bool VerifyBackOfficeIdentity(this ClaimsIdentity identity, out ClaimsIdentity? verifiedIdentity)
|
||||
{
|
||||
if (identity is null)
|
||||
{
|
||||
@@ -119,7 +119,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
verifiedIdentity = identity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType ? identity : new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
|
||||
verifiedIdentity = identity.AuthenticationType == Constants.Security.BackOfficeAuthenticationType ? identity : new ClaimsIdentity(identity.Claims, Constants.Security.BackOfficeAuthenticationType);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -294,35 +294,44 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns>User ID as integer</returns>
|
||||
public static int GetId(this ClaimsIdentity identity) => int.Parse(identity.FindFirstValue(ClaimTypes.NameIdentifier), CultureInfo.InvariantCulture);
|
||||
public static int? GetId(this ClaimsIdentity identity)
|
||||
{
|
||||
var firstValue = identity.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (firstValue is not null)
|
||||
{
|
||||
int.Parse(firstValue, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the real name belonging to the user from a ClaimsIdentity
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns>Real name of the user</returns>
|
||||
public static string GetRealName(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.GivenName);
|
||||
public static string? GetRealName(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.GivenName);
|
||||
|
||||
/// <summary>
|
||||
/// Get the username of the user from a ClaimsIdentity
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns>Username of the user</returns>
|
||||
public static string GetUsername(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.Name);
|
||||
public static string? GetUsername(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.Name);
|
||||
|
||||
/// <summary>
|
||||
/// Get the culture string from a ClaimsIdentity
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns>Culture string</returns>
|
||||
public static string GetCultureString(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.Locality);
|
||||
public static string? GetCultureString(this ClaimsIdentity identity) => identity.FindFirstValue(ClaimTypes.Locality);
|
||||
|
||||
/// <summary>
|
||||
/// Get the security stamp from a ClaimsIdentity
|
||||
/// </summary>
|
||||
/// <param name="identity"></param>
|
||||
/// <returns>Security stamp</returns>
|
||||
public static string GetSecurityStamp(this ClaimsIdentity identity) => identity.FindFirstValue(Constants.Security.SecurityStampClaimType);
|
||||
public static string? GetSecurityStamp(this ClaimsIdentity identity) => identity.FindFirstValue(Constants.Security.SecurityStampClaimType);
|
||||
|
||||
/// <summary>
|
||||
/// Get the roles assigned to a user from a ClaimsIdentity
|
||||
@@ -336,17 +345,20 @@ namespace Umbraco.Extensions
|
||||
/// <summary>
|
||||
/// Adds or updates and existing claim.
|
||||
/// </summary>
|
||||
public static void AddOrUpdateClaim(this ClaimsIdentity identity, Claim claim)
|
||||
public static void AddOrUpdateClaim(this ClaimsIdentity identity, Claim? claim)
|
||||
{
|
||||
if (identity == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(identity));
|
||||
}
|
||||
|
||||
Claim existingClaim = identity.Claims.FirstOrDefault(x => x.Type == claim.Type);
|
||||
identity.TryRemoveClaim(existingClaim);
|
||||
if (claim is not null)
|
||||
{
|
||||
Claim? existingClaim = identity.Claims.FirstOrDefault(x => x.Type == claim.Type);
|
||||
identity.TryRemoveClaim(existingClaim);
|
||||
|
||||
identity.AddClaim(claim);
|
||||
identity.AddClaim(claim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,10 +289,10 @@ namespace Umbraco.Extensions
|
||||
/// <para>Basically, exact is for one content type, or one property type, and !exact is for "all property types" of one content type.</para>
|
||||
/// <para>Both <paramref name="culture" /> and <paramref name="segment" /> can be "*" to indicate "all of them".</para>
|
||||
/// </remarks>
|
||||
public static bool ValidateVariation(this ContentVariation variation, string culture, string segment, bool exact, bool wildcards, bool throwIfInvalid)
|
||||
public static bool ValidateVariation(this ContentVariation variation, string? culture, string? segment, bool exact, bool wildcards, bool throwIfInvalid)
|
||||
{
|
||||
culture = culture.NullOrWhiteSpaceAsNull();
|
||||
segment = segment.NullOrWhiteSpaceAsNull();
|
||||
culture = culture?.NullOrWhiteSpaceAsNull();
|
||||
segment = segment?.NullOrWhiteSpaceAsNull();
|
||||
|
||||
// if wildcards are disabled, do not allow "*"
|
||||
if (!wildcards && (culture == "*" || segment == "*"))
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
public static class DelegateExtensions
|
||||
{
|
||||
public static Attempt<T> RetryUntilSuccessOrTimeout<T>(this Func<Attempt<T>> task, TimeSpan timeout, TimeSpan pause)
|
||||
public static Attempt<T?> RetryUntilSuccessOrTimeout<T>(this Func<Attempt<T?>> task, TimeSpan timeout, TimeSpan pause)
|
||||
{
|
||||
if (pause.TotalMilliseconds < 0)
|
||||
{
|
||||
@@ -20,14 +20,14 @@ namespace Umbraco.Extensions
|
||||
do
|
||||
{
|
||||
var result = task();
|
||||
if (result) { return result; }
|
||||
if (result.Success.HasValue && result.Success.Value) { return result; }
|
||||
Thread.Sleep((int)pause.TotalMilliseconds);
|
||||
}
|
||||
while (stopwatch.Elapsed < timeout);
|
||||
return Attempt<T>.Fail();
|
||||
return Attempt<T?>.Fail();
|
||||
}
|
||||
|
||||
public static Attempt<T> RetryUntilSuccessOrMaxAttempts<T>(this Func<int, Attempt<T>> task, int totalAttempts, TimeSpan pause)
|
||||
public static Attempt<T?> RetryUntilSuccessOrMaxAttempts<T>(this Func<int, Attempt<T?>> task, int totalAttempts, TimeSpan pause)
|
||||
{
|
||||
if (pause.TotalMilliseconds < 0)
|
||||
{
|
||||
@@ -38,11 +38,11 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
attempts++;
|
||||
var result = task(attempts);
|
||||
if (result) { return result; }
|
||||
if (result.Success.HasValue && result.Success.Value) { return result; }
|
||||
Thread.Sleep((int)pause.TotalMilliseconds);
|
||||
}
|
||||
while (attempts < totalAttempts);
|
||||
return Attempt<T>.Fail();
|
||||
return Attempt<T?>.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,8 +53,9 @@ namespace Umbraco.Extensions
|
||||
/// If there is an item in the dictionary with the key, it will keep trying to update it until it can
|
||||
/// </remarks>
|
||||
public static bool TryUpdate<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TValue, TValue> updateFactory)
|
||||
where TKey : notnull
|
||||
{
|
||||
TValue curValue;
|
||||
TValue? curValue;
|
||||
while (dict.TryGetValue(key, out curValue))
|
||||
{
|
||||
if (dict.TryUpdate(key, updateFactory(curValue), curValue))
|
||||
@@ -80,8 +81,9 @@ namespace Umbraco.Extensions
|
||||
/// WARNING: If the value changes after we've retrieved it, then the item will not be updated
|
||||
/// </remarks>
|
||||
public static bool TryUpdateOptimisitic<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dict, TKey key, Func<TValue, TValue> updateFactory)
|
||||
where TKey : notnull
|
||||
{
|
||||
TValue curValue;
|
||||
TValue? curValue;
|
||||
if (!dict.TryGetValue(key, out curValue))
|
||||
return false;
|
||||
dict.TryUpdate(key, updateFactory(curValue), curValue);
|
||||
@@ -96,11 +98,12 @@ namespace Umbraco.Extensions
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary<TKeyOut, TValOut> ConvertTo<TKeyOut, TValOut>(this IDictionary d)
|
||||
where TKeyOut : notnull
|
||||
{
|
||||
var result = new Dictionary<TKeyOut, TValOut>();
|
||||
foreach (DictionaryEntry v in d)
|
||||
{
|
||||
result.Add((TKeyOut)v.Key, (TValOut)v.Value);
|
||||
result.Add((TKeyOut)v.Key, (TValOut)v.Value!);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -115,11 +118,12 @@ namespace Umbraco.Extensions
|
||||
/// <param name="valConverter"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary<TKeyOut, TValOut> ConvertTo<TKeyOut, TValOut>(this IDictionary d, Func<object, TKeyOut> keyConverter, Func<object, TValOut> valConverter)
|
||||
where TKeyOut : notnull
|
||||
{
|
||||
var result = new Dictionary<TKeyOut, TValOut>();
|
||||
foreach (DictionaryEntry v in d)
|
||||
{
|
||||
result.Add(keyConverter(v.Key), valConverter(v.Value));
|
||||
result.Add(keyConverter(v.Key), valConverter(v.Value!));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -205,7 +209,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="d"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetValueAsString<TKey, TVal>(this IDictionary<TKey, TVal> d, TKey key)
|
||||
public static string? GetValueAsString<TKey, TVal>(this IDictionary<TKey, TVal> d, TKey key)
|
||||
=> d.ContainsKey(key) ? d[key]!.ToString() : string.Empty;
|
||||
|
||||
/// <summary>
|
||||
@@ -215,7 +219,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="key"></param>
|
||||
/// <param name="defaultValue"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetValueAsString<TKey, TVal>(this IDictionary<TKey, TVal> d, TKey key, string defaultValue)
|
||||
public static string? GetValueAsString<TKey, TVal>(this IDictionary<TKey, TVal> d, TKey key, string defaultValue)
|
||||
{
|
||||
if (d.ContainsKey(key))
|
||||
{
|
||||
@@ -269,12 +273,13 @@ namespace Umbraco.Extensions
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <typeparam name="TValue">The type</typeparam>
|
||||
/// <returns>The entry</returns>
|
||||
public static TValue GetValueIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string key, TValue defaultValue)
|
||||
public static TValue GetValueIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string? key, TValue
|
||||
defaultValue)
|
||||
{
|
||||
key = dictionary.Keys.FirstOrDefault(i => i.InvariantEquals(key));
|
||||
|
||||
return key.IsNullOrWhiteSpace() == false
|
||||
? dictionary[key]
|
||||
? dictionary[key!]
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
@@ -282,6 +287,7 @@ namespace Umbraco.Extensions
|
||||
this IEnumerable<TInput> enumerable,
|
||||
Func<TInput, TKey> syncKeySelector,
|
||||
Func<TInput, Task<TValue>> asyncValueSelector)
|
||||
where TKey : notnull
|
||||
{
|
||||
Dictionary<TKey,TValue> dictionary = new Dictionary<TKey, TValue>();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Extensions
|
||||
yield return item;
|
||||
}
|
||||
|
||||
public static IEnumerable<IEnumerable<T>> InGroupsOf<T>(this IEnumerable<T> source, int groupSize)
|
||||
public static IEnumerable<IEnumerable<T>> InGroupsOf<T>(this IEnumerable<T>? source, int groupSize)
|
||||
{
|
||||
if (source == null)
|
||||
throw new ArgumentNullException("source");
|
||||
@@ -49,7 +49,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
// following code derived from MoreLinq and does not allocate bazillions of tuples
|
||||
|
||||
T[] temp = null;
|
||||
T[]? temp = null;
|
||||
var count = 0;
|
||||
|
||||
foreach (var item in source)
|
||||
@@ -234,9 +234,8 @@ namespace Umbraco.Extensions
|
||||
return sequence.Select(
|
||||
x =>
|
||||
{
|
||||
if (x is TActual)
|
||||
if (x is TActual casted)
|
||||
{
|
||||
var casted = x as TActual;
|
||||
projection.Invoke(casted);
|
||||
}
|
||||
return x;
|
||||
@@ -342,7 +341,7 @@ namespace Umbraco.Extensions
|
||||
// this is to support filtering with multiple types
|
||||
public static IEnumerable<T> OfTypes<T>(this IEnumerable<T> contents, params Type[] types)
|
||||
{
|
||||
return contents.Where(x => types.Contains(x.GetType()));
|
||||
return contents.Where(x => types.Contains(x?.GetType()));
|
||||
}
|
||||
|
||||
public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> source)
|
||||
|
||||
@@ -9,11 +9,11 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
public static class NameValueCollectionExtensions
|
||||
{
|
||||
public static IEnumerable<KeyValuePair<string, string>> AsEnumerable(this NameValueCollection nvc)
|
||||
public static IEnumerable<KeyValuePair<string?, string?>> AsEnumerable(this NameValueCollection nvc)
|
||||
{
|
||||
foreach (string key in nvc.AllKeys)
|
||||
foreach (string? key in nvc.AllKeys)
|
||||
{
|
||||
yield return new KeyValuePair<string, string>(key, nvc[key]);
|
||||
yield return new KeyValuePair<string?, string?>(key, nvc[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Umbraco.Extensions
|
||||
return collection.Keys.Cast<object>().Any(k => (string) k == key);
|
||||
}
|
||||
|
||||
public static T GetValue<T>(this NameValueCollection collection, string key, T defaultIfNotFound)
|
||||
public static T? GetValue<T>(this NameValueCollection collection, string key, T defaultIfNotFound)
|
||||
{
|
||||
if (collection.ContainsKey(key) == false)
|
||||
{
|
||||
@@ -37,7 +37,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
var result = val.TryConvertTo<T>();
|
||||
|
||||
return result.Success ? result.Result : defaultIfNotFound;
|
||||
return result.Success.HasValue && result.Success.Value ? result.Result : defaultIfNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
private static readonly ConcurrentDictionary<Type, Type> NullableGenericCache = new ConcurrentDictionary<Type, Type>();
|
||||
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter> InputTypeConverterCache = new ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter>();
|
||||
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter> DestinationTypeConverterCache = new ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter>();
|
||||
private static readonly ConcurrentDictionary<Type, Type?> NullableGenericCache = new ConcurrentDictionary<Type, Type?>();
|
||||
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter?> InputTypeConverterCache = new ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter?>();
|
||||
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter?> DestinationTypeConverterCache = new ConcurrentDictionary<CompositeTypeTypeKey, TypeConverter?>();
|
||||
private static readonly ConcurrentDictionary<CompositeTypeTypeKey, bool> AssignableTypeCache = new ConcurrentDictionary<CompositeTypeTypeKey, bool>();
|
||||
private static readonly ConcurrentDictionary<Type, bool> BoolConvertCache = new ConcurrentDictionary<Type, bool>();
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns></returns>
|
||||
public static T SafeCast<T>(this object input)
|
||||
public static T? SafeCast<T>(this object input)
|
||||
{
|
||||
if (ReferenceEquals(null, input) || ReferenceEquals(default(T), input)) return default;
|
||||
if (input is T variable) return variable;
|
||||
@@ -77,11 +77,11 @@ namespace Umbraco.Extensions
|
||||
/// <returns>The <see cref="Attempt{T}"/></returns>
|
||||
public static Attempt<T> TryConvertTo<T>(this object? input)
|
||||
{
|
||||
Attempt<object> result = TryConvertTo(input, typeof(T));
|
||||
Attempt<object?> result = TryConvertTo(input, typeof(T));
|
||||
|
||||
if (result.Success)
|
||||
if (result.Success.HasValue && result.Success.Value)
|
||||
{
|
||||
return Attempt<T>.Succeed((T)result.Result);
|
||||
return Attempt<T>.Succeed((T?)result.Result);
|
||||
}
|
||||
|
||||
if (input == null)
|
||||
@@ -94,7 +94,7 @@ namespace Umbraco.Extensions
|
||||
else
|
||||
{
|
||||
// sure, null can be any object
|
||||
return Attempt<T>.Succeed((T)input);
|
||||
return Attempt<T>.Succeed((T)input!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,11 +116,11 @@ namespace Umbraco.Extensions
|
||||
/// <param name="input">The input.</param>
|
||||
/// <param name="target">The type to convert to</param>
|
||||
/// <returns>The <see cref="Attempt{Object}"/></returns>
|
||||
public static Attempt<object> TryConvertTo(this object input, Type target)
|
||||
public static Attempt<object?> TryConvertTo(this object? input, Type target)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
return Attempt<object>.Fail();
|
||||
return Attempt<object?>.Fail();
|
||||
}
|
||||
|
||||
try
|
||||
@@ -130,11 +130,11 @@ namespace Umbraco.Extensions
|
||||
// Nullable is ok
|
||||
if (target.IsGenericType && GetCachedGenericNullableType(target) != null)
|
||||
{
|
||||
return Attempt<object>.Succeed(null);
|
||||
return Attempt<object?>.Succeed(null);
|
||||
}
|
||||
|
||||
// Reference types are ok
|
||||
return Attempt<object>.If(target.IsValueType == false, null);
|
||||
return Attempt<object?>.If(target.IsValueType == false, null);
|
||||
}
|
||||
|
||||
var inputType = input.GetType();
|
||||
@@ -148,7 +148,7 @@ namespace Umbraco.Extensions
|
||||
// Check for string so that overloaders of ToString() can take advantage of the conversion.
|
||||
if (target == typeof(string))
|
||||
{
|
||||
return Attempt<object>.Succeed(input.ToString());
|
||||
return Attempt<object?>.Succeed(input.ToString());
|
||||
}
|
||||
|
||||
// If we've got a nullable of something, we try to convert directly to that thing.
|
||||
@@ -165,7 +165,7 @@ namespace Umbraco.Extensions
|
||||
// TODO: Why the check against only bool/date when a string is null/empty? In what scenario can we convert to another type when the string is null or empty other than just being null?
|
||||
if (string.IsNullOrEmpty(inputString) && (underlying == typeof(DateTime) || underlying == typeof(bool)))
|
||||
{
|
||||
return Attempt<object>.Succeed(null);
|
||||
return Attempt<object?>.Succeed(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,13 +173,13 @@ namespace Umbraco.Extensions
|
||||
var inner = input.TryConvertTo(underlying);
|
||||
|
||||
// And if successful, fall on through to rewrap in a nullable; if failed, pass on the exception
|
||||
if (inner.Success)
|
||||
if (inner.Success.HasValue && inner.Success.Value)
|
||||
{
|
||||
input = inner.Result; // Now fall on through...
|
||||
}
|
||||
else
|
||||
{
|
||||
return Attempt<object>.Fail(inner.Exception);
|
||||
return Attempt<object?>.Fail(inner.Exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,7 +211,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
if (GetCachedCanConvertToBoolean(inputType))
|
||||
{
|
||||
return Attempt.Succeed(CustomBooleanTypeConverter.ConvertFrom(input));
|
||||
return Attempt.Succeed(CustomBooleanTypeConverter.ConvertFrom(input!));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ namespace Umbraco.Extensions
|
||||
var outputConverter = GetCachedTargetTypeConverter(inputType, target);
|
||||
if (outputConverter != null)
|
||||
{
|
||||
return Attempt.Succeed(outputConverter.ConvertFrom(input));
|
||||
return Attempt.Succeed(outputConverter.ConvertFrom(input!));
|
||||
}
|
||||
|
||||
if (target.IsGenericType && GetCachedGenericNullableType(target) != null)
|
||||
@@ -243,10 +243,10 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return Attempt<object>.Fail(e);
|
||||
return Attempt<object?>.Fail(e);
|
||||
}
|
||||
|
||||
return Attempt<object>.Fail();
|
||||
return Attempt<object?>.Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -256,12 +256,12 @@ namespace Umbraco.Extensions
|
||||
/// <param name="input">The input.</param>
|
||||
/// <param name="target">The type to convert to</param>
|
||||
/// <returns>The <see cref="Nullable{Attempt}"/></returns>
|
||||
private static Attempt<object>? TryConvertToFromString(this string input, Type target)
|
||||
private static Attempt<object?>? TryConvertToFromString(this string input, Type target)
|
||||
{
|
||||
// Easy
|
||||
if (target == typeof(string))
|
||||
{
|
||||
return Attempt<object>.Succeed(input);
|
||||
return Attempt<object?>.Succeed(input);
|
||||
}
|
||||
|
||||
// Null, empty, whitespaces
|
||||
@@ -270,13 +270,13 @@ namespace Umbraco.Extensions
|
||||
if (target == typeof(bool))
|
||||
{
|
||||
// null/empty = bool false
|
||||
return Attempt<object>.Succeed(false);
|
||||
return Attempt<object?>.Succeed(false);
|
||||
}
|
||||
|
||||
if (target == typeof(DateTime))
|
||||
{
|
||||
// null/empty = min DateTime value
|
||||
return Attempt<object>.Succeed(DateTime.MinValue);
|
||||
return Attempt<object?>.Succeed(DateTime.MinValue);
|
||||
}
|
||||
|
||||
// Cannot decide here,
|
||||
@@ -296,25 +296,25 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
if (int.TryParse(input, out var value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
return Attempt<object?>.Succeed(value);
|
||||
}
|
||||
|
||||
// Because decimal 100.01m will happily convert to integer 100, it
|
||||
// makes sense that string "100.01" *also* converts to integer 100.
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.If(decimal.TryParse(input2, out var value2), Convert.ToInt32(value2));
|
||||
return Attempt<object?>.If(decimal.TryParse(input2, out var value2), Convert.ToInt32(value2));
|
||||
}
|
||||
|
||||
if (target == typeof(long))
|
||||
{
|
||||
if (long.TryParse(input, out var value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
return Attempt<object?>.Succeed(value);
|
||||
}
|
||||
|
||||
// Same as int
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.If(decimal.TryParse(input2, out var value2), Convert.ToInt64(value2));
|
||||
return Attempt<object?>.If(decimal.TryParse(input2, out var value2), Convert.ToInt64(value2));
|
||||
}
|
||||
|
||||
// TODO: Should we do the decimal trick for short, byte, unsigned?
|
||||
@@ -323,7 +323,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
if (bool.TryParse(input, out var value))
|
||||
{
|
||||
return Attempt<object>.Succeed(value);
|
||||
return Attempt<object?>.Succeed(value);
|
||||
}
|
||||
|
||||
// Don't declare failure so the CustomBooleanTypeConverter can try
|
||||
@@ -334,38 +334,38 @@ namespace Umbraco.Extensions
|
||||
switch (Type.GetTypeCode(target))
|
||||
{
|
||||
case TypeCode.Int16:
|
||||
return Attempt<object>.If(short.TryParse(input, out var value), value);
|
||||
return Attempt<object?>.If(short.TryParse(input, out var value), value);
|
||||
|
||||
case TypeCode.Double:
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.If(double.TryParse(input2, out var valueD), valueD);
|
||||
return Attempt<object?>.If(double.TryParse(input2, out var valueD), valueD);
|
||||
|
||||
case TypeCode.Single:
|
||||
var input3 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.If(float.TryParse(input3, out var valueF), valueF);
|
||||
return Attempt<object?>.If(float.TryParse(input3, out var valueF), valueF);
|
||||
|
||||
case TypeCode.Char:
|
||||
return Attempt<object>.If(char.TryParse(input, out var valueC), valueC);
|
||||
return Attempt<object?>.If(char.TryParse(input, out var valueC), valueC);
|
||||
|
||||
case TypeCode.Byte:
|
||||
return Attempt<object>.If(byte.TryParse(input, out var valueB), valueB);
|
||||
return Attempt<object?>.If(byte.TryParse(input, out var valueB), valueB);
|
||||
|
||||
case TypeCode.SByte:
|
||||
return Attempt<object>.If(sbyte.TryParse(input, out var valueSb), valueSb);
|
||||
return Attempt<object?>.If(sbyte.TryParse(input, out var valueSb), valueSb);
|
||||
|
||||
case TypeCode.UInt32:
|
||||
return Attempt<object>.If(uint.TryParse(input, out var valueU), valueU);
|
||||
return Attempt<object?>.If(uint.TryParse(input, out var valueU), valueU);
|
||||
|
||||
case TypeCode.UInt16:
|
||||
return Attempt<object>.If(ushort.TryParse(input, out var valueUs), valueUs);
|
||||
return Attempt<object?>.If(ushort.TryParse(input, out var valueUs), valueUs);
|
||||
|
||||
case TypeCode.UInt64:
|
||||
return Attempt<object>.If(ulong.TryParse(input, out var valueUl), valueUl);
|
||||
return Attempt<object?>.If(ulong.TryParse(input, out var valueUl), valueUl);
|
||||
}
|
||||
}
|
||||
else if (target == typeof(Guid))
|
||||
{
|
||||
return Attempt<object>.If(Guid.TryParse(input, out var value), value);
|
||||
return Attempt<object?>.If(Guid.TryParse(input, out var value), value);
|
||||
}
|
||||
else if (target == typeof(DateTime))
|
||||
{
|
||||
@@ -375,34 +375,34 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
case DateTimeKind.Unspecified:
|
||||
case DateTimeKind.Utc:
|
||||
return Attempt<object>.Succeed(value);
|
||||
return Attempt<object?>.Succeed(value);
|
||||
|
||||
case DateTimeKind.Local:
|
||||
return Attempt<object>.Succeed(value.ToUniversalTime());
|
||||
return Attempt<object?>.Succeed(value.ToUniversalTime());
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
return Attempt<object>.Fail();
|
||||
return Attempt<object?>.Fail();
|
||||
}
|
||||
else if (target == typeof(DateTimeOffset))
|
||||
{
|
||||
return Attempt<object>.If(DateTimeOffset.TryParse(input, out var value), value);
|
||||
return Attempt<object?>.If(DateTimeOffset.TryParse(input, out var value), value);
|
||||
}
|
||||
else if (target == typeof(TimeSpan))
|
||||
{
|
||||
return Attempt<object>.If(TimeSpan.TryParse(input, out var value), value);
|
||||
return Attempt<object?>.If(TimeSpan.TryParse(input, out var value), value);
|
||||
}
|
||||
else if (target == typeof(decimal))
|
||||
{
|
||||
var input2 = NormalizeNumberDecimalSeparator(input);
|
||||
return Attempt<object>.If(decimal.TryParse(input2, out var value), value);
|
||||
return Attempt<object?>.If(decimal.TryParse(input2, out var value), value);
|
||||
}
|
||||
else if (input != null && target == typeof(Version))
|
||||
{
|
||||
return Attempt<object>.If(Version.TryParse(input, out var value), value);
|
||||
return Attempt<object?>.If(Version.TryParse(input, out var value), value);
|
||||
}
|
||||
|
||||
// E_NOTIMPL IPAddress, BigInteger
|
||||
@@ -489,9 +489,9 @@ namespace Umbraco.Extensions
|
||||
/// <param name="o"></param>
|
||||
/// <param name="ignoreProperties"></param>
|
||||
/// <returns></returns>
|
||||
public static IDictionary<string, TVal> ToDictionary<T, TProperty, TVal>(this T o, params Expression<Func<T, TProperty>>[] ignoreProperties)
|
||||
public static IDictionary<string, TVal>? ToDictionary<T, TProperty, TVal>(this T o, params Expression<Func<T, TProperty>>[] ignoreProperties)
|
||||
{
|
||||
return o.ToDictionary<TVal>(ignoreProperties.Select(e => o.GetPropertyInfo(e)).Select(propInfo => propInfo.Name).ToArray());
|
||||
return o?.ToDictionary<TVal>(ignoreProperties.Select(e => o.GetPropertyInfo(e)).Select(propInfo => propInfo.Name).ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -521,7 +521,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
|
||||
|
||||
internal static string ToDebugString(this object obj, int levels = 0)
|
||||
internal static string? ToDebugString(this object? obj, int levels = 0)
|
||||
{
|
||||
if (obj == null) return "{null}";
|
||||
try
|
||||
@@ -589,7 +589,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static Attempt<string> TryConvertToXmlString(this object value, Type type)
|
||||
internal static Attempt<string?> TryConvertToXmlString(this object value, Type type)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -598,7 +598,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
catch (NotSupportedException ex)
|
||||
{
|
||||
return Attempt<string>.Fail(ex);
|
||||
return Attempt<string?>.Fail(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -608,7 +608,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="value"></param>
|
||||
/// <param name="type">The Type can only be a primitive type or Guid and byte[] otherwise an exception is thrown</param>
|
||||
/// <returns></returns>
|
||||
public static string ToXmlString(this object value, Type type)
|
||||
public static string? ToXmlString(this object value, Type type)
|
||||
{
|
||||
if (value == null) return string.Empty;
|
||||
if (type == typeof(string)) return (value.ToString().IsNullOrWhiteSpace() ? "" : value.ToString());
|
||||
@@ -640,12 +640,12 @@ namespace Umbraco.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string ToXmlString<T>(this object value)
|
||||
public static string? ToXmlString<T>(this object value)
|
||||
{
|
||||
return value.ToXmlString(typeof (T));
|
||||
}
|
||||
|
||||
private static string GetEnumPropertyDebugString(object enumItem, int levels)
|
||||
private static string? GetEnumPropertyDebugString(object enumItem, int levels)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -657,7 +657,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetPropertyDebugString(PropertyInfo propertyInfo, object obj, int levels)
|
||||
private static string? GetPropertyDebugString(PropertyInfo propertyInfo, object obj, int levels)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -683,7 +683,7 @@ namespace Umbraco.Extensions
|
||||
|
||||
// gets a converter for source, that can convert to target, or null if none exists
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static TypeConverter GetCachedSourceTypeConverter(Type source, Type target)
|
||||
private static TypeConverter? GetCachedSourceTypeConverter(Type source, Type target)
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
|
||||
@@ -698,12 +698,13 @@ namespace Umbraco.Extensions
|
||||
return InputTypeConverterCache[key] = converter;
|
||||
}
|
||||
|
||||
return InputTypeConverterCache[key] = null;
|
||||
InputTypeConverterCache[key] = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
// gets a converter for target, that can convert from source, or null if none exists
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static TypeConverter GetCachedTargetTypeConverter(Type source, Type target)
|
||||
private static TypeConverter? GetCachedTargetTypeConverter(Type source, Type target)
|
||||
{
|
||||
var key = new CompositeTypeTypeKey(source, target);
|
||||
|
||||
@@ -718,12 +719,13 @@ namespace Umbraco.Extensions
|
||||
return DestinationTypeConverterCache[key] = converter;
|
||||
}
|
||||
|
||||
return DestinationTypeConverterCache[key] = null;
|
||||
DestinationTypeConverterCache[key] = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
// gets the underlying type of a nullable type, or null if the type is not nullable
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static Type GetCachedGenericNullableType(Type type)
|
||||
private static Type? GetCachedGenericNullableType(Type type)
|
||||
{
|
||||
if (NullableGenericCache.TryGetValue(type, out var underlyingType))
|
||||
{
|
||||
@@ -732,11 +734,12 @@ namespace Umbraco.Extensions
|
||||
|
||||
if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
Type underlying = Nullable.GetUnderlyingType(type);
|
||||
Type? underlying = Nullable.GetUnderlyingType(type);
|
||||
return NullableGenericCache[type] = underlying;
|
||||
}
|
||||
|
||||
return NullableGenericCache[type] = null;
|
||||
NullableGenericCache[type] = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
// gets an IConvertible from source to target type, or null if none exists
|
||||
|
||||
@@ -523,7 +523,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, at a level lesser or equal to the specified level.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content, int maxLevel)
|
||||
public static IPublishedContent? Ancestor(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.EnumerateAncestors(false).FirstOrDefault(x => x.Level <= maxLevel);
|
||||
}
|
||||
@@ -535,7 +535,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="contentTypeAlias">The content type alias.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent Ancestor(this IPublishedContent content, string contentTypeAlias)
|
||||
public static IPublishedContent? Ancestor(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.EnumerateAncestors(false).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
@@ -547,7 +547,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The nearest (in down-top order) ancestor of the content, of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. May return <c>null</c>.</remarks>
|
||||
public static T Ancestor<T>(this IPublishedContent content)
|
||||
public static T? Ancestor<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors<T>().FirstOrDefault();
|
||||
@@ -562,7 +562,7 @@ namespace Umbraco.Extensions
|
||||
/// <returns>The ancestor of the content, at the specified level and of the specified content type.</returns>
|
||||
/// <remarks>Does not consider the content itself. If the ancestor at the specified level is
|
||||
/// not of the specified type, returns <c>null</c>.</remarks>
|
||||
public static T Ancestor<T>(this IPublishedContent content, int maxLevel)
|
||||
public static T? Ancestor<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Ancestors<T>(maxLevel).FirstOrDefault();
|
||||
@@ -586,7 +586,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, at a level lesser or equal to the specified level.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its level. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content, int maxLevel)
|
||||
public static IPublishedContent? AncestorOrSelf(this IPublishedContent content, int maxLevel)
|
||||
{
|
||||
return content.EnumerateAncestors(true).FirstOrDefault(x => x.Level <= maxLevel);
|
||||
}
|
||||
@@ -598,7 +598,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="contentTypeAlias">The content type.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, of the specified content type.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its content type. May return <c>null</c>.</remarks>
|
||||
public static IPublishedContent AncestorOrSelf(this IPublishedContent content, string contentTypeAlias)
|
||||
public static IPublishedContent? AncestorOrSelf(this IPublishedContent content, string contentTypeAlias)
|
||||
{
|
||||
return content.EnumerateAncestors(true).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
@@ -610,7 +610,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="content">The content.</param>
|
||||
/// <returns>The content or its nearest (in down-top order) ancestor, of the specified content type.</returns>
|
||||
/// <remarks>May or may not return the content itself depending on its content type. May return <c>null</c>.</remarks>
|
||||
public static T AncestorOrSelf<T>(this IPublishedContent content)
|
||||
public static T? AncestorOrSelf<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf<T>().FirstOrDefault();
|
||||
@@ -623,7 +623,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="maxLevel">The level.</param>
|
||||
/// <returns></returns>
|
||||
public static T AncestorOrSelf<T>(this IPublishedContent content, int maxLevel)
|
||||
public static T? AncestorOrSelf<T>(this IPublishedContent content, int maxLevel)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorsOrSelf<T>(maxLevel).FirstOrDefault();
|
||||
@@ -817,17 +817,17 @@ namespace Umbraco.Extensions
|
||||
return content.DescendantsOrSelf(variationContextAccessor, level, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null)
|
||||
public static IPublishedContent? Descendant(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent Descendant(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null)
|
||||
public static IPublishedContent? Descendant(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, false, culture).FirstOrDefault(x => x.Level == level);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null)
|
||||
public static IPublishedContent? DescendantOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, false, culture).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
@@ -849,12 +849,12 @@ namespace Umbraco.Extensions
|
||||
return content;
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null)
|
||||
public static IPublishedContent? DescendantOrSelf(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, int level, string? culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, true, culture).FirstOrDefault(x => x.Level == level);
|
||||
}
|
||||
|
||||
public static IPublishedContent DescendantOrSelfOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null)
|
||||
public static IPublishedContent? DescendantOrSelfOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null)
|
||||
{
|
||||
return content.EnumerateDescendants(variationContextAccessor, true, culture).FirstOrDefault(x => x.ContentType.Alias.InvariantEquals(contentTypeAlias));
|
||||
}
|
||||
@@ -978,7 +978,7 @@ namespace Umbraco.Extensions
|
||||
return content.Children(variationContextAccessor, culture).OfType<T>();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null)
|
||||
public static IPublishedContent? FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
@@ -986,28 +986,28 @@ namespace Umbraco.Extensions
|
||||
/// <summary>
|
||||
/// Gets the first child of the content, of a given content type.
|
||||
/// </summary>
|
||||
public static IPublishedContent FirstChildOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null)
|
||||
public static IPublishedContent? FirstChildOfType(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string contentTypeAlias, string? culture = null)
|
||||
{
|
||||
return content.ChildrenOfType(variationContextAccessor, contentTypeAlias, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<IPublishedContent, bool> predicate, string? culture = null)
|
||||
public static IPublishedContent? FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<IPublishedContent, bool> predicate, string? culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, predicate, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static IPublishedContent FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Guid uniqueId, string? culture = null)
|
||||
public static IPublishedContent? FirstChild(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Guid uniqueId, string? culture = null)
|
||||
{
|
||||
return content.Children(variationContextAccessor, x => x.Key == uniqueId, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T FirstChild<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null)
|
||||
public static T? FirstChild<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, string? culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>(variationContextAccessor, culture).FirstOrDefault();
|
||||
}
|
||||
|
||||
public static T FirstChild<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<T, bool> predicate, string? culture = null)
|
||||
public static T? FirstChild<T>(this IPublishedContent content, IVariationContextAccessor variationContextAccessor, Func<T, bool> predicate, string? culture = null)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.Children<T>(variationContextAccessor, culture).FirstOrDefault(predicate);
|
||||
@@ -1149,7 +1149,7 @@ namespace Umbraco.Extensions
|
||||
/// <remarks>
|
||||
/// This is the same as calling <see cref="Umbraco.Web.PublishedContentExtensions.AncestorOrSelf(IPublishedContent, int)" /> with <c>maxLevel</c> set to 1.
|
||||
/// </remarks>
|
||||
public static IPublishedContent Root(this IPublishedContent content)
|
||||
public static IPublishedContent? Root(this IPublishedContent content)
|
||||
{
|
||||
return content.AncestorOrSelf(1);
|
||||
}
|
||||
@@ -1165,7 +1165,7 @@ namespace Umbraco.Extensions
|
||||
/// <remarks>
|
||||
/// This is the same as calling <see cref="Umbraco.Web.PublishedContentExtensions.AncestorOrSelf{T}(IPublishedContent, int)" /> with <c>maxLevel</c> set to 1.
|
||||
/// </remarks>
|
||||
public static T Root<T>(this IPublishedContent content)
|
||||
public static T? Root<T>(this IPublishedContent content)
|
||||
where T : class, IPublishedContent
|
||||
{
|
||||
return content.AncestorOrSelf<T>(1);
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
|
||||
var valueConverted = value.TryConvertTo<T>();
|
||||
if (valueConverted)
|
||||
if (valueConverted.Success.HasValue && valueConverted.Success.Value)
|
||||
{
|
||||
return valueConverted.Result;
|
||||
}
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
|
||||
var noValueConverted = noValue.TryConvertTo<T>();
|
||||
if (noValueConverted)
|
||||
if (noValueConverted.Success.HasValue && noValueConverted.Success.Value)
|
||||
{
|
||||
return noValueConverted.Result;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
var nodeIds = path.Split(Constants.CharArrays.Comma, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(x => int.TryParse(x, NumberStyles.Integer, CultureInfo.InvariantCulture, out var output) ? Attempt<int>.Succeed(output) : Attempt<int>.Fail())
|
||||
.Where(x => x.Success)
|
||||
.Where(x => x.Success ?? false)
|
||||
.Select(x=>x.Result)
|
||||
.Reverse()
|
||||
.ToArray();
|
||||
@@ -393,7 +393,7 @@ namespace Umbraco.Extensions
|
||||
/// <returns>The enum try parse.</returns>
|
||||
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "By Design")]
|
||||
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#", Justification = "By Design")]
|
||||
public static bool EnumTryParse<T>(this string strType, bool ignoreCase, out T result)
|
||||
public static bool EnumTryParse<T>(this string strType, bool ignoreCase, out T? result)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -498,7 +498,7 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
public static string FromUrlBase64(this string input)
|
||||
public static string? FromUrlBase64(this string input)
|
||||
{
|
||||
if (input == null) throw new ArgumentNullException(nameof(input));
|
||||
|
||||
@@ -522,9 +522,9 @@ namespace Umbraco.Extensions
|
||||
/// <param name="format">The format.</param>
|
||||
/// <param name="args">The args.</param>
|
||||
/// <returns></returns>
|
||||
public static string InvariantFormat(this string format, params object[] args)
|
||||
public static string InvariantFormat(this string? format, params object?[] args)
|
||||
{
|
||||
return String.Format(CultureInfo.InvariantCulture, format, args);
|
||||
return string.Format(CultureInfo.InvariantCulture, format ?? string.Empty, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -548,7 +548,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="compare">The compare.</param>
|
||||
/// <param name="compareTo">The compare to.</param>
|
||||
/// <returns></returns>
|
||||
public static bool InvariantEquals(this string compare, string compareTo)
|
||||
public static bool InvariantEquals(this string compare, string? compareTo)
|
||||
{
|
||||
return String.Equals(compare, compareTo, StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
@@ -590,9 +590,9 @@ namespace Umbraco.Extensions
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="val"></param>
|
||||
/// <returns></returns>
|
||||
public static T ParseInto<T>(this string val)
|
||||
public static T? ParseInto<T>(this string val)
|
||||
{
|
||||
return (T)val.ParseInto(typeof(T));
|
||||
return (T?)val.ParseInto(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -601,7 +601,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="val"></param>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
public static object ParseInto(this string val, Type type)
|
||||
public static object? ParseInto(this string val, Type type)
|
||||
{
|
||||
if (string.IsNullOrEmpty(val) == false)
|
||||
{
|
||||
@@ -641,10 +641,15 @@ namespace Umbraco.Extensions
|
||||
/// <param name="str">Refers to itself</param>
|
||||
/// <param name="hashType">String with the hash type. See remarks section of the CryptoConfig Class in MSDN docs for a list of possible values.</param>
|
||||
/// <returns>The hashed string</returns>
|
||||
private static string GenerateHash(this string str, string hashType)
|
||||
private static string GenerateHash(this string str, string? hashType)
|
||||
{
|
||||
HashAlgorithm? hasher = null;
|
||||
//create an instance of the correct hashing provider based on the type passed in
|
||||
var hasher = HashAlgorithm.Create(hashType);
|
||||
if (hashType is not null)
|
||||
{
|
||||
hasher = HashAlgorithm.Create(hashType);
|
||||
}
|
||||
|
||||
if (hasher == null) throw new InvalidOperationException("No hashing type found by name " + hashType);
|
||||
using (hasher)
|
||||
{
|
||||
@@ -1184,7 +1189,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
algorithm.TransformBlock(namespaceBytes, 0, namespaceBytes.Length, null, 0);
|
||||
algorithm.TransformFinalBlock(nameBytes, 0, nameBytes.Length);
|
||||
hash = algorithm.Hash;
|
||||
hash = algorithm.Hash!;
|
||||
}
|
||||
|
||||
// most bytes from the hash are copied straight to the bytes of the new GUID (steps 5-7, 9, 11-12)
|
||||
@@ -1221,7 +1226,7 @@ namespace Umbraco.Extensions
|
||||
/// <summary>
|
||||
/// Turns an null-or-whitespace string into a null string.
|
||||
/// </summary>
|
||||
public static string NullOrWhiteSpaceAsNull(this string text)
|
||||
public static string? NullOrWhiteSpaceAsNull(this string text)
|
||||
=> string.IsNullOrWhiteSpace(text) ? null : text;
|
||||
|
||||
|
||||
@@ -1236,7 +1241,7 @@ namespace Umbraco.Extensions
|
||||
return string.IsNullOrWhiteSpace(path) == false
|
||||
&& path.IndexOfAny(Path.GetInvalidPathChars().ToArray()) == -1
|
||||
&& Path.IsPathRooted(path)
|
||||
&& Path.GetPathRoot(path).Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) == false;
|
||||
&& Path.GetPathRoot(path)?.Equals(Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal) == false;
|
||||
}
|
||||
|
||||
// FORMAT STRINGS
|
||||
|
||||
@@ -15,14 +15,14 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
public static class TypeExtensions
|
||||
{
|
||||
public static object GetDefaultValue(this Type t)
|
||||
public static object? GetDefaultValue(this Type t)
|
||||
{
|
||||
return t.IsValueType
|
||||
? Activator.CreateInstance(t)
|
||||
: null;
|
||||
}
|
||||
|
||||
internal static MethodInfo GetGenericMethod(this Type type, string name, params Type[] parameterTypes)
|
||||
internal static MethodInfo? GetGenericMethod(this Type type, string name, params Type[] parameterTypes)
|
||||
{
|
||||
var methods = type.GetMethods().Where(method => method.Name == name);
|
||||
|
||||
@@ -75,12 +75,12 @@ namespace Umbraco.Extensions
|
||||
return true;
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetBaseTypes(this Type type, bool andSelf)
|
||||
public static IEnumerable<Type?> GetBaseTypes(this Type? type, bool andSelf)
|
||||
{
|
||||
if (andSelf)
|
||||
yield return type;
|
||||
|
||||
while ((type = type.BaseType) != null)
|
||||
while ((type = type?.BaseType) != null)
|
||||
yield return type;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ namespace Umbraco.Extensions
|
||||
/// </returns>
|
||||
public static bool IsOfGenericType(this Type type, Type genericType)
|
||||
{
|
||||
Type[] args;
|
||||
Type[]? args;
|
||||
return type.TryGetGenericArguments(genericType, out args);
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Umbraco.Extensions
|
||||
/// <param name="genericType"></param>
|
||||
/// <param name="genericArgType"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryGetGenericArguments(this Type type, Type genericType, out Type[] genericArgType)
|
||||
public static bool TryGetGenericArguments(this Type type, Type genericType, out Type[]? genericArgType)
|
||||
{
|
||||
if (type == null)
|
||||
{
|
||||
@@ -147,7 +147,7 @@ namespace Umbraco.Extensions
|
||||
throw new ArgumentException("genericType must be a generic type");
|
||||
}
|
||||
|
||||
Func<Type, Type, Type[]> checkGenericType = (@int, t) =>
|
||||
Func<Type, Type, Type[]?> checkGenericType = (@int, t) =>
|
||||
{
|
||||
if (@int.IsGenericType)
|
||||
{
|
||||
@@ -313,34 +313,34 @@ namespace Umbraco.Extensions
|
||||
return typeof(TInterface).IsAssignableFrom(type);
|
||||
}
|
||||
|
||||
public static TAttribute FirstAttribute<TAttribute>(this Type type)
|
||||
public static TAttribute? FirstAttribute<TAttribute>(this Type type)
|
||||
{
|
||||
return type.FirstAttribute<TAttribute>(true);
|
||||
}
|
||||
|
||||
public static TAttribute FirstAttribute<TAttribute>(this Type type, bool inherit)
|
||||
public static TAttribute? FirstAttribute<TAttribute>(this Type type, bool inherit)
|
||||
{
|
||||
var attrs = type.GetCustomAttributes(typeof(TAttribute), inherit);
|
||||
return (TAttribute)(attrs.Length > 0 ? attrs[0] : null);
|
||||
return (TAttribute?)(attrs.Length > 0 ? attrs[0] : null);
|
||||
}
|
||||
|
||||
public static TAttribute FirstAttribute<TAttribute>(this PropertyInfo propertyInfo)
|
||||
public static TAttribute? FirstAttribute<TAttribute>(this PropertyInfo propertyInfo)
|
||||
{
|
||||
return propertyInfo.FirstAttribute<TAttribute>(true);
|
||||
}
|
||||
|
||||
public static TAttribute FirstAttribute<TAttribute>(this PropertyInfo propertyInfo, bool inherit)
|
||||
public static TAttribute? FirstAttribute<TAttribute>(this PropertyInfo propertyInfo, bool inherit)
|
||||
{
|
||||
var attrs = propertyInfo.GetCustomAttributes(typeof(TAttribute), inherit);
|
||||
return (TAttribute)(attrs.Length > 0 ? attrs[0] : null);
|
||||
return (TAttribute?)(attrs.Length > 0 ? attrs[0] : null);
|
||||
}
|
||||
|
||||
public static IEnumerable<TAttribute> MultipleAttribute<TAttribute>(this PropertyInfo propertyInfo)
|
||||
public static IEnumerable<TAttribute>? MultipleAttribute<TAttribute>(this PropertyInfo propertyInfo)
|
||||
{
|
||||
return propertyInfo.MultipleAttribute<TAttribute>(true);
|
||||
}
|
||||
|
||||
public static IEnumerable<TAttribute> MultipleAttribute<TAttribute>(this PropertyInfo propertyInfo, bool inherit)
|
||||
public static IEnumerable<TAttribute>? MultipleAttribute<TAttribute>(this PropertyInfo propertyInfo, bool inherit)
|
||||
{
|
||||
var attrs = propertyInfo.GetCustomAttributes(typeof(TAttribute), inherit);
|
||||
return (attrs.Length > 0 ? attrs.ToList().ConvertAll(input => (TAttribute)input) : null);
|
||||
@@ -389,8 +389,8 @@ namespace Umbraco.Extensions
|
||||
var t = c;
|
||||
while (t != typeof(object))
|
||||
{
|
||||
if (t.IsGenericType && t.GetGenericTypeDefinition() == type) return true;
|
||||
t = t.BaseType;
|
||||
if (t is not null && t.IsGenericType && t.GetGenericTypeDefinition() == type) return true;
|
||||
t = t?.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,7 +403,7 @@ namespace Umbraco.Extensions
|
||||
/// </summary>
|
||||
/// <param name="type">the source type</param>
|
||||
/// <returns></returns>
|
||||
public static Type GetEnumeratedType(this Type type)
|
||||
public static Type? GetEnumeratedType(this Type type)
|
||||
{
|
||||
if (typeof(IEnumerable).IsAssignableFrom(type) == false)
|
||||
return null;
|
||||
@@ -420,7 +420,7 @@ namespace Umbraco.Extensions
|
||||
return null;
|
||||
}
|
||||
|
||||
public static T GetCustomAttribute<T>(this Type type, bool inherit)
|
||||
public static T? GetCustomAttribute<T>(this Type type, bool inherit)
|
||||
where T : Attribute
|
||||
{
|
||||
return type.GetCustomAttributes<T>(inherit).SingleOrDefault();
|
||||
|
||||
@@ -154,7 +154,7 @@ namespace Umbraco.Extensions
|
||||
return new Uri(baseUri.GetLeftPart(UriPartial.Authority) + uri.GetSafeAbsolutePath() + uri.GetSafeQuery());
|
||||
}
|
||||
|
||||
static string GetSafeQuery(this Uri uri)
|
||||
static string? GetSafeQuery(this Uri uri)
|
||||
{
|
||||
if (uri.IsAbsoluteUri)
|
||||
return uri.Query;
|
||||
|
||||
@@ -15,11 +15,11 @@ namespace Umbraco.Extensions
|
||||
|
||||
public static Task WaitOneAsync(this WaitHandle handle, int millisecondsTimeout = Timeout.Infinite)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
var tcs = new TaskCompletionSource<object?>();
|
||||
var callbackHandleInitLock = new object();
|
||||
lock (callbackHandleInitLock)
|
||||
{
|
||||
RegisteredWaitHandle callbackHandle = null;
|
||||
RegisteredWaitHandle? callbackHandle = null;
|
||||
// ReSharper disable once RedundantAssignment
|
||||
callbackHandle = ThreadPool.RegisterWaitForSingleObject(
|
||||
handle,
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Extensions
|
||||
{
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
callbackHandle.Unregister(null);
|
||||
callbackHandle?.Unregister(null);
|
||||
}
|
||||
},
|
||||
/*state:*/ null,
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
public static XmlNodeList? SelectNodes(this XmlNode source, string expression, IEnumerable<XPathVariable>? variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
@@ -53,7 +53,7 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable> variables)
|
||||
public static XmlNodeList? SelectNodes(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable>? variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectNodes(source, expression, av);
|
||||
@@ -71,12 +71,12 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
public static XmlNodeList? SelectNodes(this XmlNode source, string? expression, params XPathVariable[]? variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
return source.SelectNodes(expression ?? "");
|
||||
|
||||
var iterator = source.CreateNavigator().Select(expression, variables);
|
||||
var iterator = source.CreateNavigator()?.Select(expression ?? "", variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
@@ -92,12 +92,12 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, params XPathVariable[] variables)
|
||||
public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, params XPathVariable[]? variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectNodes(expression);
|
||||
|
||||
var iterator = source.CreateNavigator().Select(expression, variables);
|
||||
var iterator = source.CreateNavigator()?.Select(expression, variables);
|
||||
return XmlNodeListFactory.CreateNodeList(iterator);
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable> variables)
|
||||
public static XmlNode? SelectSingleNode(this XmlNode source, string expression, IEnumerable<XPathVariable>? variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
@@ -131,7 +131,7 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable> variables)
|
||||
public static XmlNode? SelectSingleNode(this XmlNode source, XPathExpression expression, IEnumerable<XPathVariable>? variables)
|
||||
{
|
||||
var av = variables == null ? null : variables.ToArray();
|
||||
return SelectSingleNode(source, expression, av);
|
||||
@@ -149,12 +149,12 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, string expression, params XPathVariable[] variables)
|
||||
public static XmlNode? SelectSingleNode(this XmlNode source, string expression, params XPathVariable[]? variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
|
||||
return SelectNodes(source, expression, variables).Cast<XmlNode>().FirstOrDefault();
|
||||
return SelectNodes(source, expression, variables)?.Cast<XmlNode>().FirstOrDefault();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -169,7 +169,7 @@ namespace Umbraco.Extensions
|
||||
/// value which itself is <c>null</c>, then variables are ignored.</para>
|
||||
/// <para>The XPath expression should reference variables as <c>$var</c>.</para>
|
||||
/// </remarks>
|
||||
public static XmlNode SelectSingleNode(this XmlNode source, XPathExpression expression, params XPathVariable[] variables)
|
||||
public static XmlNode? SelectSingleNode(this XmlNode source, XPathExpression expression, params XPathVariable[]? variables)
|
||||
{
|
||||
if (variables == null || variables.Length == 0 || variables[0] == null)
|
||||
return source.SelectSingleNode(expression);
|
||||
@@ -211,7 +211,7 @@ namespace Umbraco.Extensions
|
||||
///// </summary>
|
||||
///// <param name="xElement"></param>
|
||||
///// <returns></returns>
|
||||
public static XmlNode ToXmlElement(this XContainer xElement)
|
||||
public static XmlNode? ToXmlElement(this XContainer xElement)
|
||||
{
|
||||
var xmlDocument = new XmlDocument();
|
||||
using (var xmlReader = xElement.CreateReader())
|
||||
@@ -235,7 +235,7 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
public static T RequiredAttributeValue<T>(this XElement xml, string attributeName)
|
||||
public static T? RequiredAttributeValue<T>(this XElement xml, string attributeName)
|
||||
{
|
||||
if (xml == null)
|
||||
{
|
||||
@@ -247,14 +247,14 @@ namespace Umbraco.Extensions
|
||||
throw new InvalidOperationException($"{attributeName} not found in xml");
|
||||
}
|
||||
|
||||
XAttribute attribute = xml.Attribute(attributeName);
|
||||
XAttribute? attribute = xml.Attribute(attributeName);
|
||||
if (attribute is null)
|
||||
{
|
||||
throw new InvalidOperationException($"{attributeName} not found in xml");
|
||||
}
|
||||
|
||||
Attempt<T> result = attribute.Value.TryConvertTo<T>();
|
||||
if (result.Success)
|
||||
if (result.Success.HasValue && result.Success.Value)
|
||||
{
|
||||
return result.Result;
|
||||
}
|
||||
@@ -262,7 +262,7 @@ namespace Umbraco.Extensions
|
||||
throw new InvalidOperationException($"{attribute.Value} attribute value cannot be converted to {typeof(T)}");
|
||||
}
|
||||
|
||||
public static T AttributeValue<T>(this XElement xml, string attributeName)
|
||||
public static T? AttributeValue<T>(this XElement xml, string attributeName)
|
||||
{
|
||||
if (xml == null) throw new ArgumentNullException("xml");
|
||||
if (xml.HasAttributes == false) return default(T);
|
||||
@@ -270,15 +270,15 @@ namespace Umbraco.Extensions
|
||||
if (xml.Attribute(attributeName) == null)
|
||||
return default(T);
|
||||
|
||||
var val = xml.Attribute(attributeName).Value;
|
||||
var val = xml.Attribute(attributeName)?.Value;
|
||||
var result = val.TryConvertTo<T>();
|
||||
if (result.Success)
|
||||
if (result.Success.HasValue && result.Success.Value)
|
||||
return result.Result;
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static T AttributeValue<T>(this XmlNode xml, string attributeName)
|
||||
public static T? AttributeValue<T>(this XmlNode xml, string attributeName)
|
||||
{
|
||||
if (xml == null) throw new ArgumentNullException("xml");
|
||||
if (xml.Attributes == null) return default(T);
|
||||
@@ -286,15 +286,15 @@ namespace Umbraco.Extensions
|
||||
if (xml.Attributes[attributeName] == null)
|
||||
return default(T);
|
||||
|
||||
var val = xml.Attributes[attributeName].Value;
|
||||
var val = xml.Attributes[attributeName]?.Value;
|
||||
var result = val.TryConvertTo<T>();
|
||||
if (result.Success)
|
||||
if (result.Success.HasValue && result.Success.Value)
|
||||
return result.Result;
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
public static XElement GetXElement(this XmlNode node)
|
||||
public static XElement? GetXElement(this XmlNode node)
|
||||
{
|
||||
XDocument xDoc = new XDocument();
|
||||
using (XmlWriter xmlWriter = xDoc.CreateWriter())
|
||||
@@ -302,7 +302,7 @@ namespace Umbraco.Extensions
|
||||
return xDoc.Root;
|
||||
}
|
||||
|
||||
public static XmlNode GetXmlNode(this XContainer element)
|
||||
public static XmlNode? GetXmlNode(this XContainer element)
|
||||
{
|
||||
using (var xmlReader = element.CreateReader())
|
||||
{
|
||||
@@ -312,9 +312,15 @@ namespace Umbraco.Extensions
|
||||
}
|
||||
}
|
||||
|
||||
public static XmlNode GetXmlNode(this XContainer element, XmlDocument xmlDoc)
|
||||
public static XmlNode? GetXmlNode(this XContainer element, XmlDocument xmlDoc)
|
||||
{
|
||||
return xmlDoc.ImportNode(element.GetXmlNode(), true);
|
||||
var node = element.GetXmlNode();
|
||||
if (node is not null)
|
||||
{
|
||||
return xmlDoc.ImportNode(node, true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// this exists because
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Cms.Core.Xml
|
||||
/// <remarks>The underlying XML store used to issue the query must be
|
||||
/// an object inheriting <see cref="XmlNode"/>, such as
|
||||
/// <see cref="XmlDocument"/>.</remarks>
|
||||
public static XmlNodeList CreateNodeList(XPathNodeIterator iterator)
|
||||
public static XmlNodeList CreateNodeList(XPathNodeIterator? iterator)
|
||||
{
|
||||
return new XmlNodeListIterator(iterator);
|
||||
}
|
||||
@@ -34,12 +34,12 @@ namespace Umbraco.Cms.Core.Xml
|
||||
|
||||
private class XmlNodeListIterator : XmlNodeList
|
||||
{
|
||||
readonly XPathNodeIterator _iterator;
|
||||
readonly XPathNodeIterator? _iterator;
|
||||
readonly IList<XmlNode> _nodes = new List<XmlNode>();
|
||||
|
||||
public XmlNodeListIterator(XPathNodeIterator iterator)
|
||||
public XmlNodeListIterator(XPathNodeIterator? iterator)
|
||||
{
|
||||
_iterator = iterator.Clone();
|
||||
_iterator = iterator?.Clone();
|
||||
}
|
||||
|
||||
public override System.Collections.IEnumerator GetEnumerator()
|
||||
@@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Xml
|
||||
return new XmlNodeListEnumerator(this);
|
||||
}
|
||||
|
||||
public override XmlNode Item(int index)
|
||||
public override XmlNode? Item(int index)
|
||||
{
|
||||
|
||||
if (index >= _nodes.Count)
|
||||
@@ -73,7 +73,7 @@ namespace Umbraco.Cms.Core.Xml
|
||||
/// </summary>
|
||||
private void ReadToEnd()
|
||||
{
|
||||
while (_iterator.MoveNext())
|
||||
while (_iterator is not null && _iterator.MoveNext())
|
||||
{
|
||||
var node = _iterator.Current as IHasXmlNode;
|
||||
// Check IHasXmlNode interface.
|
||||
@@ -92,7 +92,7 @@ namespace Umbraco.Cms.Core.Xml
|
||||
{
|
||||
while (_nodes.Count <= to)
|
||||
{
|
||||
if (_iterator.MoveNext())
|
||||
if (_iterator is not null && _iterator.MoveNext())
|
||||
{
|
||||
var node = _iterator.Current as IHasXmlNode;
|
||||
// Check IHasXmlNode interface.
|
||||
@@ -159,7 +159,7 @@ namespace Umbraco.Cms.Core.Xml
|
||||
return true;
|
||||
}
|
||||
|
||||
object System.Collections.IEnumerator.Current
|
||||
object? System.Collections.IEnumerator.Current
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user