2 Stimmen

C# Typvergleich mit Reflexion

Ich würde gerne prüfen, ob eine Eigenschaft vom Typ DbSet<T> durch Reflexion.

public class Foo
{
    public DbSet<Bar> Bars { get; set; }
}

Mit Hilfe der Reflexion:

var types = Assembly.GetExecutingAssembly().GetTypes();
foreach (var type in types)
{
    if (type.IsSubclassOf(typeof (Foo)) || type.FullName == typeof (Foo).FullName)
    {
        foreach (
            var prop in Type.GetType(type.FullName).
                GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
        {
            var propType = prop.PropertyType;
            bool a = propType.IsAssignableFrom(typeof (DbSet<>));
            bool b = typeof (DbSet<>).IsAssignableFrom(propType);

            bool c = propType.BaseType.IsAssignableFrom(typeof (DbSet<>));
            bool d = typeof (DbSet<>).IsAssignableFrom(propType.BaseType);

            bool e = typeof (DbSet<>).IsSubclassOf(propType);
            bool f = typeof (DbSet<>).IsSubclassOf(propType.BaseType);
            bool g = propType.IsSubclassOf(typeof (DbSet<>));
            bool h = propType.BaseType.IsSubclassOf(typeof (DbSet<>));

            bool i = propType.BaseType.Equals(typeof (DbSet<>));
            bool j = typeof (DbSet<>).Equals(propType.BaseType);

            bool k = propType.Name == typeof (DbSet<>).Name;
        }
    }
}
  • Gibt es eine kombinierte Lösung, um den Typ zu überprüfen? Wie Sie sehen können, verwende ich IsSubClassOf + FullName um Klassen des Typs Foo und jede andere Klasse, die sich von Foo .

  • alle Prüfungen (a bis j) außer c,f,k geben false zurück. c,f geben System.Object als BaseType zurück, was für mich nicht von Nutzen ist. k halte ich für eine unsichere Kontrolle . Aber ich werde es verwenden, wenn keine andere Lösung gefunden wird. Im Debug-Modus wird die propType 's FullName ist:

    System.Data.Entity.DbSet\`1\[\[Console1.Bar, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null\]\]

    Gibt es eine andere Möglichkeit zu prüfen, ob propType ist vom Typ DbSet<> ?
    Gracias.

6voto

Jon Skeet Punkte 1325502

Benötigen Sie es, um mit Unterklassen von DbSet<> auch? Wenn nicht, können Sie verwenden:

if (propType.IsGenericType &&
    propType.GetGenericTypeDefinition() == typeof(DbSet<>))

Vollständige Probe:

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

class Test<T>
{
    public List<int> ListInt32 { get; set; }
    public List<T> ListT { get; set; }
    public string Other { get; set; }
    public Action<string> OtherGeneric { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var query = from prop in typeof(Test<string>).GetProperties()
                    let propType = prop.PropertyType
                    where propType.IsGenericType &&
                          propType.GetGenericTypeDefinition() == typeof(List<>)
                    select prop.Name;

        foreach (string name in query)
        {
            Console.WriteLine(name);
        }
    }
}

Bei Unterklassen müssten Sie nur denselben Test rekursiv in der Vererbungshierarchie anwenden. Schwieriger wird es, wenn Sie auf Schnittstellen testen müssen.

2voto

Sergey Kalinichenko Punkte 694383

Das Problem mit Ihrem Code ist, dass er davon ausgeht, dass typeof(DbType<>) kennzeichnet einen regulären Typ. Es handelt sich nicht um einen normalen Typ, sondern um eine generische Typdefinition. Aus diesem Grund ist die IsAssignableFrom , IsSubclassOf usw. werden nicht funktionieren. Type x ist vom Typ DbSet<T> wenn die folgende Bedingung erfüllt ist:

x.IsGenericType && x.GetGenericTypeDefinition() == typeof(DbSet<>) && x.GetGenericTypeArguments()[0] == typeof(T)

0voto

Dmitrii Matunin Punkte 109

Ich würde den folgenden Typenvergleich vorschlagen (hat bei mir gut funktioniert):

foreach (var prop in customObject.GetType().GetProperties().Where(e => e.CanRead && e.CanWrite))
{
    var typeName = prop.PropertyType.FullName ?? "";
    //!!! Type comparision here:
    if (typeName == typeof(string).FullName)
    {
        prop.SetValue(customObject, "abc");
        continue;
    }
    // other code
}

Für löschbare Typen (zum Beispiel DateTime? ) können Sie diese Art von Vergleich verwenden:

if (typeName.Contains(typeof(string).FullName))
{
    prop.SetValue(customObject, "abc");
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X