使用反射的c#类型比较

本文关键字:类型 比较 反射的 | 更新日期: 2023-09-27 18:17:16

我想检查一个属性是否为使用反射的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派生的任何其他类。

  • 除c、f、k外的所有检查(a到j)都返回false。c、f返回系统。对象作为BaseType,这对我没有用处。k,我认为是不安全检查。但如果没有找到其他解决方案,我将使用我的。在调试模式下,propTypeFullName为:

    <>以前System.Data.Entity.DbSet ' 1 [[Console1。栏,ConsoleApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

    是否有其他方法来检查propType是否为DbSet<>类型?
    谢谢。

使用反射的c#类型比较

您是否需要它来处理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);
        }
    }
}
对于子类,您只需要在继承层次结构上递归地应用相同的测试。如果需要对接口进行测试,那就更麻烦了。

代码的问题在于它假设typeof(DbType<>)表示常规类型。它不是一个普通类型:相反,它是一个泛型类型定义。这就是为什么IsAssignableFrom, IsSubclassOf等不会工作。如果满足以下条件,则Type xDbSet<T>类型:

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

我建议使用以下类型比较(对我来说很好):

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
}

对于可空类型(例如DateTime?),您可以使用这种类型的比较:

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