The InternalsVisibleToAttribute
attribute is one way to do this but you have to realise that it exposes all internals to the other assembly.
Also note that if you're not using signed assemblies, the InternalsVisibleToAttribute
will allow access to internals from any assembly with that name. That may not be desirable.
Another option could be to use tooling to inject the required code from assembly "A" into assembly "B". That would allow "B" to function independently without accessing internals. It depends on how your assemblies are used whether that's a desirable solution or not.
Finally, you could access the code in assembly "A" using reflection. It's a bit fiddly but if there is just a couple of things you need it may be enough. This will also allow you to provide nice fallback or error handling when assembly "B" is present but A is missing.
As others have pointed out, reflection can provide access to anything in your assembly internal or not. If you need to protect your code you should look into obfuscation.