因此,我正在使用类似ORM的代码片段,需要使用反射SetValue / GetValue和属性来提前实例化和填充对象,而无需提前知道它们。这样做很有效,但性能很糟糕,因为我需要创建新的实例,然后为每个新的" row"迭代它们的属性,并且该对象可能还有需要创建/填充的嵌套对象。 / p>
所以我尝试使用和缓存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
我在这里缺少什么?我觉得这是一个非常基本的东西,我忽略了,所以我很感激任何指针。提前谢谢。
答案 0 :(得分:1)
看起来太复杂了。如果你有位置(类撕裂)你明确知道对象的类型,你可以在那里直接播放它们。并保持通用委托类型。
尝试使用这样的setter / getter来避免调用代码中的类型/依赖性
Public Delegate Function GetStringDelegate(Instance As Object) As String
Public Delegate Sub SetStringDelegate(Instance As Object, Value As String)
Public getCommonDTOUID As GetStringDelegate = Function(Instance) DirectCast(Instance, CommonDTO).UID
Public setCommonDTOUID As SetStringDelegate = Sub(Instance, Value) DirectCast(Instance, CommonDTO).UID = Value
我希望有TypeName =>列表关于类型对象的getter / setters集合列表。
您也可以使用通用对象委托:
Public Delegate Function GetDelegate(Instance As Object) As Object
Public Delegate Sub SetDelegate(Instance As Object, Value As Object)
Public getCommonDTOUID As GetDelegate = Function(Instance) DirectCast(Instance, CommonDTO).UID
Public setCommonDTOUID As SetDelegate = Sub(Instance, Value) DirectCast(Instance, CommonDTO).UID = CStr(Value)
这取决于您的调用需求。字符串调用看起来像这样
Dim Value As String = DirectCast(dictCache.Item("UID"), GetStringDelegate)(tdto)