【问题标题】:Accessing property on DisplayClass object at runtime在运行时访问 DisplayClass 对象的属性
【发布时间】:2019-08-04 05:32:58
【问题描述】:

环境: VS2017,C# 7.0 面向 .NET Core 2.1。

我正在尝试编写一个用于单元测试的假/模拟类,但我在访问 DisplayClass 对象上的属性时遇到了困难,我知道它是 a closure class from an anonymous function

我的代码如下所示:

namespace MyCompany.Application.Web.Test.Fakes
{
    public class FakeElasticClient : IElasticClient
    {
        public FakeElasticClient() { }

        public Task<ISearchResponse<T>> SearchAsync<T>(Func<SearchDescriptor<T>, ISearchRequest> selector = null, CancellationToken cancellationToken = default(CancellationToken)) where T : class
        {
            var methodName = selector.Method.Name;
            dynamic tgt = selector.Target;
            object id = tgt?.GetType().GetProperty("id")?.GetValue(tgt, null);
            int? total;
            if (methodName.Contains("Quux"))
            {
                total = CountSomething((Guid)id);
            }
            else
            {
                total = CountSomethingElse((Guid)id);
            }

            return Task.Run(() => new FakeSearchResponse<T>(total ?? 0) as ISearchResponse<T>);
        }

        // … below here follows a couple thousand other methods

id 转换为Guid 会引发NullReferenceException,即使Visual Studio 调试器显示tgt 对象具有id 属性:

评论:

  • 我从this answer 窃取了object id = … 行。
  • tgt.GetType() 返回MyCompany.Application.Domain.Repository.Implementations.BusinessEntityRepository.&lt;&gt;c__DisplayClass8_0
  • tgt.GetType().GetProperties() 返回一个空的 PropertyInfo 数组。
  • this blog post 的启发,我为MyCompany.Application.Domain.Repository.Implementations.BusinessEntityRepositoryMyCompany.Application.Web.Controllers 类添加了[assembly: InternalsVisibleTo("MyCompany.Application.Web.Test")] 属性,据我所知,这是调用链中仅有的两个类。没有任何区别。
  • 我尝试过使用 IgnoresAccessChecksTo as described here,但无法编译任何东西。

如何检索id 的值?

【问题讨论】:

  • 编译器使用字段而不是属性生成闭包类型,因此id 将是一个字段;试试tgt.GetType().GetFields()。也就是说,如果您必须处理编译器的实现细节,我认为您将单元测试做得太过分了。
  • 这实际上是一个相当简单的单元测试,问题是我这里需要访问的值是在传递给方法的匿名函数内部。无论如何,您是完全正确的,当我将行更改为 object id = tgt?.GetType().GetField("id")?.GetValue(tgt); 时它会起作用。如果您将其添加为答案,我会将其标记为正确。 ??????

标签: c# dynamic reflection anonymous-function anonymous-types


【解决方案1】:

编译器使用字段而不是属性生成闭包类型,因此id 是一个字段。请改用tgt.GetType().GetFields()

【讨论】:

  • TIL 字段和属性之间的区别。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多