c# - 为什么 Assembly.GetTypes() 不会返回封闭泛型类型?

标签 c# .net generics reflection

我创建了一个通用 JavaScriptConverter自定义泛型类( TabularList<> )的派生,我将其称为 ITabularConverter<>ITabularConverter使用反射来检索从 TabularList<> 派生的所有封闭类型泛型类型定义通知 JavaScriptSerializer 它能够转换 ITabularConverter<> 的所有封闭类型。该代码如下所示:

public override IEnumerable<Type> SupportedTypes
{
    get
    {
        var type = typeof (TabularList<>);
        var itabulars = Assembly.GetAssembly(type).GetTypes()
            .Where(t => t.IsGenericType 
                && t.GetGenericTypeDefinition() == type);
        return itabulars;
    }
}

问题是,即使在执行此代码时至少存在一种封闭类型 TabularList<>,上述代码也仅返回开放泛型类型定义。当我将搜索扩展到所有当前加载的程序集时,情况也是如此。

更奇怪的是,如果我检查调用堆栈,我可以看到 JavaScriptSerializer.Serialize 方法被调用的位置,并使用立即窗口来检查正在序列化的对象并证明通用定义的封闭版本存在。然而,当我在立即窗口中执行以下代码时,结果是 false :

Assembly.GetAssembly(obj.TabularListProp.GetType())
    .GetTypes()
    .Contains(obj.TabularListProp.GetType());

因此,我检索定义了封闭泛型的程序集,然后在该程序集定义的类型中查找封闭泛型类型,但未找到封闭类型。这有什么意义呢?

这是 TabularList<> 的声明:

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

namespace Central.Claims.UX.ClaimWFMgrViewModel
{
    [Serializable]
    public class TabularList<T> : List<T>, ITabular
    {

        private List<List<object>> _tableView;

        [XmlIgnore]
        public List<List<object>> TableView
        {
            get { return GetTableView(); }
        }

        private List<KeyValuePair<string, Func<object, object>>> Schema { get; set; }  
        public TabularList()
        {
            Initialize();
        }

        public TabularList(IEnumerable<T> source) : base(source)
        {
            Initialize();
        }

        private void Initialize()
        {
            RefreshTableView = true;
            var type = typeof(T);

            if (Schemas.ContainsKey(type.Name))
            {
                Schema = Schemas[type.Name];
            }
            else
            {
                Schema = new List<KeyValuePair<string, Func<object, object>>>();
            }
        }

        protected List<List<object>> GetTableView()
        {    
            GetSchema();
            BuildTable();

            return _tableView;
        }

        private void GetSchema()
        {
            if (this.Any())
            {
                var properties = this.First().GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);

                foreach (var property in properties)
                {
                    var getter = property.GetGetMethod();

                    Schema.Add(new KeyValuePair<string, Func<object, object>>(
                        property.Name,
                        (Func<object, object>) Delegate.CreateDelegate(typeof (Func<object, object>), getter)
                        ));
                }
            }
        }

        private void BuildTable()
        {
            _tableView = new List<List<object>>();

            foreach (var item in this)
            {
                TableView.Add(ToTableRow(item));
            }
        }

        private List<object> ToTableRow(T item)
        {
            var row = new List<object>();

            foreach (var column in Schema)
            {
                row.Add(column.Value(item));
            }

            return row;
        }
    }     
}

根据此处提供的答案,我在 SO 问题 How to retrieve a list of all closed generic types generated by the .NET runtime? 中重新表述了这个问题

最佳答案

请记住,反射只是查询元数据,因此其中包含的任何信息都是纯粹的编译类型信息。事实上,您有一个 TabularList<SomeType>) 的实例更改定义它的程序集中包含的元数据。

封闭泛型类型在定义开放泛型类型的程序集中定义,也不在创建该特定封闭类型的程序集中定义。

您是否希望找到 List<T>所有可能封闭定义的元数据mscorlib内?您是否希望在创建 List<int> 的程序集中找到它?变量?

请注意,它确实以另一种方式工作 - 如果您调用

Assembly a = Assembly.GetAssembly(typeof(List<int>));

你得到了大会

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

因此,您也许可以反转您的逻辑 - 不是搜索程序集中的所有封闭类型,而是查找封闭类型的程序集以查看它是否“受支持”。

关于c# - 为什么 Assembly.GetTypes() 不会返回封闭泛型类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33214826/

相关文章:

c# - .NET : How to get time for keypress as precisely as possible?

c# - 批量上传到 YouTube - ASP.NET 4 C#

c# - 单个 Windows 线程的内存开销是多少?

.net - 安装在不同操作系统上的 .NET 应用程序使用什么版本的 TLS

swift 2 自省(introspection)

c# - 如何创建这个 wpf 工具栏

c# - Using with inner using 的正确使用方法

C# 使用 HTTPWebRequest 登录网站

MYSQL 初学者。创建包含多种数据类型列的表

java - 包含多态方法引用的数据结构