我目前正在尝试在我的解决方案中编写单元测试,但我想将我的单元测试放在不同的单独项目中。问题是当我生成一些假测试数据时,我需要设置类的属性,但这是不可能的,因为属性具有私有(private)/内部设置。
我找到了一种使用属性仅向某些项目公开内部属性的方法
InternalsVisibleTo
,这效果很好,但看起来有点困惑和不干净。我正在寻找更离散的方式将我的私有(private)属性(property)暴露给其他项目。例如,也许有一种方法可以公开我的属性,而无需在我的域类中显式添加属性?
知道我该怎么做吗?
编辑:我发现这篇关于在 csproj 文件中设置 InternalsVisibleTo
的文章。有人用过这个吗?
https://bartwullems.blogspot.com/2020/06/internalsvisibleto-in-your-csproj-file.html
最佳答案
this blog post 中描述了一种替代方案示例代码位于 GitHub ,它使用一个未记录的属性在访问私有(private)/内部成员的程序集中使用。
但请注意以下几点:
- 这没有记录,也不推荐
- 不能直接编译,需要使用Roslyn
- 它似乎甚至会忽略对私有(private)成员的访问,这绝对是需要非常小心的事情
但是,例如在处理动态程序集等时,它可能很有用,请参见下面的示例。
代码
这是需要完成的操作,在您的代码中添加 IgnoresAccessChecksToAttribute
,如以下代码所示(确保它不在任何其他命名空间下,否则它将不起作用):
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class IgnoresAccessChecksToAttribute : Attribute
{
public IgnoresAccessChecksToAttribute(string assemblyName)
{
AssemblyName = assemblyName;
}
public string AssemblyName { get; }
}
}
然后在代码中的任意位置添加属性,如下所示:
[assembly: IgnoresAccessChecksTo("AssemblyToAccess")]
或在 csproj 文件中:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute">
<_Parameter1>AssemblyToAccess</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
编译
编译很棘手,因为它不能用标准方法编译,而是必须通过 Roslyn 调用,应该有很多资源可以帮助您了解如何使用 Roslyn 进行动态编译,但这里是需要完成的特定细节此编译工作:
var compilationOptions = new CSharpCompilationOptions(OutputKind.ConsoleApplication).
WithMetadataImportOptions(MetadataImportOptions.All);
var topLevelBinderFlagsProperty = typeof(CSharpCompilationOptions)
.GetProperty("TopLevelBinderFlags", BindingFlags.Instance | BindingFlags.NonPublic);
// 22 is the value of the undocumented member BinderFlags.IgnoreAccessibility
topLevelBinderFlagsProperty.SetValue(compilationOptions, (uint)1 << 22);
装配生成器中的用法
一种合法用途是在动态编译需要访问内部类的程序集时,请参阅 my answer there示例代码。
关于.net - InternalsVisibleTo 的替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66007077/