Last active
December 9, 2021 23:04
-
-
Save apples/f7c29aa5fb923f07a7d00aabeb5f1f0a to your computer and use it in GitHub Desktop.
C# Shallow copy function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
namespace Mealplan | |
{ | |
public static class Copy | |
{ | |
public static T Shallow<T>(object src, Type? srcType = null, object? defaultValues = null, object? forceValues = null) | |
where T : new() | |
{ | |
var dest = new T(); | |
var nullabilityContext = new NullabilityInfoContext(); | |
Type typeT = typeof(T); | |
Type typeU = srcType ?? src.GetType(); | |
Type? typeD = defaultValues?.GetType(); | |
Type? typeF = forceValues?.GetType(); | |
foreach (var prop in typeT.GetProperties()) | |
{ | |
var nullable = nullabilityContext.Create(prop).WriteState != NullabilityState.NotNull; | |
if (typeF?.GetProperty(prop.Name) is PropertyInfo forceValuesProp) | |
{ | |
var forcedValue = forceValuesProp.GetValue(forceValues); | |
if (forcedValue == null && !nullable) | |
{ | |
throw new InvalidOperationException($"Property {prop.Name} must not be null, but forceValues provided a null value."); | |
} | |
prop.SetValue(dest, forcedValue); | |
} | |
else if (typeU.GetProperty(prop.Name) is PropertyInfo srcProp) | |
{ | |
var value = srcProp.GetValue(src); | |
if (value != null) | |
{ | |
prop.SetValue(dest, value); | |
} | |
else if (typeD?.GetProperty(prop.Name) is PropertyInfo defaultValuesProp) | |
{ | |
var defaultValue = defaultValuesProp?.GetValue(defaultValues); | |
if (defaultValue == null && !nullable) | |
{ | |
throw new InvalidOperationException($"Property {prop.Name} must not be null, but neither {nameof(src)} nor {nameof(defaultValues)} provided a non-null value."); | |
} | |
prop.SetValue(dest, defaultValue); | |
} | |
else | |
{ | |
if (defaultValues != null) | |
{ | |
throw new InvalidOperationException($"Property {prop.Name} must not be null, but {nameof(src)} did not provide a non-null value, and {nameof(defaultValues)} did not provide any value at all."); | |
} | |
else | |
{ | |
throw new InvalidOperationException($"Property {prop.Name} must not be null, but {nameof(src)} did not provide a non-null value, and {nameof(defaultValues)} was not provided."); | |
} | |
} | |
} | |
} | |
return dest; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment