簡體   English   中英

VB中的Linq.Expression GetValue?

[英]Linq.Expression GetValue in VB?

題:

我有這個C#程序,它獲取mytable的字段表名的值。
而且效果很好。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;


namespace AttachObjectsCS
{


    static class Program
    {


        public class cmytable
        {
            public string tablename = "test";
        }


        // http://stackoverflow.com/questions/2616638/access-the-value-of-a-member-expression
        private static object GetValue(System.Linq.Expressions.MemberExpression member)
        {
            System.Linq.Expressions.Expression objectMember = System.Linq.Expressions.Expression.Convert(member, typeof(object));
            System.Linq.Expressions.Expression<Func<object>> getterLambda = System.Linq.Expressions.Expression.Lambda<Func<object>>(objectMember);

            var getter = getterLambda.Compile();

            return getter();
        }


        public static void AddField<T>(System.Linq.Expressions.Expression<Func<T>> expr, string alias)
        {
            var body = ((System.Linq.Expressions.MemberExpression)expr.Body);
            Console.WriteLine("Name is: {0}", body.Member.Name);


            object obj = GetValue(body);


            Console.WriteLine("Value is: {0}", obj);
        }



        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {

            if (false)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }


            cmytable mytable = new cmytable();

            AddField(() => mytable.tablename, "te");


            Console.WriteLine(Environment.NewLine);
            Console.WriteLine(" --- Press any key to continue --- ");
            Console.ReadKey();
        } // End Sub Main 


    } // End Class Program


} // End Namespace AttachObjectsCS

現在,我需要VB.NET中的相同功能,但是失敗了。
現在,由於我知道VB.NET和C#並不總是使用相同的linq表達式,因此我在這里遇到問題並不感到驚訝。

Module Program




    Public Class cmytable
        Public tablename As String = "test"
    End Class


    Public Sub AddField(Of T)(expr As System.Linq.Expressions.Expression(Of Func(Of T)))
        Dim body = DirectCast(expr.Body, System.Linq.Expressions.MemberExpression)
        Dim strName As String = body.Member.Name
        Console.WriteLine("Name is: {0}", strName)


        Dim obj As Object = GetValue(body)


        Console.WriteLine("Value is: {0}", obj)
    End Sub


    ' http://stackoverflow.com/questions/2616638/access-the-value-of-a-member-expression '
    Private Function GetValue(member As System.Linq.Expressions.MemberExpression) As Object
        Dim objectMember As System.Linq.Expressions.Expression = System.Linq.Expressions.Expression.Convert(member, GetType(Object))
        Dim getterLambda As System.Linq.Expressions.Expression(Of Func(Of Object)) = System.Linq.Expressions.Expression.Lambda(Of Func(Of Object))(objectMember)


        Dim getter = getterLambda.Compile()

        Return getter()
    End Function



    Public Sub Main()

        Dim mytable As New cmytable

        AddField(Function() mytable.tablename)
    End Sub


End Module ' Program

問題出在GetValue,問題是我似乎沒有合適的objectMember。

這是表達式的調試輸出:

CS objectMember = {Convert(value(AttachObjectsCS.Program+<>c__DisplayClass0).mytable.tablename)}
VB objectMember = {Convert(value(AttachObjects.Program+_Closure$__1).$VB$Local_mytable.tablename)}

CS getterLambda = {() => Convert(value(AttachObjectsCS.Program+<>c__DisplayClass0).mytable.tablename)}
VB getterLambda = {() => Convert(value(AttachObjects.Program+_Closure$__1).$VB$Local_mytable.tablename)}

我的猜測是問題在於$VB$Local_中的$VB$Local_mytable.tablename

現在,我想知道必須更改什么才能在VB.NET中工作。
有人知道/有線索嗎?

編輯:
嗯,問題似乎是由項目范圍設置中的“ Option Infer Off”引起的。
因此,問題變成了:如何使用“ Option Infer Off”來做到這一點?

您的問題與表達式樹無關(如果您不願意包含要得到的錯誤,這將更容易發現)。

您具有Option Infer OffOption Strict Off以及以下代碼:

Dim getter = getterLambda.Compile()

Return getter()

拋出MissingMemberException

找不到類型'Func(Of Object)'的默認成員。

問題是()在這里被解釋為調用默認成員而不是委托,因為getter的類型為Object 要解決此問題,可以指定變量的類型:

Dim getter As Func(Of Object) = getterLambda.Compile()

Return getter()

或者您可以使用更多詳細語法來調用委托:

Dim getter = getterLambda.Compile()

Return getter.Invoke()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM