gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 10:21:50 25 4
gpt4 key购买 nike

我创建了一个通用的 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com