Betrachten Sie den folgenden Beispielcode:
class SampleClass
{
public long SomeProperty { get; set; }
}
public void SetValue(SampleClass instance, decimal value)
{
// value is of type decimal, but is in reality a natural number => cast
instance.SomeProperty = (long)value;
}
Jetzt muss ich etwas Ähnliches durch Nachdenken tun:
void SetValue(PropertyInfo info, object instance, object value)
{
// throws System.ArgumentException: Decimal can not be converted to Int64
info.SetValue(instance, value)
}
Beachten Sie, dass ich nicht davon ausgehen kann, dass PropertyInfo immer eine lange Zahl darstellt, und dass dieser Wert auch nicht immer eine Dezimalzahl ist. Ich weiß jedoch, dass der Wert für diese Eigenschaft in den richtigen Typ umgewandelt werden kann.
Wie kann ich den Parameter 'value' durch Reflektion in den von der PropertyInfo-Instanz dargestellten Typ konvertieren?
c#
reflection
casting
jeroenh
quelle
quelle
Convert.ChangeType(value, property.PropertyType);
dies immer noch fehlschlagen kann, wennvalue
dieIConvertible
Schnittstelle nicht implementiert wird. Zum Beispiel, wenninfo.PropertyType
es einigeIEnumerable
Die Antwort von Thomas funktioniert nur für Typen, die eine IConvertible-Schnittstelle implementieren:
Dieser Code kompiliert einen linq-Ausdruck, der das Unboxing (falls erforderlich) und die Konvertierung ausführt:
public static object Cast(this Type Type, object data) { var DataParam = Expression.Parameter(typeof(object), "data"); var Body = Expression.Block(Expression.Convert(Expression.Convert(DataParam, data.GetType()), Type)); var Run = Expression.Lambda(Body, DataParam).Compile(); var ret = Run.DynamicInvoke(data); return ret; }
Der resultierende Lambda-Ausdruck entspricht (TOut) (TIn) -Daten, wobei TIn der Typ der Originaldaten und TOut der angegebene Typ ist
quelle
IEnumerable<object>
(wo diese Objekte Strings sind)IEnumerable<string>
. Leider bekomme ich Fehler wieUnable to cast object of type 'System.Collections.Generic.IEnumerable'1[System.Object]' to type 'System.Collections.Generic.IEnumerable'1[System.String]'.
Die Antwort von Thomas ist richtig, aber ich dachte, ich würde meine Feststellung hinzufügen, dass Convert.ChangeType die Konvertierung in nullfähige Typen nicht handhabt. Um nullbare Typen zu behandeln, habe ich den folgenden Code verwendet:
void SetValue(PropertyInfo info, object instance, object value) { var targetType = info.PropertyType.IsNullableType() ? Nullable.GetUnderlyingType(info.PropertyType) : info.PropertyType; var convertedValue = Convert.ChangeType(value, targetType); info.SetValue(instance, convertedValue, null); }
Dieser Code verwendet die folgende Erweiterungsmethode:
public static class TypeExtensions { public static bool IsNullableType(this Type type) { return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)); }
quelle
Als Beitrag zu jeroenhs Antwort möchte ich hinzufügen, dass Convert.ChangeType mit einem Nullwert abstürzt. Die Zeile zum Abrufen des konvertierten Werts sollte also lauten:
var convertedValue = value == null ? null : Convert.ChangeType(value, targetType);
quelle
Wenn der Typ eine Nullable Guid ist, funktioniert keine der oben vorgeschlagenen Lösungen. Es wird eine ungültige Besetzung von '
System.DBNull
' bis 'System.Guid
' Ausnahme ausgelöstConvert.ChangeType
So beheben Sie diese Änderung an:
var convertedValue = value == System.DBNull.Value ? null : Convert.ChangeType(value, targetType);
quelle
DBNull.Value
nurnull
beim Abrufen von Nullwerten aus der Datenbank über ADO.Net erhalten. Sie werden dasselbe zum Beispiel mit nullable int sehen.Dies ist eine sehr alte Frage, aber ich dachte, ich würde mich für ASP.NET Core Googler entscheiden.
Ist in ASP.NET Core
.IsNullableType()
(unter anderem) geschützt, sodass der Code etwas anders ist. Die Antwort von @ jeroenh wurde geändert, um in ASP.NET Core zu funktionieren:void SetValue(PropertyInfo info, object instance, object value) { Type proptype = info.PropertyType; if (proptype.IsGenericType && proptype.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { proptype = new NullableConverter(info.PropertyType).UnderlyingType; } var convertedValue = Convert.ChangeType(value, proptype); info.SetValue(instance, convertedValue); }
quelle