0

I'll try to keep this as general as possible, as I'm trying to understand a pattern rather than solve a specific problem.

Suppose I have a web application (A), and I want to make part of its logic and/or structures available through a restricted interface. For example, I may want to enable users to register an account, but only through a AccountManager.RegisterAccount method rather than by doing a new Account (which users should not be allowed to call). Such users should be able to register the account, but not necessarily through the web application.

To achieve this, I create a class library (B), with all the base structures and business logic, leaving in the web app project just what relates to the web itself.

However, I can't see how I could release the library B without revealing parts that should be kept hidden from users of that class. The internal access modifier isn't really my tool here, because it would restrict those parts from the app A too. Instead, I need those parts to be "public" for A (which is a "privileged user" of B), but "non public" for the users of B.

How can I achieve that?

Simone
  • 1,260
  • 1
  • 16
  • 27
  • Why do you need `B`? Make `A` constructor `internal` and `RegisterAccount` `public`. – Sinatr Nov 14 '16 at 16:41
  • This is a very good use case for why you should use and program against interfaces and not concrete types. Expose the interfaces from the assemblies and use factory patterns to create instances of the concrete types that implement those interfaces or use DI/IoC to allow the instances to be injected directly. – Igor Nov 14 '16 at 16:56
  • This does not make any sense in the context of a web app. The user can't use Reflection from his web browser to access code you don't let him use. And there will be multiple users using your web server, some that haven't logged in yet so that library is loaded anyway. All that a web server ever needs to be secure is a door and a lock. And a security analyst, you need one. – Hans Passant Nov 14 '16 at 17:25
  • @Igor it's not really a matter of dependencies. I need the clients to use the implementation provided by the library, not only the interface it defines. – Simone Nov 15 '16 at 00:08
  • @HansPassant Security is not the concern here. The "access" I'm talking about is programmatic, for client code that uses my library, not a matter of authentication or authorization for users of my web app. – Simone Nov 15 '16 at 00:10
  • @Simone - I recommend a little reading, [Interface-based programming](https://en.wikipedia.org/wiki/Interface-based_programming) and on SO [What exactly is “interface based programming”?](http://stackoverflow.com/questions/1848442/what-exactly-is-interface-based-programming). – Igor Nov 15 '16 at 09:55
  • If the interface is public, doesn't the class implementing it also have to be public? – Jack Hughes Nov 15 '16 at 10:23
  • @Igor That's all true, I understand your point. And trust me, I know my stuff about interfaces. But what I'm trying to do here is not "hey client, here is how you should interact with something that behaves like this", it is more like "hey client, here's what you must use". No alternative implementation, no testing, nothing. – Simone Nov 15 '16 at 10:50
  • Which is what interface based programming excels at. Your implementations are marked as internal (or less if you have nested classes). Your interfaces are marked as public. Your module exposes either DI registration or Factory classes that create instances for those types you want to expose externally but the method signatures only return the interfaces (not concrete types). This gives the consumer of the module restricted access to only those types that you want to expose. – Igor Nov 15 '16 at 10:53
  • Correct (I missed your point about the factory earlier), but an open point remains: clients should only use certain types, but a certain client application should instead use more types. Such additional types would be used internally by the library (no problem), but they also should be "public" for client A and "non public" for other clients. Interface based programming does the second part, but is pointless as to the other requirement. The `InternalsVisibleTo` attribute suggested by Jack is exactly what I need. I'm sorry that I didn't make it clear before :) – Simone Nov 15 '16 at 12:08

1 Answers1

2

Sounds like internal is precisely what you need. Make AccountManager public and Account internal will prevent clients from interacting with the Account class. You can use InternalsVisibleTo to make Account class public to A but not for third party programs.

In your library you can place the following:

[assembly: InternalsVisibleTo("A")]

There are some obvious downsides to this approach. The library won't effectively have any internal implementation details because A is able to access them as public.

Jack Hughes
  • 5,514
  • 4
  • 27
  • 32