【发布时间】:2018-09-22 02:25:57
【问题描述】:
因此,我正在编写类似 ORM 的代码,该代码需要在不提前知道对象的情况下实例化和填充对象,使用反射 SetValue/GetValue 和属性。这行得通,但性能很糟糕,因为我需要创建新实例,然后为每个新“行”迭代它们的属性,并且对象可能也有需要创建/填充的嵌套对象。
所以我尝试使用和缓存 getter/setter 的委托,但我发现了一些问题。请仅查看 getter 的示例代码,我认为 setter 会更糟(对不起 VB 代码哈哈):
Public Class CommonDTO
'actual objects
Public Property UID As String
Public Property CreateDate As DateTime
End Class
Public Class torm
Private flags As BindingFlags = BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public
Private common As Type = GetType(CommonDTO)
'List for holding all the supported types, inside it contains many dictionaries holding the actual delegates
Public listCacheGet As New ConditionalWeakTable(Of Type, Dictionary(Of String, [Delegate]))
Private commonUID As PropertyInfo = Common.GetProperty("UID", flags)
Private commonCreateDate As PropertyInfo = Common.GetProperty("CreateDate", flags)
'Create the delegates for the get/set of each property. This is a royal PITA btw
Public getcommonUID As Func(Of CommonDTO, String) = CType([Delegate].CreateDelegate(GetType(Func(Of CommonDTO, String)),
commonUID.GetGetMethod(nonPublic:=True)), Func(Of CommonDTO, String))
Public setcommonUID As Action(Of CommonDTO, String) = CType([Delegate].CreateDelegate(GetType(Action(Of CommonDTO, String)),
commonUID.GetSetMethod()), Action(Of CommonDTO, String))
Public getcommonCreateDate As Func(Of CommonDTO, DateTime) = CType([Delegate].CreateDelegate(GetType(Func(Of CommonDTO, DateTime)),
commonCreateDate.GetGetMethod(nonPublic:=True)), Func(Of CommonDTO, DateTime))
Public setcommonCreateDate As Action(Of CommonDTO, DateTime) = CType([Delegate].CreateDelegate(GetType(Action(Of CommonDTO, DateTime)),
commonCreateDate.GetSetMethod()), Action(Of CommonDTO, DateTime))
Public Sub New()
Dim listCommonDTOGet As New Dictionary(Of String, [Delegate])
'Fill the lists
listCommonDTOGet.Add("UID", getcommonUID)
listCommonDTOGet.Add("CreateDate", getcommonCreateDate)
listCacheGet.Add(common, listCommonDTOGet)
End Sub
End Class
Public Class Test
Public Sub test(tdto as type)
Dim orm As New torm
Dim tempDTO = Activator.CreateInstance(tdto)
Dim dictCache As IDictionary = Nothing
'obtain the dictionary for the type that we are using
orm.listCacheGet.TryGetValue(tdto, dictCache)
'...but here is the problem. I don't know the exact type of the delegate
'contained within. I don't know how to instantiate it on its actual
'Func/Action definition (because this procedure doesn't know it,
'and I think that T wouldn't work either, because the callers
'wouldn't know the actual Func/Action definition either,
'so I have only managed to create it as Object or [Delegate]
Dim getv as [Delegate] = dictCache.Item("UID")
'...so getv ends up being an object that actually has the cached
'delegate and I have no idea how to invoke.
'Well, I CAN do this, but it's even slower than using
'SetValue/GetValue!!
Console.Writeline(getv.DynamicInvoke(tempDTO))
'and of course, the direct calling is super fast
Console.Writeline(orm.getcommonUID(tempDTO))
End Sub
End Class
我在这里缺少什么?我觉得这是我忽略的非常基本的东西,所以我会很感激任何指示。提前致谢。
【问题讨论】:
-
"对不起 VB 代码,哈哈"
-
@AndrewMortimer 很多人出于某种原因讨厌 VB。除此之外,我的代码很丑;)
-
即使你不知道
T,只要传入一个类型,你就可以在运行时在它上面实例化一个泛型类型。例如Dim myGeneric = GetType(GenericType(Of ))(在Of后面故意留空)然后是Dim mySpecific = myGeneric.MakeGenericType(specificType)。我不确定这是否会帮助你。如果客户端代码知道类型,您还可以通过设置 getter/setter 委托来做一些其他很酷的事情。
标签: .net vb.net reflection delegates