问题:我想调用泛型函数,定义为:
Public Shared Function DeserializeFromXML(Of T)(Optional ByRef strFileNameAndPath As String = Nothing) As T
现在,当我打电话给它时,我希望使用以下任何变体:
Dim x As New XMLserialization.cConfiguration
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of x)()
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(GetType(x))()
x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of GetType(x))()
但它不起作用。 我觉得必须输入
非常烦人且难以理解 x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of XMLserialization.cConfiguration)()
有没有办法通过从实例中获取类型来调用泛型函数?
答案 0 :(得分:3)
泛化和反思使非常可怜的朋友。但是,您可以通过MakeGenericMethod执行此操作。然而,这将是艰难和丑陋的。
由于XmlSerializer
基于Type
个实例 - 我会反驳:基于 realy 代码Type
,并从浅层通用调用版; C#中的例子:
public T DeserializeFromXML<T>(string path) {
return (T)DeserializeFromXML(typeof(T), path);
}
public object DeserializeFromXML(Type type, string path) {
//TODO: real code
}
答案 1 :(得分:2)
仅使用System.Reflection
命名空间的方法,这对于您尝试保存的工作确实不值得。
答案 2 :(得分:2)
听起来我想为您的XMLserialization.cConfiguration
类型创建一个较短的别名。尝试使用Imports
语句来完成此任务:
' at the top of the file
Imports C = XMLserialization.cConfiguration
' somewhere in the body of the file
Dim x = XMLserialization.XMLserializeLDAPconfig.DeserializeFromXML(Of C)()
答案 3 :(得分:1)
泛型方法的类型是在编译时确定的,这就是您无法使用变量进行设置的原因。这是泛型编程和类型反射之间的关键区别。
答案 4 :(得分:1)
有一个很好的理由说明为什么你不能在代码中轻松地做到这一点以及为什么反射是如此多的额外工作:泛型都是关于保留类型,所以你可以有一个List(Of Integer)
而不是{{1并且必须转换/包装所有内容,并通过代码维护强类型来提高代码可维护性(这样可以减少运行时转换和类型异常)。
泛型是真正的编译时间。它们允许您推迟指定的类型,以便可以重用通用代码或使用另一个程序集指定的类型。
然而,你的反序列化是运行时 - 你不知道在编写代码时你将拥有什么类型,这就是你需要一个变量来保存类型的原因。在这种情况下,拥有通用代码并没有任何好处 - 您的序列化成本将高于装箱成本的数量级,并且对于强类型结果没有代码可维护性优势,因为您仍然不知道什么它是在编译时。
简而言之,这很难实现.Net告诉你审查你的初步假设的方式 - 将你的方法改为:
List(Of Object)
然后将您的结果从对象转换为Public Shared Function DeserializeFromXML(Optional ByRef strFileNameAndPath As String = Nothing) As Object
类。
答案 5 :(得分:0)
[这是回答问题,不一定解决你的更大问题。]
为避免要求Of cConfiguration
,您可以在通用方法中包含忽略的ByVal Configuration As T
。
然后你可以说
x = DeserializeFromXML(x)
但是@ DanTao的答案可能比我的更好,除非你找到Configuration
参数的用途。