copy of nested properties works now
This commit is contained in:
@@ -15,6 +15,8 @@ namespace zero.Core.Blueprints
|
||||
{
|
||||
public List<BlueprintField<T>> UnlockedFields { get; private set; } = new();
|
||||
|
||||
protected static string[] DefaultFields { get; set; } = new[] { "name", "alias", "key", "sort", "isActive", "hash", "languageId", "createdById", "createdDate", "lastModifiedById", "lastModifiedDate", "blueprint" };
|
||||
|
||||
|
||||
public Blueprint() : base(typeof(T))
|
||||
{
|
||||
@@ -40,8 +42,8 @@ namespace zero.Core.Blueprints
|
||||
}
|
||||
|
||||
// copy all properties which are synced from the blueprint to the model
|
||||
ObjectTraverser.CopyProperties(blueprint, model, model.Blueprint.Desync);
|
||||
ApplyDefaults(blueprint, model);
|
||||
ObjectCloner.CopyProperties(blueprint, model, DefaultFields.Union(model.Blueprint.Desync).ToArray());
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace zero.Core.Utils
|
||||
{
|
||||
public class ObjectCloner
|
||||
{
|
||||
const string SEPARATOR = ".";
|
||||
|
||||
static Type STRING_TYPE = typeof(string);
|
||||
|
||||
static ConcurrentDictionary<string, IEnumerable<PropertyInfo>> PublicPropertiesPerType { get; set; } = new();
|
||||
|
||||
|
||||
|
||||
public static T CopyProperties<T>(T source, T target, params string[] exceptions)
|
||||
{
|
||||
return CopyPropertiesInternal(source, target, null, exceptions);
|
||||
}
|
||||
|
||||
|
||||
static T CopyPropertiesInternal<T>(T source, T target, string keyPrefix = null, params string[] exceptions)
|
||||
{
|
||||
Type type = source.GetType();
|
||||
|
||||
if (!PublicPropertiesPerType.TryGetValue(type.FullName, out IEnumerable<PropertyInfo> properties))
|
||||
{
|
||||
properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(x => x.CanWrite);
|
||||
PublicPropertiesPerType.TryAdd(type.FullName, properties);
|
||||
}
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
{
|
||||
string propertyNameWithPrefix = CombineKey(SEPARATOR, keyPrefix, property.Name);
|
||||
|
||||
if (exceptions.Contains(propertyNameWithPrefix, StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object propertyValue = property.GetValue(source, null);
|
||||
|
||||
if (property.PropertyType.IsValueType || property.PropertyType.IsEnum || property.PropertyType.Equals(STRING_TYPE) || propertyValue == null || propertyValue is IEnumerable)
|
||||
{
|
||||
Console.WriteLine("copy: " + propertyNameWithPrefix);
|
||||
property.SetValue(target, propertyValue, null);
|
||||
}
|
||||
else if (property.PropertyType.IsClass)
|
||||
{
|
||||
string[] nestedExceptions = exceptions.Where(x => x.StartsWith(propertyNameWithPrefix, StringComparison.InvariantCultureIgnoreCase)).ToArray();
|
||||
property.SetValue(target, CopyPropertiesInternal(propertyValue, property.GetValue(target, null), propertyNameWithPrefix, nestedExceptions), null);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
private static string CombineKey(string sep, string key1, string key2)
|
||||
{
|
||||
if (String.IsNullOrEmpty(key1))
|
||||
{
|
||||
return key2;
|
||||
}
|
||||
return String.Join(sep, key1, key2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
@@ -238,36 +239,6 @@ namespace zero.Core.Utils
|
||||
}
|
||||
|
||||
|
||||
public static T CopyProperties<T>(T source, T target, params string[] exceptions)
|
||||
{
|
||||
Type sourceType = source.GetType();
|
||||
Type stringType = typeof(System.String);
|
||||
|
||||
foreach (PropertyInfo sourceProperty in sourceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
|
||||
{
|
||||
Console.WriteLine("key: " + sourceProperty.Name);
|
||||
|
||||
if (!sourceProperty.CanWrite || exceptions.Contains(sourceProperty.Name, StringComparer.InvariantCultureIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
object sourcePropertyValue = sourceProperty.GetValue(source, null);
|
||||
|
||||
if (sourceProperty.PropertyType.IsValueType || sourceProperty.PropertyType.IsEnum || sourceProperty.PropertyType.Equals(stringType) || sourcePropertyValue == null || sourcePropertyValue is ICollection)
|
||||
{
|
||||
sourceProperty.SetValue(target, sourcePropertyValue, null);
|
||||
}
|
||||
else if (sourceProperty.PropertyType.IsClass)
|
||||
{
|
||||
sourceProperty.SetValue(target, CopyProperties(sourcePropertyValue, sourceProperty.GetValue(target, null)), null);
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
|
||||
private static string CombineKey(string sep, string key1, string key2)
|
||||
{
|
||||
if (String.IsNullOrEmpty(key1))
|
||||
|
||||
Reference in New Issue
Block a user