Created
June 4, 2021 10:15
-
-
Save pitermarx/0932aa40ce84f391c332e93e59617e64 to your computer and use it in GitHub Desktop.
Cake Model Binding
This file contains hidden or 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.ComponentModel; | |
// Uses cake Configuration to bind a model | |
// Configuration values should come from | |
// 1 - CAKE_ prefixed env vars | |
// 2 - cake.config files | |
// 3 - cmdline arguments | |
class NaiveModelBinder | |
{ | |
private readonly Func<string, string> getValue; | |
private readonly Action<string> log; | |
public NaiveModelBinder(ICakeContext context) | |
{ | |
this.getValue = context.Configuration.GetValue; | |
this.log = context.Debug; | |
} | |
public T Bind<T>() | |
{ | |
log($"\nBinding configuration values to model {typeof(T).Name}"); | |
return (T)this.Bind(typeof(T)); | |
} | |
private object Bind(Type type, string prefix = "") | |
{ | |
var props = type.GetProperties(); | |
var instance = Activator.CreateInstance(type); | |
foreach (var prop in props) | |
{ | |
if (TryGetValue(prop.PropertyType, prop.Name, prefix, out var value)) | |
{ | |
if (prop.PropertyType == typeof(string) || !prop.PropertyType.IsClass) | |
{ | |
log($"{(prefix + prop.Name).Replace("_", ".")}={value}"); | |
} | |
prop.SetValue(instance, value); | |
} | |
} | |
return instance; | |
} | |
private bool TryGetValue(Type type, string name, string prefix, out object value) | |
{ | |
var stringValue = this.getValue(prefix + name); | |
if (type == typeof(string)) | |
{ | |
value = stringValue; | |
return stringValue != null; | |
} | |
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) | |
{ | |
return TryGetValue(Nullable.GetUnderlyingType(type), name, prefix, out value); | |
} | |
if (type.IsClass) | |
{ | |
value = Bind(type, prefix + name + "_"); | |
return true; | |
} | |
if (string.IsNullOrEmpty(stringValue)) | |
{ | |
value = null; | |
return false; | |
} | |
value = TypeDescriptor | |
.GetConverter(type) | |
.ConvertFromInvariantString(stringValue); | |
return true; | |
} | |
} | |
T Bind<T>() => new NaiveModelBinder(Context).Bind<T>(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example usage
