InternalsVisibleTo does not work - c#

I insert the line:
[assembly: InternalsVisibleTo("MyTests")]
inside my project under test( Properties/AssemblyInfo.cs) where MyTests is the name of the Unit Test project. But for some reason I still cannot access the internal methods from the unit test project.
Any ideas about what I am doing wrong ?

If your assembly is signed with a strong name look at this answer.
Otherwise check that the name of your test assembly really is "MyTests.dll" (it doesn't have to match the project name, though it will by default).

Let's break it down a bit as many of us have experienced this slight mix-up in the past...
Assembly A has your internal class.
Assembly B has your unit tests.
You wish to grant the internals of assembly A visibility in assembly B.
You need to put the InternalsVisibleTo assembly attribute inside assembly A and grant access to assembly B.

You still need your test project to reference your main project.
This can be easy to overlook and if you have no existing test code this may appear like the InternalsVisibleTo is not functioning.

I had the same issue after renaming a namespace. Basically the in .cs files was the new namespace but in the .csproj and AssemblyInfo.cs it was the old namespace.
namespace newNamespace {
....
}
So, I changed in .csproj the following to the new namespace:
<RootNamespace>oldnamespace</RootNamespace>
<AssemblyName>oldnamespace</AssemblyName>
And in AssemblyInfo.cs:
[assembly: AssemblyTitle("oldnamespace")]
[assembly: AssemblyProduct("oldnamespace")]

In my case I was coding to an Interface. As interfaces can only specify public properties the internal properties were not present on the interface.
Make sure you're not doing the same thing as I was!
I changed:
Assert.IsNotNull((exportFileManager)?.ThumbnailFileExporter);
To:
Assert.IsNotNull((exportFileManager as ExportFileManager)?.ThumbnailFileExporter);

I made the incorrect assumption that InternalsVisibleTo will help in accessing Private methods too.
Here are some other aspects that can lead to this error:
Your class is either internal or public
Your method is internal
The InternalsVisibleTo property contains the full namespace of your test project.

You can expose internals from strong named assembly to another strong named friend assembly only. But non-strong named assembly can expose internals to strong named friend assembly.

Related

Is it possible to make all internal classes visible to another assembly in C# with some configuration?

I know that is possible change the visibility with:
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("UnitTests")]
namespace Foobar
{
internal class Foo
{
//...
}
}
So my test project can create the test for the class Foo. The problem is that I have a lot of internal classes and I don't want to dirty them with that assembly expression. Is there another way of doing this InternalsVisibleTo("UnitTests") for the whole project?
The [InternalsVisibleTo] attribute is an assembly-level attribute, meaning that if you define it once, it already applies to the entire assembly.
So that line you show only needs to be included only once in your project to apply to all internal types.
I'd recommend moving it to where the other assembly-level attributes are specified: in the AssemblyInfo.cs file in the Properties folder of the project.
To expand upon the comment from #CodeCaster, the attribute should be placed in
AssemblyInfo.cs
in the Properties section of your project
e.g.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: InternalsVisibleTo("UnitTests")]
you will also need to fully qualify the assembly name
e.g.
[assembly: InternalsVisibleTo("Foo.Bar.UnitTests")]

Keyword global:: when adding reference

I've encountered a strange phenomenon today as I added a reference of a project to another project and trying to use an interface of the referenced assembly:
Situation:
The class MySampleApplication is in the project MyApplication.
The interface IMySampleApplication is in the referenced project MyApplication.Interfaces.
When I do this:
public class MySampleApplication : IMySampleApplication
Resharper adds the following using:
using global::MyApplication.Interfaces;
Question:
Why is it adding the global:: prefix and how can I avoid this?
Thanks in advance
You'll have two occurrences of MyApplication somewhere in your code, eg you'll likely have a class called MyApplication in your local project as well as the namespace in the MyApplication project.
The local MyApplication will take precedence over the namespace in your MyApplication project, so MyApplication.Interfaces will not be found. To get around this, the special alias global:: can be used to tell the compiler that in this case MyApplication refers to a base namespace and so MyApplication.Interfaces can then be correctly identified.
As to how to avoid it, that's easy to say, but it may be harder to achieve: rename one of them to remove the name conflict...
You probably have another entity called MyApplication in your project which is hiding the namespace.
See: "How to: Use the Global Namespace Alias (C# Programming Guide)"

C# - How to make my assembly strongly named?

I'm trying to create unit tests for some of my private methods and I read that you can access them from your unit tests via [assembly: InternalsVisibleTo("DLLName")].
However, mine's not working and another solution was to add the Public Key. I tried to get the Public Key of my unit test project via sn -Tp DLLName but it is complaining that it isn't strongly named.
How can I make it so that it is strongly named? Am I using the InternalsVisibleTo the wrong way?
I think if you go to the properties of your project, on the side bar there should be a navigation link called "Signing". There should be an option to sign the assembly. If that is not there, then I don't think you can give it a strong name?
Chances are your unit test assembly isn't strongly named at the moment - after all, it's a relatively unusual requirement, as the reasons for strong naming don't often apply to test assemblies.
However, the use of InternalsVisibleTo does necessitate this - because it's a bit like you're adding a reference from the strongly-named production assembly to the test assembly, and you can't refer to a non-strongly-named assembly from a strongly-named one.
So just make the test assembly strongly named in the same way as you have for the production assembly (Project Properties, Signing), give it a key (e.g. the same one as your production assembly) and then use sn -Tp to get the public key.
All this is assuming that the reason your original InternalsVisibleTo attempt didn't work because the production assembly is strongly-named. If it isn't, then signing the test assembly won't help at all, and you need to give us more information about the problem you're seeing.
To create and sign an assembly with a strong name using the Assembly Linker
At the command prompt, type the following command:
al /out:<assembly name> <module name> /keyfile:<file name>
In this command, assembly name is the name of the assembly to sign with a strong name, module name is the name of the code module used to create the assembly, and file name is the name of the container or file that contains the key pair.
The following example signs the assembly MyAssembly.dll with a strong name using the key file sgKey.snk.
al /out:MyAssembly.dll MyModule.netmodule /keyfile:sgKey.snk

