【发布时间】: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.<>c__DisplayClass8_0 -
tgt.GetType().GetProperties()返回一个空的PropertyInfo数组。 - 受this blog post 的启发,我为
MyCompany.Application.Domain.Repository.Implementations.BusinessEntityRepository和MyCompany.Application.Web.Controllers类添加了[assembly: InternalsVisibleTo("MyCompany.Application.Web.Test")]属性,据我所知,这是调用链中仅有的两个类。没有任何区别。 - 我尝试过使用
IgnoresAccessChecksToas described here,但无法编译任何东西。
如何检索id 的值?
【问题讨论】:
-
编译器使用字段而不是属性生成闭包类型,因此
id将是一个字段;试试tgt.GetType().GetFields()。也就是说,如果您必须处理编译器的实现细节,我认为您将单元测试做得太过分了。 -
这实际上是一个相当简单的单元测试,问题是我这里需要访问的值是在传递给方法的匿名函数内部。无论如何,您是完全正确的,当我将行更改为
object id = tgt?.GetType().GetField("id")?.GetValue(tgt);时它会起作用。如果您将其添加为答案,我会将其标记为正确。 ??????
标签: c# dynamic reflection anonymous-function anonymous-types