2012-11-07 11 views
16

Mamy właściwość typu long?, która zostanie wypełniona przez int.Problem z konwersją typu podczas ustawiania właściwości poprzez odbicie

Działa to dobrze, kiedy po prostu ustawić właściwość bezpośrednio obj.Value = v; ale gdy próbuję i ustawić właściwości poprzez odbicie info.SetValue(obj, v, null); daje mi następujący wyjątek:

obiekt typu „System.Int32” nie może być skonwertowane na typ "System.Nullable`1 [System.Int64]".

Jest to uproszczony scenariusz:

class TestClass 
    { 
     public long? Value { get; set; } 
    } 

    [TestMethod] 
    public void TestMethod2() 
    { 
     TestClass obj = new TestClass(); 
     Type t = obj.GetType(); 

     PropertyInfo info = t.GetProperty("Value"); 
     int v = 1; 

     // This works 
     obj.Value = v; 

     // This does not work 
     info.SetValue(obj, v, null); 
    } 

Dlaczego nie działać, gdy ustawienie właściwości przez reflection natomiast działa podczas ustawiania właściwości bezpośrednio?

Odpowiedz

48

zobacz pełny artykuł: How to set value of a property using Reflection?

pełny kod jeśli ustawienie wartości dla wartości pustych typu

public static void SetValue(object inputObject, string propertyName, object propertyVal) 
{ 
    //find out the type 
    Type type = inputObject.GetType(); 

    //get the property information based on the type 
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(propertyName); 

    //find the property type 
    Type propertyType = propertyInfo.PropertyType; 

    //Convert.ChangeType does not handle conversion to nullable types 
    //if the property type is nullable, we need to get the underlying type of the property 
    var targetType = IsNullableType(propertyInfo.PropertyType) ? Nullable.GetUnderlyingType(propertyInfo.PropertyType) : propertyInfo.PropertyType; 

    //Returns an System.Object with the specified System.Type and whose value is 
    //equivalent to the specified object. 
    propertyVal = Convert.ChangeType(propertyVal, targetType); 

    //Set the value of the property 
    propertyInfo.SetValue(inputObject, propertyVal, null); 

} 
private static bool IsNullableType(Type type) 
{ 
    return type.IsGenericType && type.GetGenericTypeDefinition().Equals(typeof(Nullable<>)); 
} 

trzeba konwertować wartości jak to IE trzeba konwertować wartości do rodzaju nieruchomości tak jak poniżej:

PropertyInfo info = t.GetProperty("Value"); 
object value = null; 
try 
{ 
    value = System.Convert.ChangeType(123, 
     Nullable.GetUnderlyingType(info.PropertyType)); 
} 
catch (InvalidCastException) 
{ 
    return; 
} 
propertyInfo.SetValue(obj, value, null); 

Musisz to zrobić, ponieważ Ty Nie można przekonwertować dowolną wartość arbirtary do danego rodzaju ... więc trzeba przekonwertować go jak ten

+0

Doskonała odpowiedź !! – series0ne

+0

Przepraszamy za opóźnienie, bawiliśmy się z próbkami kodu. Zrobiłem lewę, dzięki! – Shikyo

+0

To nie działa, gdy ustawienie "null". Łatwo to naprawić, próbował edytować swój post, ale został odrzucony. – Shikyo

2

Kiedy piszesz:

obj.Value = v; 

kompilator wie, jak to zrobić właściwego odlewania dla Ciebie i faktycznie kompiluje

obj.Value = new long?((long) v); 

Podczas użytkowania odbicie nie ma kompilatora, aby ci pomóc.

2

Ponieważ typ long ma niejawną metodę konwersji.

6.1.2 Implicit numeric conversions

Można zobaczyć ukrytą metodę konwersji jako ukryte metody, które istnieją za = symbolem.

także współpracować z rodzaju wartości pustych:

int i = 0; 
int? j = i; // Implicit conversion 
long k = i; // Implicit conversion 
long? l = i; // Implicit conversion 

Ale będzie na odwrót nie działa, ponieważ nie istnieje niejawna konwersja przekazać null do niezerowe:

int? i = 0; 
int j = i; // Compile assert. An explicit conversion exit... 
int k = (int)i; // Compile, but if i is null, you will assert at runtime. 

Nie trzeba jawnie konwertować int na int? ... ani na long?.

Jednak, gdy używasz odbicia, pomijasz niejawną konwersję i przypisujesz bezpośrednio wartość do właściwości. W ten sposób musisz przekonwertować go jawnie.

info.SetValue(obj, (long?)v, null); 

Pomiń wszystkie słodkie rzeczy ukryte za =.

+0

Podejrzewa się coś takiego, dzięki za jasne wyjaśnienie. – Shikyo

Powiązane problemy