views:

70

answers:

3

I have a .NET assembly, to be released. Its release build includes:

  • A public, documented API of methods which people are supposed to use
  • A public but undocumented API of other methods, which exist only in order to help test the assembly, and which people are not supposed to use

The assembly to be released is a custom control, not an application. To regression-test it, I run it in a testing framework/application, which uses (in addition to the public/documented API) some advanced/undocumented methods which are exported from the control.

For the public methods which I don't want people to use, I excluded them from the documentation using the <exclude> tag (supported by the Sandcastle Help File Builder), and the [EditorBrowsable] attribute, for example like this:

/// <summary>
/// Gets a <see cref="IEditorTransaction"/> instance, which helps
/// to combine several DOM edits into a single transaction, which
/// can be undone and redone as if they were a single, atomic operation.
/// </summary>
/// <returns>A <see cref="IEditorTransaction"/> instance.</returns>
IEditorTransaction createEditorTransaction();

/// <exclude/>
[EditorBrowsable(EditorBrowsableState.Never)]
void debugDumpBlocks(TextWriter output);

This successfully removes the method from the API documentation, and from Intellisense. However, if in a sample application program I right-click on an instance of the interface to see its definition in the metadata, I can still see the method, and the [EditorBrowsable] attribute as well, for example:

// Summary:
//     Gets a ModelText.ModelDom.Nodes.IEditorTransaction instance, which helps
//     to combine several DOM edits into a single transaction, which can be undone
//     and redone as if they were a single, atomic operation.
//
// Returns:
//     A ModelText.ModelDom.Nodes.IEditorTransaction instance.
IEditorTransaction createEditorTransaction();
//
[EditorBrowsable(EditorBrowsableState.Never)]
void debugDumpBlocks(TextWriter output);

Questions:

  • Is there a way to hide a public method, even from the meta data?
  • If not then instead, for this scenario, would you recommend making the methods internal and using the InternalsVisibleTo attribute? Or would you recommend some other way, and if so what and why?

Thank you.

+5  A: 

internal/InternalsVisibleTo is a good approach, but it still generates the methods in the compiled code and they will be available via reflection.

You can always use a conditional compilation symbol for unit testing that only adds the testing methods and, when building your release version, not define that symbol. That way, the methods simply do not exist when not built in "Test" configuration.

CMerat
+1 used symbols like this in the past, by far the easiest way to go.
Adam
I don't mind about hackers using reflection; I just don't want ordinary consumers of the control to see undocumented methods. Also, conditional compilation wouldn't work because I [test the release version](http://stackoverflow.com/questions/420343).
ChrisW
If you create another configuration that only differs from the release version by having the extra methods, it ends up being the same. You don't need to be in Debug configuration to define other symbols.
CMerat
A: 

Personally I would use the compiler switch, but you could always use reflection in your unit test code to get to the private members.

Adam
Given that I will not use conditional compilation because I want to [test the release build](http://stackoverflow.com/questions/420343), do you know if it would be better to use reflection, or to use the `InternalsVisibleTo` attribute?
ChrisW
If the only differences between the two versions of code is going to be the signature of a method changing from private to public, I'd argue this doesn't affect the test coverage enough to be a problem. If anything will break, its very likely the compiler will catch it anyway. I'd use reflection - its internal and you don't want it getting out so settle.
Adam
A: 

The two possibilities are InternalsVisibleTo, and/or reflection. I'm not aware of any strong reason for prefering one over the idea.

ChrisW