使用反射的 C# 类型比较

发布于 2024-12-20 14:41:11 字数 1985 浏览 2 评论 0原文

我想使用反射检查属性是否属于 DbSet 类型。

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 将 System.Object 作为 BaseType 返回,这对我来说没有用。 k,我认为检查不安全。但如果没有找到其他解决方法,这将是我使用的。在调试模式下,propTypeFullName 为:

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

    是否还有其他方法可以检查 propType 是否为 DbSet 类型?
    谢谢。

I'd like to check if a property is of type DbSet<T> using reflection.

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

By using reflection:

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;
        }
    }
}
  • Is there a merged solution to check the type? As you can see, I'm using IsSubClassOf + FullName to get classes of type Foo and any other class which is derived from Foo.

  • all the checks (a to j) except c,f,k return false. c,f return System.Object as BaseType which is no use for me. k, I consider an unsafe check. But will be my what I use if no other workaround is found. In debug mode, the propType's FullName is:

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

    Is there any other way to check if propType is of type DbSet<>?
    Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一世旳自豪 2024-12-27 14:41:11

您是否也需要它来处理 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);
        }
    }
}

对于子类,您只需要在继承层次结构中递归地应用相同的测试。如果您需要测试接口,这会变得更加痛苦。

Do you need it to cope with subclasses of DbSet<> as well? If not, you can use:

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

Full sample:

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

With subclasses you'd just need to apply the same test recursively up the inheritance hierarchy. It becomes more of a pain if you need to test for interfaces.

眼藏柔 2024-12-27 14:41:11

您的代码的问题在于它假设 typeof(DbType<>) 表示常规类型。它不是普通类型:相反,它是泛型类型定义。这就是为什么 IsAssignableFromIsSubclassOf 等不起作用。如果满足以下条件,Type x 的类型为 DbSet

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

The problem with your code is that it is assuming that typeof(DbType<>) denotes a regular type. It is not a normal type: rather, it is a generic type definition. That is why the IsAssignableFrom, IsSubclassOf etc. are not going to work. Type x is of type DbSet<T> if the following condition is true:

x.IsGenericType && x.GetGenericTypeDefinition() == typeof(DbSet<>) && x.GetGenericTypeArguments()[0] == typeof(T)
樱花细雨 2024-12-27 14:41:11

我建议进行以下类型比较(对我来说效果很好):

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
}

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

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

I'd suggest the following type comparision (worked fine for me):

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
}

For nullable types (for example DateTime? ) you might use this type of comparison:

if (typeName.Contains(typeof(string).FullName))
{
    prop.SetValue(customObject, "abc");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文