/* Verwendungsbeispiel
public class OBJ
{
public string Text { get; set; }
public Guid? Guid { get; set; }
}
// Instanz
var temp = new obj();
foreach(var prop in typeof(OBJ).GetProperties())
{
object newValue = null;
bool found = true;
// Welche Property?
switch(prop.Name)
{
case "Text": // Neuer Wert
newValue = "HELLO WORLD";
break;
case "Guid":
newValue = Guid.NewGuid();
break;
default:
found = false;
break;
}
if(found){
// Setzen
prop.SetValueNullableCorrected(temp, newValue);
}
}
*/
public static class Extension
/// <summary>
/// Legt den Instanzwert für die angegebene Property fest und passt die Werte (auch DBNull) auf den Typ der Property an (auch Nullable).
/// </summary>
/// <typeparam name="T">Die Zielinstanz der Property</typeparam>
/// <param name="info">Zielproperty in der Instanz</param>
/// <param name="instance">Zielinstanz</param>
/// <param name="value">Einzugebener Wert</param>
internal static void SetValueNullableCorrected<T>(this PropertyInfo info, T instance, object value)
{
// ggf. Instanz erstellen
if (instance == null)
instance = Activator.CreateInstance<T>();
// Typ der Property
var type = info.PropertyType;
// Nullable<Typ>?
if (type.IsGenericType)
{
if (type != value.GetType())
{
if (value == null || value == DBNull.Value)
{
info.SetValue(instance, null, null);
}
// Nullable<Typ> erzeugen und Wert eingeben
else
{
NullableConverter nC = new NullableConverter(info.PropertyType);
info.SetValue(instance, nC.ConvertFrom(value), null);
}
}
else
{
// Wenn DBNull dann default(type)
info.SetValue(instance, value == DBNull.Value ? Activator.CreateInstance(type) : value, null);
}
}
// Normale Typen?
else
{
if (value == DBNull.Value)
{
if (value.GetType().IsNullable())
{
info.SetValue(instance, null, null);
}
else
{
info.SetValue(instance, Activator.CreateInstance(type), null);
}
}
else
{
var val = Convert.ChangeType(value, type);
info.SetValue(instance, val, null);
}
}
}
/// <summary>
/// Prüft, ob ein Typ (null)-Werte annehmen kann oder nicht
/// </summary>
/// <param name="value">Typ, der geprüft werden soll</param>
/// <returns>Kann (null)-Werte annehmen (true) oder nicht (false)</returns>
internal static bool IsNullable(this Type realType)
{
if (!realType.IsValueType)
{
// kein Wertetyp, daher kann der Typ (null)-Werte annehmen
return true;
}
// Wenn Nullable.GetUnderlyingType() einen übergeordneten Typ ermitteln kann,
// bedeutet dies, dass dies ein Wertetyp ist, der (null)-Werte annehmen kann,
// z.B. bool?
return Nullable.GetUnderlyingType(realType) == realType;
}
}