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(ObjectExtensions): add CreateInstanceWithCascade extension method #5491

Merged
merged 11 commits into from
Mar 2, 2025
2 changes: 1 addition & 1 deletion src/BootstrapBlazor/BootstrapBlazor.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">

<PropertyGroup>
<Version>9.4.3-beta03</Version>
<Version>9.4.3-beta04</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
6 changes: 3 additions & 3 deletions src/BootstrapBlazor/Components/Table/Table.razor.Edit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,11 @@ private TItem CreateInstance()
{
try
{
return Activator.CreateInstance<TItem>();
return ObjectExtensions.CreateInstanceWithCascade<TItem>();
}
catch (Exception)
catch (Exception ex)
{
throw new InvalidOperationException($"{typeof(TItem)} missing new() method. Please provider {nameof(CreateItemCallback)} create the {typeof(TItem)} instance. {typeof(TItem)} 未提供无参构造函数 new() 请通过 {nameof(CreateItemCallback)} 回调方法创建实例");
throw new InvalidOperationException($"{typeof(TItem)} missing new() method. Please provide {nameof(CreateItemCallback)} create the {typeof(TItem)} instance. {typeof(TItem)} 未提供无参构造函数 new() 请通过 {nameof(CreateItemCallback)} 回调方法创建实例", ex);
}
}

Expand Down
46 changes: 42 additions & 4 deletions src/BootstrapBlazor/Extensions/ObjectExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,14 @@ public static string GetTypeDesc(this Type t)
/// 字符串类型转换为其他数据类型
/// </summary>
/// <returns></returns>
public static bool TryConvertTo(this string? source, Type type, [MaybeNullWhen(false)] out object? val)
public static bool TryConvertTo(this string? source, Type type, out object? val)
{
var ret = true;
val = source;
if (type != typeof(string))
{
ret = false;
var methodInfo = Array.Find(typeof(ObjectExtensions).GetMethods(), m => m.Name == nameof(TryConvertTo) && m.IsGenericMethod);
var methodInfo = Array.Find(typeof(ObjectExtensions).GetMethods(), m => m is { Name: nameof(TryConvertTo), IsGenericMethod: true });
if (methodInfo != null)
{
methodInfo = methodInfo.MakeGenericMethod(type);
Expand All @@ -159,7 +159,7 @@ public static bool TryConvertTo(this string? source, Type type, [MaybeNullWhen(f
}

/// <summary>
///
/// Tries to convert the string representation of a value to a specified type.
/// </summary>
/// <typeparam name="TValue"></typeparam>
/// <param name="source"></param>
Expand Down Expand Up @@ -203,7 +203,7 @@ public static bool TryConvertTo<TValue>(this string? source, [MaybeNullWhen(fals
}

/// <summary>
/// 格式化为 文件大小与单位格式 字符串
/// Formats the file size into a string with appropriate units
/// </summary>
/// <param name="fileSize"></param>
/// <returns></returns>
Expand Down Expand Up @@ -237,4 +237,42 @@ internal static void Clone<TModel>(this TModel source, TModel item)
}
}
}

/// <summary>
/// Creates an instance of a type and ensures all class-type properties are initialized.
/// </summary>
/// <typeparam name="TItem">The type to create an instance of.</typeparam>
/// <returns>An instance of the specified type with initialized properties.</returns>
public static TItem CreateInstanceWithCascade<TItem>()
{
var instance = Activator.CreateInstance<TItem>();
instance!.EnsureInitialized();
return instance;
}

/// <summary>
/// Ensures that all class-type properties of the instance are initialized.
/// </summary>
/// <param name="instance">The instance to initialize properties for.</param>
private static void EnsureInitialized(this object instance)
{
// Reflection performance needs to be optimized here
foreach (var propertyInfo in instance.GetType().GetProperties().Where(p => p.PropertyType.IsClass && p.PropertyType != typeof(string)))
{
var type = propertyInfo.PropertyType;
var value = propertyInfo.GetValue(instance, null);
if (value is null)
{
var pv = CreateInstance(type);
propertyInfo.SetValue(instance, pv);
}
}
}

private static object? CreateInstance(Type type)
{
var instance = Activator.CreateInstance(type);
instance!.EnsureInitialized();
return instance;
}
}