Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: mc sdk & sdk unit test #112

Merged
merged 9 commits into from
Jul 4, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/BasicAbility/Masa.Contrib.BasicAbility.Mc/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.Contrib.BasicAbility.Mc;

internal class Constants
{
public const string DEFAULT_CLIENT_NAME = "masa.contrib.basicability.mc";
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace System.Collections.Concurrent;

/// <summary>
/// Extension methods for Dictionary.
/// </summary>
public static class DictionaryExtensions
{
/// <summary>
/// This method is used to try to get a value in a dictionary if it does exists.
/// </summary>
/// <typeparam name="T">Type of the value</typeparam>
/// <param name="dictionary">The collection object</param>
/// <param name="key">Key</param>
/// <param name="value">Value of the key (or default value if key not exists)</param>
/// <returns>True if key does exists in the dictionary</returns>
internal static bool TryGetValue<T>(this IDictionary<string, object> dictionary, string key, out T value)
{
object valueObj;
if (dictionary.TryGetValue(key, out valueObj) && valueObj is T)
{
value = (T)valueObj;
return true;
}

value = default;
return false;
}

/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue? GetOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key)
{
return dictionary.TryGetValue(key, out var obj) ? obj : default;
}

/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue? GetOrDefault<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dictionary, TKey key)
{
return dictionary.TryGetValue(key, out var obj) ? obj : default;
}

/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue? GetOrDefault<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dictionary, TKey key)
{
return dictionary.TryGetValue(key, out var obj) ? obj : default;
}

/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, [NotNull] TKey key, Func<TKey, TValue> factory)
{
TValue obj;
if (dictionary.TryGetValue(key, out obj))
{
return obj;
}

return dictionary[key] = factory(key);
}

/// <summary>
/// Gets a value from the dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, [NotNull] TKey key, Func<TValue> factory)
{
return dictionary.GetOrAdd(key, k => factory());
}

