首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用DynamicMethod.CreateDelegate返回带实例对象的字段值

如何使用DynamicMethod.CreateDelegate返回带实例对象的字段值
EN

Stack Overflow用户
提问于 2014-08-07 16:59:45
回答 1查看 312关注 0票数 1

正如问题中所指出的,我感兴趣的是使用.net的动态特性来缓存对象的字段getter/setter并在运行时调用它。

使用来自:Is there a way to create a delegate to get and set values for a FieldInfo?的信息

我已经设置了一个类和函数来设置我需要的功能:

代码语言:javascript
复制
Public Class c1
    Public someField As Integer 'we will Get the value of this dynamically
End Class

Public Function CreateGetter(Of S, T)(ByVal strFieldName As String) As Func(Of S, T)
    'creates a function to return the value
    Dim objFieldInfo As FieldInfo
    Dim strMethodName As String
    Dim objGetterMethod As DynamicMethod
    Dim objGen As ILGenerator
    objFieldInfo = GetType(S).GetField(strFieldName)
    strMethodName = Convert.ToString(objFieldInfo.ReflectedType.FullName) & ".get_" & Convert.ToString(objFieldInfo.Name)
    objGetterMethod = New DynamicMethod(strMethodName, GetType(T), New Type(0) {GetType(S)}, True)
    objGen = objGetterMethod.GetILGenerator()
    If objFieldInfo.IsStatic = False Then
        objGen.Emit(OpCodes.Ldarg_0)
        objGen.Emit(OpCodes.Ldfld, objFieldInfo)
    Else
        objGen.Emit(OpCodes.Ldsfld, objFieldInfo)
    End If
    objGen.Emit(OpCodes.Ret)
    Return DirectCast(objGetterMethod.CreateDelegate(GetType(Func(Of S, T))), Func(Of S, T))
End Function

我把这个好代码称为:

代码语言:javascript
复制
Dim getValue = CreateGetter(Of c1, Integer)("someField")
Dim someValue As Integer
someValue = getValue(o1)

然而,我感到困惑的部分是如何修改函数CreateGetter,以便能够在缓存的形式中使用它,比如:(缓存实例对象)。

代码语言:javascript
复制
Dim getValue = CreateGetter(Of c1, Integer)(o1,"someField")
Dim someValue As Integer
someValue = getValue()

我意识到这可能需要对CreateGetter中的IL代码进行一些修改,但这是我一直坚持的棘手的部分。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-08 11:36:36

实际上,你不能用一种方法来做这件事。要永久保存该对象,您需要在某个对象中添加一个字段,然后创建一个指向该对象上的某个方法的委托。

您可以使用Reflection.Emit完成所有这些工作,但这将是一件乏味的事情。相反,您可以利用编译器已经可以这样做来创建闭包的事实:不是直接返回DynamicMethod委托,而是返回调用该委托的lambda:

代码语言:javascript
复制
Dim fieldAccessor = DirectCast(objGetterMethod.CreateDelegate(GetType(Func(Of S, T))), Func(Of S, T))

Return Function() fieldAccessor(obj)

另一种选择是为所有这些使用表达式树。这有一个优点,你不必处理IL,这可能是很难得到正确的。类似于:

代码语言:javascript
复制
Function CreateGetter(Of S, T)(obj as S, fieldName As String) As Func(Of T)
    Dim expr = Expression.Lambda(Of Func(Of T))(
        Expression.Field(Expression.Constant(obj), fieldName))
    Return expr.Compile()
End Function

这个版本只适用于实例字段,我认为对于静态字段,不需要obj的重载更有意义。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25188178

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档