C# asp.net - The type or namespace name 'Helper' could not be found (are you missing a using directive or an assembly reference?)

I'm reworking someone else's code, where they had a helper class with way to much code that shouldn't be there (data access, business logic, everything had slowly been shoved in there).
I've moved the relevant code into the appropriate pre-existing classes and created a separate, brand new helper class in the appropriate project, but all my references to this class simply don't work.
Here's a simple view of how my class looks (names slightly changed);
namespace Company.Web.Application.Reporting
{
public class ReportHelper
{
here I have a bunch of methods
}
}
and here is how it is being referenced;
using Company.Web.Application.Reporting;
namespace Company.Web.Application.App.Reports
{
public partial class PlansReports : PageBase
{
//This is the problem part
private ReportHelper Helper = new ReportHelper();
heaps of other code with no problems here...
}
}
My problem is that the I get the following error, everywhere that I try to access my new helper.
The type or namespace name
'ReportHelper' could not be found (are
you missing a using directive or an
assembly reference?)
All my using statements are there, I have the appropriate references in each relevant project, yet this still persists.
At this point I am totally stuck, I just need to get this referencing issue sorted out so I can ensure all my helper methods work correctly.
Any help is greatly appreciated,
Pat.
OK, I found the problem (actually a colleague did)
This original Helper class was contained in the app_code folder of my main project, which as I have just learned, handles compiling differently to all other folders in a project.
Code in here is compiled at run time, rather than during the build.
When I created my new classes, they were in the app_code folder because I used code rush to extract the class to a new file, which kept it in the same location...after which I moved them to their "sensible" location.
Unfortunately they still had the build action of "Content" inherited from their previous presence in the app_code folder.
So, on the new class file, I simply changed its build action to "Compile" and now all is well with the world.
Cheers,
Pat.
Is your ReportHelper in a separate project or DLL? If so have you added this project/dll as a reference? (In your solution explorer under References, check your project/dll is there.
Have you built Company.Web.Application.Reporting so that the type would be known? That would be my idea along with ensuring that the dependencies are set up properly.
It sounds like you know what you are doing and everything looks right, so it has to be something simple. Are you trying to access changes in ReportHelper that haven't been compiled into the dll? I would try rebuilding the reference assembly; every time you make changes to that assembly, it needs to be rebuilt.
Also verify you are adding the correct assembly (e.g. Debug vs. Release) to your project. It doesn't matter which type, but you don't want compile new changes into the Debug dll, and keep adding the old version of the Release dll.

COM Interop registration

I have a .NET assembly which I am exposing to COM. The assembly has two public interfaces and one public class. When I build the assembly I get this warning:
(assemblyName.dll) does not contain any types that can be registered for COM Interop.
My assembly information includes the following line.
[assembly: ComVisible(true)]
Most people having this problem on the web, that I have found, fixed it with the above line in their assembly information. This has not helped for me.
I also tried adding [ComVisible(true)] to the class and interface definitions, and it also did not help.
ComVisible classes generally need to have a public default constructor. Its members should typically also reference only ComVisible types.
You don't need to specify ComVisible(true) on the class if you have specified it at the assembly level.
However, the usual way to generate an assembly with ComVisible classes is:
Specify ComVisible(false) at assembly-level. Thus only classes that are explicitly marked with ComVisible(true) are exposed to COM.
Define an explicit ComVisible interface :
e.g.
[
ComVisible(true),
GuidAttribute("..."),
Description("...")
]
public interface IMyComVisibleType
{
// members...
}
Your ComVisible class should specify ClassInterfaceType.None, and should implement the ComVisible interface:
e.g.
[
ComVisible(true),
GuidAttribute("..."),
ClassInterface(ClassInterfaceType.None)
]
public sealed class MyComVisibleType : IMyComVisibleType
{
// implementation ...
}
Note that the Guid and Description attributes are not required, but useful to give you more control of the COM generation.
If the above doesn't help, try posting some sample code and I'm sure someone will be able to help.
I ran into the default constructor problem. What fooled me was that the type library file will contain the class GUID reference even though that class is not being registered. A quick way to see what will be registered is to create a registry file ('assembly.reg') like this:
regasm assembly.dll /regfile:assembly.reg /codebase
There's a good discussion of exposing interfaces in COM Interop: Base class properties not exposed to COM. Some example code is here: Exposing .NET Components to COM.
Here are a few other things to true
Make sure the types you want to register are marked as public
Add the ComVisible(true) attribute to the type directly in addition to the assembly
Add the Guid attribute
Not sure if the last 2 are strictly necessary but I would try them out.
I think you need to have a strong-named assembly. Do you sign your assembly with a key file?
Further, also try specifying :
[Guid("{newly generated GUID}")]
[ClassInterface(ClassInterfaceType.AutoDual)]
I had the same problem on a project where I checked the "Register For COM interop" option for my C# project. There is an easy solution:
While in the Solution Explorer, go to the Properties folder. Open the AssemblyInfo.cs file. Scroll down to the line that says:
[assembly: ComVisible(false)]
Change this to:
[assembly: ComVisible(true)]
This will remove the warning messages, and allows the .tlb file to be created, which then enables the .NET code for COM visibility.
If you don't want the entire assembly to be COM-visible then follow one of the other tips above.

Categories

Resources