C# 通过 System.Reflection 访问内部成员?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/171332/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accessing internal members via System.Reflection?
提问by Matthew Scharley
I'm trying to Unit Test a class that has many internal functions. These obviously need testing too, but my Tests project is seperate, mainly because it covers many small, related projects. What I have so far is:
我正在尝试对具有许多内部功能的类进行单元测试。这些显然也需要测试,但我的测试项目是独立的,主要是因为它涵盖了许多小的、相关的项目。到目前为止我所拥有的是:
FieldInfo[] _fields =
typeof(ButtonedForm.TitleButton).GetFields(
BindingFlags.NonPublic | BindingFlags.Instance |
BindingFlags.DeclaredOnly);
Console.WriteLine("{0} fields:", _fields.Length);
foreach (FieldInfo fi in _fields)
{
Console.WriteLine(fi.Name);
}
This spits out all the private members nicely, but still doesn't display internals. I know this is possible, because when I was messing around with the autogenerated tests that Visual Studio can produce, it asked about something to do with displaying internals to the Test project. Well, now I'm using NUnit and really liking it, but how can I achieve the same thing with it?
这很好地吐出所有私有成员,但仍然不显示内部结构。我知道这是可能的,因为当我在处理 Visual Studio 可以生成的自动生成的测试时,它询问与向 Test 项目显示内部结构有关的事情。好吧,现在我正在使用 NUnit 并且非常喜欢它,但是我怎样才能用它实现同样的目标呢?
采纳答案by Eric Schoonover
It would be more appropriate to use the InternalsVisibleTo
attribute to grant access to the internal members of the assembly to your unit test assembly.
使用该InternalsVisibleTo
属性将程序集内部成员的访问权限授予单元测试程序集会更合适。
Here is a link with some helpful additional info and a walk through:
这是一个包含一些有用的附加信息和演练的链接:
To actually answer your question... Internal and protected are not recognized in the .NET Reflection API. Here is a quotation from MSDN:
要实际回答您的问题... .NET 反射 API 中无法识别 Internal 和 protected。这是来自MSDN的引文:
The C# keywords protected and internal have no meaning in IL and are not used in the Reflection APIs. The corresponding terms in IL are Family and Assembly. To identify an internal method using Reflection, use the IsAssemblyproperty. To identify a protected internal method, use the IsFamilyOrAssembly.
C# 关键字 protected 和 internal 在 IL 中没有意义,也没有在反射 API 中使用。IL 中的相应术语是Family 和Assembly。要使用反射识别内部方法,请使用IsAssembly属性。要识别受保护的内部方法,请使用IsFamilyOrAssembly。
回答by Ash
Adding the InternalsVisibleToassembly level attribute to your main project, with the Assembly name of thre test project should make internal members visible.
将InternalsVisibleTo程序集级别属性添加到您的主项目,并使用三个测试项目的程序集名称应该使内部成员可见。
For example add the following to your assembly outside any class:
例如,将以下内容添加到任何类之外的程序集中:
[assembly: InternalsVisibleTo("AssemblyB")]
Or for a more specific targeting:
或者对于更具体的定位:
[assembly:InternalsVisibleTo("AssemblyB, PublicKey=32ab4ba45e0a69a1")]
Note, if your application assembly has a strong name, your test assembly will also need to be strongly named.
请注意,如果您的应用程序程序集具有强名称,则您的测试程序集也需要具有强名称。
回答by Mitch Wheat
I think you need to ask whether you should write unit tests for private methods? If you write unit tests for your public methods, with a 'reasonable' code coverage, aren't you already testing any private methods that need to be called as a result?
我认为您需要问是否应该为私有方法编写单元测试?如果您为公共方法编写单元测试,并且具有“合理”的代码覆盖率,那么您是否已经测试了任何需要作为结果调用的私有方法?
Tying tests to private methods will make the tests more brittle. You should be able to change the implementation of any private methods without breaking any tests.
将测试绑定到私有方法会使测试更加脆弱。您应该能够在不破坏任何测试的情况下更改任何私有方法的实现。
Refs:
参考:
http://weblogs.asp.net/tgraham/archive/2003/12/31/46984.aspxhttp://richardsbraindump.blogspot.com/2008/08/should-i-unit-test-private-methods.htmlhttp://junit.sourceforge.net/doc/faq/faq.htm#tests_11http://geekswithblogs.net/geekusconlivus/archive/2006/07/13/85088.aspx
http://weblogs.asp.net/tgraham/archive/2003/12/31/46984.aspx http://richardsbraindump.blogspot.com/2008/08/should-i-unit-test-private-methods.html http://junit.sourceforge.net/doc/faq/faq.htm#tests_11 http://geekswithblogs.net/geekusconlivus/archive/2006/07/13/85088.aspx
回答by Jon Skeet
Your code is only showing fields - so I'd hope it wouldn't show any internal members, as fields should always be private IMO. (With the potential exception of constants.)
您的代码仅显示字段 - 所以我希望它不会显示任何内部成员,因为字段应该始终是私有的 IMO。(常量除外。)
Does ButtonedForm.TitleButton actually have any non-private fields? If you're trying to find internal methodsthen obviously you need to be calling GetMethods
(or GetMembers
) to get at them.
ButtonedForm.TitleButton 实际上有任何非私有字段吗?如果您正在尝试查找内部方法,那么显然您需要调用GetMethods
(或GetMembers
) 来获取它们。
As others have suggested, InternalsVisibleTo
is very handy for testing (and almost solely for testing!). As for whether you should be testing internal methods - I certainly find it useful to be able to do so. I don't regard unit testing as being exclusivelyblack-box testing. Often when you know that public functionality is implemented using a few internal methods connected in a simple way, it's easier to do thorough testing of each of the internal methods and some "pseudo-integration" tests on the public method.
正如其他人所建议的那样,InternalsVisibleTo
对于测试非常方便(并且几乎仅用于测试!)。至于您是否应该测试内部方法 - 我当然觉得能够这样做很有用。我不认为单元测试只是黑盒测试。通常,当您知道公共功能是使用几个以简单方式连接的内部方法实现时,对每个内部方法进行彻底测试和对公共方法进行一些“伪集成”测试会更容易。
回答by Jon Skeet
A justification for using the InternalsVisible is under my circumstances. We purchase the source code to a Chart Control. We have found where we need to make some modifications to that source control and compile our own version. Now to ensure we did not break anything, there are some unit tests I need to write that need access to some internal fields.
使用 InternalsVisible 的理由是在我的情况下。我们购买了图表控件的源代码。我们找到了需要对该源代码控制进行一些修改并编译我们自己的版本的地方。现在为了确保我们没有破坏任何东西,我需要编写一些需要访问一些内部字段的单元测试。
This is a perfect case where the InternalsVisible makes sense.
这是 InternalsVisible 有意义的完美案例。
I was wondering, though, what do you do if you do not have access to the source? How could you get to an internal field? .Net Reflector can see that code, but I guess it is just looking at the IL.
不过,我想知道,如果您无法访问源代码,该怎么办?你怎么能进入内部领域?.Net Reflector 可以看到该代码,但我想它只是在查看 IL。