调用泛型反射方法时,对象引用未设置为对象的实例

本文关键字:设置 对象 实例 对象引用 反射 泛型 方法 调用 | 更新日期: 2023-09-27 18:04:01

这个问题很令人困惑。它相当复杂和抽象,所以我将尽我所能来解释它。

我有3类LinkedIn, FacebookTwitter。它们都继承自一个公共基类SocialBase,该基类只有一个属性:uuid,并且该属性仅用于我们可以在数据库中找到实际类型。

所以我有这个函数,它接受一个Profile类,其中包含所有LinkedIn, FacebookTwitter表的外键,以及一个Enum值,它将告诉我们是否查找LinkedIn, FacebookTwitter外键

public static async Task UnlinkSocialAccountFromProfile(Profile prof, SocialNetworks provider)
    {
        //TYPE variable of LinkedIn, Facebook, or Twitter
        var handler = HandlerMapping[provider];
        //client is MobileServiceClient
        var method = client.GetType().GetMethod("GetTable", Type.EmptyTypes);
        //MobileServiceClient.GetTable<handler>()
        var generic = method.MakeGenericMethod(handler);
        //IMobileServiceTable<handler> 
        var table = generic.Invoke(client, null);
        //Profile has 3 foreign keys, LinkedinUUID, FacebookUUID, TwitterUUID, we want the <handler>UUID
        string propertyValue = prof.GetType().GetProperty(handler.Name + "UUID").GetValue(prof) as string;
        //Invoke Extension method with our generic types
        var genMethod =
            typeof (Extensions).GetMethod("FilterByNamedProperty")
                .MakeGenericMethod(table.GetType().GetGenericArguments()[0], propertyValue.GetType());
        //Get the List<handler> that results from our query
        var result = await (Task<List<Linkedin>>)(genMethod.Invoke(null, new [] {table, "uuid", propertyValue}));
        //var result = await (table as IMobileServiceTable<SocialBase>).FilterByNamedProperty("uuid", propertyValue);
        await new SocialResources().DeleteIfExists((result as IList<SocialBase>)[0]);
}

我在这里做的是获取类的Type,所以这将是SocialBase子类之一。对于这个特殊的例子,我知道我要寻找LinkedIn类型。因此,在获得类型LinkedIn之后,我需要从我的MobileServiceTable调用泛型方法,所以通常它看起来像MobileServiceTable.GetTable<LinkedIn>(),但由于反射,我们必须采取更长的路线。

在得到我返回的IMobileServiceTable<LinkedIn>实例后,我得到了我正在寻找的外键的值。在本例中,它将被称为LinkedInUUID。现在棘手的部分来了。我有这个扩展方法,它将为我构建我的查询表达式,因为它的类型必须是Expression<Func<LinkedIn, bool>>

public async static Task<List<TSource>> FilterByNamedProperty<TSource, TValue>(this IMobileServiceTable<TSource> source, string propertyName, TValue value)
    {
        // uuid
        var property = typeof(TSource).GetProperty(propertyName);
        // (TSource)p
        var parExp = Expression.Parameter(typeof(TSource));
        //p.uuid
        var methodExp = Expression.Property(parExp, property);
        // value
        var constExp = Expression.Constant(value, typeof(TValue));
        // p.uuid == value
        var binExp = Expression.Equal(methodExp, constExp);
        // p => p.uuid == value
        var lambda = Expression.Lambda<Func<TSource, bool>>(binExp, parExp);
        return await source.Where(lambda).ToListAsync(); 
    }

我相信注释很好地解释了每个语句发生时的构建过程。然而,一旦我们到达return await ...,应用程序将崩溃。下面是该行之前的输出和紧随其后的错误。

IMobileServiceTable<TSource> source = {Microsoft.WindowsAzure.MobileServices.MobileServiceTable<SocialConnect.Linkedin>}(正确)

propertyName = uuid(正确)

TValue value = dscRJQSIxJaEfd(正确)

我有一种强烈的感觉,问题是我的lambda表达式,但如果我用这行var test = await (source as IMobileServiceTable<Linkedin>).Where(p => p.uuid == (value as string)).ToListAsync();测试扩展,它工作得很好。但是,一旦我改变它使用lambda变量比我得到异常。lambda表达式的实际值是{Param_0 => (Param_0.uuid == "dscRJQSIxJaEfd")},看起来是正确的

任何想法?

编辑不好意思,这是堆栈跟踪

的实际异常
`A first chance exception of type 'System.NullReferenceException' occurred in mscorlib.dll
System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.WindowsAzure.MobileServices.Query.FilterBuildingExpressionVisitor.GetTableMemberName(Expression expression, MobileServiceContractResolver contractResolver)
   at Microsoft.WindowsAzure.MobileServices.Query.FilterBuildingExpressionVisitor.VisitMemberAccess(MemberExpression expression)
   at Microsoft.WindowsAzure.MobileServices.Query.FilterBuildingExpressionVisitor.Visit(Expression node)
   at Microsoft.WindowsAzure.MobileServices.Query.FilterBuildingExpressionVisitor.VisitBinary(BinaryExpression expression)
   at Microsoft.WindowsAzure.MobileServices.Query.FilterBuildingExpressionVisitor.Visit(Expression node)
   at Microsoft.WindowsAzure.MobileServices.Query.FilterBuildingExpressionVisitor.Compile(Expression expression, MobileServiceContractResolver contractResolver)
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQueryTranslator1.AddFilter(MethodCallExpression expression)
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQueryTranslator1.VisitMethodCall(MethodCallExpression expression)
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQueryTranslator1.Visit(Expression expression)
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQueryTranslator1.Translate()
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQueryProvider.Compile[T](IMobileServiceTableQuery1 query)
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQueryProvider.<Execute>d__31.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
   at Microsoft.WindowsAzure.MobileServices.Query.MobileServiceTableQuery1.<ToListAsync>d__0.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
   at SocialConnect.Models.Extensions.<FilterByNamedProperty>d__22.MoveNext() in MobileServiceSample'MobileServiceSample'Extensions.cs:line 55`

调用泛型反射方法时,对象引用未设置为对象的实例

好了,我终于解决了这个问题。显然,问题不在于查询或我正在做的任何事情,而是与SocialBase类。我一直在使用它来制作方法,我知道泛型TEntity将具有uuid属性,因此我可以轻松地在任何数据库中找到它。但我猜这个字段没有被正确序列化,这就是导致NullReferenceException的原因。删除基类后,只是反射地找到属性和值,然后一切都开始正常工作。

我不明白为什么它以前不能正常工作,因为在此之前我一直在使用基础SocialBase类。