it-swarm.com.de

Wandeln Sie eine Eigenschaft mithilfe von Reflektionen dynamisch in ihren tatsächlichen Typ um

Ich muss eine Eigenschaft dynamisch in ihren tatsächlichen Typ umwandeln. Wie kann/kann ich dies mit Reflektion tun?

Um das wirkliche Szenario zu erklären, an dem ich gerade arbeite. Ich versuche, die Erweiterungsmethode "First" für eine Entity Framework-Eigenschaft aufzurufen. Die spezifische Eigenschaft, die für das Framework-Kontextobjekt aufgerufen werden soll, wird als Zeichenfolge an die Methode übergeben (sowie die ID des abzurufenden Datensatzes). Ich brauche also den tatsächlichen Typ des Objekts, um die First-Methode aufzurufen. 

Ich kann die "Where" -Methode für das Objekt nicht verwenden, da die Lambda- oder Delegat-Methode immer noch den tatsächlichen Typ des Objekts benötigt, um auf die Eigenschaften zugreifen zu können.

Da das Objekt vom Entity Framework generiert wird, kann ich den Typ nicht in eine Schnittstelle umwandeln und diese bearbeiten.

Dies ist Szenario-Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Reflection;

namespace NmSpc
{

    public class ClassA
    {
        public int IntProperty { get; set; }
    }

    public class ClassB
    {
        public ClassA MyProperty { get; set; }
    }

    public class ClassC
    {
        static void Main(string[] args)
        {
            ClassB tester = new ClassB();

            PropertyInfo propInfo = typeof(ClassB).GetProperty("MyProperty");
            //get a type unsafe reference to ClassB`s property
            Object property = propInfo.GetValue(tester, null);

            //get the type safe reference to the property
            ClassA typeSafeProperty = property as ClassA;

            //I need to cast the property to its actual type dynamically. How do I/Can I do this using reflection?
            //I will not know that "property" is of ClassA apart from at runtime
        }
    }
}
25
Keith K

Ich hatte einige Zeit, also habe ich versucht, mein Problem mit VS2010 zu lösen, und ich glaube, ich hatte recht, als ich daran dachte, dass das dynamische Keywork meine Frage 'lösen' würde. Siehe den Code unten.

using System.Reflection;

namespace TempTest
{
    public class ClassA
    {
        public int IntProperty { get; set; }
    }

    public class ClassB
    {
        public ClassB()
        {
            MyProperty = new ClassA { IntProperty = 4 };
        }
        public ClassA MyProperty { get; set; }
    }

    public class Program
    {
        static void Main(string[] args)
        {
            ClassB tester = new ClassB();

            PropertyInfo propInfo = typeof(ClassB).GetProperty("MyProperty");
            //get a type unsafe reference to ClassB`s property
            dynamic property = propInfo.GetValue(tester, null);

            //casted the property to its actual type dynamically
            int result = property.IntProperty; 
        }
    }
}
5
Keith K
public object CastPropertyValue(PropertyInfo property, string value) { 
if (property == null || String.IsNullOrEmpty(value))
    return null;
if (property.PropertyType.IsEnum)
{
    Type enumType = property.PropertyType;
    if (Enum.IsDefined(enumType, value))
        return Enum.Parse(enumType, value);
}
if (property.PropertyType == typeof(bool))
    return value == "1" || value == "true" || value == "on" || value == "checked";
else if (property.PropertyType == typeof(Uri))
    return new Uri(Convert.ToString(value));
else
    return Convert.ChangeType(value, property.PropertyType);  }
31
Nisus

Sobald Sie den reflektierten Typ erhalten, können Sie Convert.ChangeType() verwenden.

3
Marty

Obwohl ich die Lösung für das Problem der realen Welt posten sollte.

string objectType = "MyProperty";

using (MyEntitiesContext entitiesContext = new MyEntitiesContext())
{
try
{
    string queryString = @"SELECT VALUE " + objectType+  " FROM MyEntitiesContext." + objectType + " AS " + objectType + " WHERE " + objectType + ".id = @id";

    IQueryable<Object> query = entitiesContext.CreateQuery<Object>(queryString, new ObjectParameter("id", objectId));

    foreach (Object result in query)
    {
        return result;
    }
}
catch (EntitySqlException ex)
{
    Console.WriteLine(ex.ToString());
}
}

return null;

Ich denke, das neue dynamische CLR4-Keywork könnte die "Nice" -Lösung sein.

Danke für all die Antworten.

1
Keith K

Das Vorhandensein einer Variablen eines bestimmten Typs ist wirklich nur zur Kompilierzeit nützlich und wird Ihnen zur Laufzeit bei der Verwendung dieser Variablen nicht helfen. Versuchen Sie, den Code an der Stelle zu schreiben, an der Sie dies verwenden würden. Sie werden feststellen, dass der Typ die Zeit für die Kompilierung auf einer bestimmten Ebene (möglicherweise weiter oben in der Anrufkette) kennt der konkrete Typ dafür nützlich sein).

Beachten Sie jedoch Folgendes: Wenn Ihr Typ ein Referenztyp ist, ist das Objekt immer noch der Typ, den Sie erstellt haben. Es ist nicht so, dass es von Vorteil ist, wenn das Objekt als Typ im Vergleich zum Objekt gespeichert wird. Dies ist die Schönheit des Nachdenkens (und auch ein Grund dafür, warum es funktioniert). Es gibt wirklich keinen Grund, zu versuchen, seinen Typ zur Laufzeit in einem Cast zu "ändern", da er immer noch ein Objekt ist.

1
Reed Copsey

Wie wäre es, wenn Sie den root-Wert als String festlegen und ihn dann als String herumführen, bis Sie ihn in den Zieltyp konvertieren müssen?

1
euwe
Type resultType = typeof(T);
IEnumerable<PropertyDescriptor> properties = TypeDescriptor.GetProperties(resultType).Cast<PropertyDescriptor>();

object instance = Activator.CreateInstance(resultType);

var objValue = "VALUE FOR HEADER";
var resultHeader = "HeaderName";
var prop = properties.Single(p => string.Equals(p.Name, resultHeader, StringComparison.InvariantCultureIgnoreCase));

var targetType = Nullable.GetUnderlyingType(prop.PropertyType) !=null Nullable.GetUnderlyingType(prop.PropertyType):prop.PropertyType;

objValue  = Convert.ChangeType(objValue , targetType);
prop.SetValue(instance, objValue );

// Instanz zurückgeben;

0
user8097903