/// <summary>
/// Gets a value from the concurrent dictionary with given key. Returns default value if can not find.
/// </summary>
/// <param name="dictionary">Concurrent dictionary to check and get</param>
/// <param name="key">Key to find the value</param>
/// <param name="factory">A factory method used to create the value if not found in the dictionary</param>
/// <typeparam name="TKey">Type of the key</typeparam>
/// <typeparam name="TValue">Type of the value</typeparam>
/// <returns>Value if found, default if can not found.</returns>
public static TValue GetOrAdd<TKey, TValue>(this ConcurrentDictionary<TKey, TValue> dictionary, [NotNull] TKey key, Func<TValue> factory)
{
return dictionary.GetOrAdd(key, k => factory());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace System.Collections.Concurrent;

public static class ExtraPropertiesExtensions
{
public static bool HasProperty(this ExtraPropertyDictionary source, string name)
{
return source.ContainsKey(name);
}

public static object GetProperty(this ExtraPropertyDictionary source, string name, object defaultValue = null)
{
return source.GetOrDefault(name)
?? defaultValue;
}

public static TProperty GetProperty<TProperty>(this ExtraPropertyDictionary source, string name, TProperty defaultValue = default)
{
var value = source.GetProperty(name);
if (value == null)
{
return defaultValue;
}

if (TypeHelper.IsPrimitiveExtended(typeof(TProperty), includeEnums: true))
{
var conversionType = typeof(TProperty);
if (TypeHelper.IsNullable(conversionType))
{
conversionType = conversionType.GetFirstGenericArgumentIfNullable();
}

if (conversionType == typeof(Guid))
{
return (TProperty)TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(value.ToString());
}

if (conversionType == typeof(DateTimeOffset))
{
return (TProperty)TypeDescriptor.GetConverter(conversionType).ConvertFromInvariantString(value.ToString());
}

return (TProperty)Convert.ChangeType(value?.ToString(), conversionType, CultureInfo.InvariantCulture);
}

throw new Exception("GetProperty<TProperty> does not support non-primitive types. Use non-generic GetProperty method and handle type casting manually.");
}

public static TSource SetProperty<TSource>(
this TSource source,
string name,
object value)
where TSource : ExtraPropertyDictionary
{
source[name] = value;

return source;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// Copyright (c) MASA Stack All rights reserved.
// Licensed under the MIT License. See LICENSE.txt in the project root for license information.

namespace Masa.Contrib.BasicAbility.Mc.Infrastructure.Helper;

public static class TypeHelper
{
private static readonly HashSet<Type> FloatingTypes = new HashSet<Type>
{
typeof(float),
typeof(double),
typeof(decimal)
};

private static readonly HashSet<Type> NonNullablePrimitiveTypes = new HashSet<Type>
{
typeof(byte),
typeof(short),
typeof(int),
typeof(long),
typeof(sbyte),
typeof(ushort),
typeof(uint),
typeof(ulong),
typeof(bool),
typeof(float),
typeof(decimal),
typeof(DateTime),
typeof(DateTimeOffset),
typeof(TimeSpan),
typeof(Guid)
};

public static bool IsNonNullablePrimitiveType(Type type)
{
return NonNullablePrimitiveTypes.Contains(type);
}

public static bool IsFunc(object obj)
{
if (obj == null)
{
return false;
}

var type = obj.GetType();
if (!type.GetTypeInfo().IsGenericType)
{
return false;
}

return type.GetGenericTypeDefinition() == typeof(Func<>);
}

public static bool IsFunc<TReturn>(object obj)
{
return obj != null && obj.GetType() == typeof(Func<TReturn>);
}

public static bool IsPrimitiveExtended(Type type, bool includeNullables = true, bool includeEnums = false)
{
if (IsPrimitiveExtendedInternal(type, includeEnums))
{
return true;
}

if (includeNullables && IsNullable(type) && type.GenericTypeArguments.Any())
{
return IsPrimitiveExtendedInternal(type.GenericTypeArguments[0], includeEnums);
}

return false;
}

public static bool IsNullable(Type type)
{
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}

public static Type GetFirstGenericArgumentIfNullable(this Type t)
{
if (t.GetGenericArguments().Length > 0 && t.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return t.GetGenericArguments().FirstOrDefault();
}

return t;
}

private static bool IsPrimitiveExtendedInternal(Type type, bool includeEnums)
{
if (type.IsPrimitive)
{
return true;
}

if (includeEnums && type.IsEnum)
{
return true;
}

return type == typeof(string) ||
type == typeof(decimal) ||
type == typeof(DateTimeOffset) ||
type == typeof(DateTimeOffset) ||
type == typeof(TimeSpan) ||
type == typeof(Guid);
}

public static T? GetDefaultValue<T>()
{
return default;
}

public static object? GetDefaultValue(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}

return null;
}

public static bool IsFloatingType(Type type, bool includeNullable = true)
{
if (FloatingTypes.Contains(type))
{
return true;
}

if (includeNullable &&
IsNullable(type) &&
FloatingTypes.Contains(type.GenericTypeArguments[0]))
{
return true;
}

return false;
}

public static object ConvertFrom<TTargetType>(object value)
{
return ConvertFrom(typeof(TTargetType), value);
}

public static object ConvertFrom(Type targetType, object value)
{
return TypeDescriptor
.GetConverter(targetType)
.ConvertFrom(value);
}

public static Type StripNullable(Type type)
{
return IsNullable(type)
? type.GenericTypeArguments[0]
: type;
}

public static bool IsDefaultValue(object obj)
{
if (obj == null)
{
return true;
}

return obj.Equals(GetDefaultValue(obj.GetType()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Masa.Utils.Caller.HttpClient" Version="0.5.0-preview.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\BuildingBlocks\MASA.BuildingBlocks\src\BasicAbility\Masa.BuildingBlocks.BasicAbility.Mc\Masa.BuildingBlocks.BasicAbility.Mc.csproj" />
</ItemGroup>

</Project>
Loading