C# 泛型列表如何获取T的类型?

发布于 2024-07-25 15:52:49 字数 1500 浏览 3 评论 0原文

我正在开展一个反思项目,但现在我陷入了困境。

如果我有一个可以容纳 Listmyclass 对象,有谁知道如何获取下面代码中的类型(如果属性 myclass) .SomList 为空?

List<myclass> myList = dataGenerator.getMyClasses();
lbxObjects.ItemsSource = myList; 
lbxObjects.SelectionChanged += lbxObjects_SelectionChanged;

private void lbxObjects_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Reflect();
}

Private void Reflect()
{
    foreach (PropertyInfo pi in lbxObjects.SelectedItem.GetType().GetProperties())
    {
        switch (pi.PropertyType.Name.ToLower())
        {
            case "list`1":
            {           
                // This works if the List<T> contains one or more elements.
                Type tTemp = GetGenericType(pi.GetValue(lbxObjects.SelectedItem, null));

                // but how is it possible to get the Type if the value is null? 
                // I need to be able to create a new object of the type the generic list expect. 
                // Type type = pi.getType?? // how to get the Type of the class inside List<T>?
                break;
            }
        }
    }
}

private Type GetGenericType(object obj)
{
    if (obj != null)
    {
        Type t = obj.GetType();
        if (t.IsGenericType)
        {
            Type[] at = t.GetGenericArguments();
            t = at.First<Type>();
        } 
        return t;
    }
    else
    {
        return null;
    }
}

I'm working on a reflection project, and now I'm stuck.

If I have an object of myclass that can hold a List<SomeClass>, does anyone know how to get the type as in the code below if the property myclass.SomList is empty?

List<myclass> myList = dataGenerator.getMyClasses();
lbxObjects.ItemsSource = myList; 
lbxObjects.SelectionChanged += lbxObjects_SelectionChanged;

private void lbxObjects_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    Reflect();
}

Private void Reflect()
{
    foreach (PropertyInfo pi in lbxObjects.SelectedItem.GetType().GetProperties())
    {
        switch (pi.PropertyType.Name.ToLower())
        {
            case "list`1":
            {           
                // This works if the List<T> contains one or more elements.
                Type tTemp = GetGenericType(pi.GetValue(lbxObjects.SelectedItem, null));

                // but how is it possible to get the Type if the value is null? 
                // I need to be able to create a new object of the type the generic list expect. 
                // Type type = pi.getType?? // how to get the Type of the class inside List<T>?
                break;
            }
        }
    }
}

private Type GetGenericType(object obj)
{
    if (obj != null)
    {
        Type t = obj.GetType();
        if (t.IsGenericType)
        {
            Type[] at = t.GetGenericArguments();
            t = at.First<Type>();
        } 
        return t;
    }
    else
    {
        return null;
    }
}

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

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

发布评论

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

评论(4

带上头具痛哭 2024-08-01 15:52:49
Type type = pi.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition()
        == typeof(List<>))
{
    Type itemType = type.GetGenericArguments()[0]; // use this...
}

更一般地说,要支持任何 IList,您需要检查接口:

foreach (Type interfaceType in type.GetInterfaces())
{
    if (interfaceType.IsGenericType &&
        interfaceType.GetGenericTypeDefinition()
        == typeof(IList<>))
    {
        Type itemType = type.GetGenericArguments()[0];
        // do something...
        break;
    }
}
Type type = pi.PropertyType;
if(type.IsGenericType && type.GetGenericTypeDefinition()
        == typeof(List<>))
{
    Type itemType = type.GetGenericArguments()[0]; // use this...
}

More generally, to support any IList<T>, you need to check the interfaces:

foreach (Type interfaceType in type.GetInterfaces())
{
    if (interfaceType.IsGenericType &&
        interfaceType.GetGenericTypeDefinition()
        == typeof(IList<>))
    {
        Type itemType = type.GetGenericArguments()[0];
        // do something...
        break;
    }
}
蓝眼泪 2024-08-01 15:52:49

