Skip to content

Instantly share code, notes, and snippets.

@apples
Last active December 9, 2021 23:04
Show Gist options
  • Save apples/f7c29aa5fb923f07a7d00aabeb5f1f0a to your computer and use it in GitHub Desktop.
Save apples/f7c29aa5fb923f07a7d00aabeb5f1f0a to your computer and use it in GitHub Desktop.
C# Shallow copy function
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