Сравнение типов C # с использованием отражения - PullRequest
2 голосов
/ 10 декабря 2011

Я хотел бы проверить, если свойство имеет тип DbSet<T>, используя отражение.

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

Используя отражение:

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;
        }
    }
}
  • Существует ли объединенное решение для проверки типа?Как видите, я использую IsSubClassOf + FullName, чтобы получить классы типа Foo и любой другой класс, производный от Foo.

  • все проверки (от a до j), кроме c, f, k, возвращают false.c, f возвращает System.Object как BaseType, который мне не нужен.k, я считаю небезопасной проверкой .Но я буду использовать то, что я использую, если другого обходного пути не найдено.В режиме отладки propType FullName:

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

    Есть ли другой способ проверить, относится ли propType к типу DbSet<>?
    Спасибо.

Ответы [ 2 ]

5 голосов
/ 10 декабря 2011

Вам это нужно, чтобы справиться и с подклассами DbSet<>? Если нет, вы можете использовать:

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

Полный образец:

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);
        }
    }
}

С подклассами вам просто нужно применить один и тот же тест рекурсивно вверх по иерархии наследования. Если вам нужно проверить интерфейсы, это становится более болезненным.

2 голосов
/ 10 декабря 2011

Проблема с вашим кодом в том, что предполагается, что typeof(DbType<>) обозначает обычный тип. Это не нормальный тип: скорее, это определение общего типа. Вот почему IsAssignableFrom, IsSubclassOf и т. Д. Не будут работать. Type x имеет тип DbSet<T>, если выполняется следующее условие:

x.IsGenericType && x.GetGenericTypeDefinition() == typeof(DbSet<>) && x.GetGenericTypeArguments()[0] == typeof(T)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...