给定一个我怀疑是某种 IList 的对象,我如何确定它是什么它是 IList?

这是勇敢的解决方案。 它假设您有要测试的实际对象(而不是 Type)。

public static Type ListOfWhat(Object list)
{
    return ListOfWhat2((dynamic)list);
}

private static Type ListOfWhat2<T>(IList<T> list)
{
    return typeof(T);
}

用法示例:

object value = new ObservableCollection<DateTime>();
ListOfWhat(value).Dump();

打印

typeof(DateTime)

Given an object which I suspect to be some kind of IList<>, how can I determine of what it's an IList<>?

Here's the gutsy solution. It assumes you have the actual object to test (rather than a Type).

public static Type ListOfWhat(Object list)
{
    return ListOfWhat2((dynamic)list);
}

private static Type ListOfWhat2<T>(IList<T> list)
{
    return typeof(T);
}

Example usage:

object value = new ObservableCollection<DateTime>();
ListOfWhat(value).Dump();

Prints

typeof(DateTime)
z祗昰~ 2024-08-01 15:52:49

Marc 的答案是我为此使用的方法,但为了简单起见(以及更友好的 API?),如果您有以下属性,您可以在集合基类中定义一个属性:

public abstract class CollectionBase<T> : IList<T>
{
   ...

   public Type ElementType
   {
      get
      {
         return typeof(T);
      }
   }
}

我发现这种方法很有用,并且很容易理解任何仿制药新手。

Marc's answer is the approach I use for this, but for simplicity (and a friendlier API?) you can define a property in the collection base class if you have one such as:

public abstract class CollectionBase<T> : IList<T>
{
   ...

   public Type ElementType
   {
      get
      {
         return typeof(T);
      }
   }
}

I have found this approach useful, and is easy to understand for any newcomers to generics.

爱人如己 2024-08-01 15:52:49

给定一个我怀疑是某种 IList 的对象,我如何确定它是什么它是 IList?

这是一个可靠的解决方案。 对于篇幅,我深表歉意 - C# 的内省 API 让这变得异常困难。

/// <summary>
/// Test if a type implements IList of T, and if so, determine T.
/// </summary>
public static bool TryListOfWhat(Type type, out Type innerType)
{
    Contract.Requires(type != null);

    var interfaceTest = new Func<Type, Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>) ? i.GetGenericArguments().Single() : null);

    innerType = interfaceTest(type);
    if (innerType != null)
    {
        return true;
    }

    foreach (var i in type.GetInterfaces())
    {
        innerType = interfaceTest(i);
        if (innerType != null)
        {
            return true;
        }
    }

    return false;
}

用法示例:

    object value = new ObservableCollection<int>();
Type innerType;
TryListOfWhat(value.GetType(), out innerType).Dump();
innerType.Dump();

返回

True
typeof(Int32)

Given an object which I suspect to be some kind of IList<>, how can I determine of what it's an IList<>?

Here's a reliable solution. My apologies for length - C#'s introspection API makes this suprisingly difficult.

/// <summary>
/// Test if a type implements IList of T, and if so, determine T.
/// </summary>
public static bool TryListOfWhat(Type type, out Type innerType)
{
    Contract.Requires(type != null);

    var interfaceTest = new Func<Type, Type>(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IList<>) ? i.GetGenericArguments().Single() : null);

    innerType = interfaceTest(type);
    if (innerType != null)
    {
        return true;
    }

    foreach (var i in type.GetInterfaces())
    {
        innerType = interfaceTest(i);
        if (innerType != null)
        {
            return true;
        }
    }

    return false;
}

Example usage:

    object value = new ObservableCollection<int>();
Type innerType;
TryListOfWhat(value.GetType(), out innerType).Dump();
innerType.Dump();

Returns

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