T未知时调用缓存委托

时间:2018-04-12 04:26:31

标签: .net vb.net reflection delegates

因此,我正在使用类似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

我在这里缺少什么?我觉得这是一个非常基本的东西,我忽略了,所以我很感激任何指针。提前谢谢。

1 个答案:

答案 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)