views:

81

answers:

4

Recently I was reading about partitioning code with .NET assemblies and stumbled upon a nice suggestion from this post: "reduce the number of your .NET assemblies to the strict minimum".

I couldn't agree more! And one of the reasons I personally see most often, is that people just want to isolate some piece of code, so they make the types/methods internal and put them into a separate project.

There are many other reasons (valid and not) for splitting code into several assemblies, but if you want to isolate components/APIs while still having them located in one library, how can you do that?

namespace MyAssembly.SomeApiInternals
{
     //Methods from this class should not 
     //be used outside MyAssembly.SomeApiInternals
     internal class Foo
     {              
          internal void Boo() { }
     }
}

namespace MyAssembly.AnotherPart
{
     public class Program
     {              
          public void Test() 
          {
               var foo = MyAssembly.SomeApiInternals.Foo();
               foo.Boo(); //Ok, not a compiler error but some red flag at least 
          }
     }
}             

How can one restrict a type/method from being used by other types/methods in the same assembly but outside this very namespace?

(I'm going to give a few answers myself and see how people would vote.)

Thanks!

A: 

Mark methods/types in MyAssembly.SomeApiInternals with Obsolete attribute and suppress the warnings inside the namespace.

If the methods/types will be used outside of the namespace, we'll get a compiler warning.

andreister
+1  A: 

Use NDepend and put in CQL rules that embody what you want and run them as part of your build. The language isnt interested in this level of restrictions. (I hadnt followed your link yet - are you really trying to do this without NDepend? Your answer should rule it in or out)

Ruben Bartelink
Exactly, that's something I'm also thinking about. Neat solution but only for those who use NDepend :)
andreister
@andreister: If you're going to invest the time to do stuff like this, having it automated and working properly is essential or people will stop doing it. The price of an NDepend license would be'd even figure in this calculation.
Ruben Bartelink
See also http://feedproxy.google.com/~r/CodeBetter/~3/FnLEmvpVmkY/ndepend-v3-is-now-100-integrated-in-visual-studio.aspx
Ruben Bartelink
+1  A: 

If you use ReSharper, employ RIANT plugin.

It would allow you to mark types/methods with <restrict> tag and specify the namespace where the usages are allowed. There will be R# warnings for any usages outside the restricted namespace:

alt text

andreister
Obviously this is great - all you need to do is decide whether you want NDepend to give the rule teeth for non R# / Non RIANT users
Ruben Bartelink
+3  A: 

You could put the code in different assemblies, then merge the assemblies with ILMerge in a post-build step...

Thomas Levesque
This is clearly the optimal approach, I feel the reasoning for using as few assemblies as possible are completely bogus. The cost of not having the clearly defined assemblies is way higher (IMO) than any justification that could be made. For the OP if performance is your concern, this is one of the last places you should be looking to make good baseline decisions.
Chris Marisic
Yup, this solution seems to be the best one as it doesn't use proprietary tools. Re "if performance is your concern" - what about compilation time? If you could "cut the compile time from 4 minutes to 20 seconds" (from here: http://codebetter.com/blogs/jeremy.miller/archive/2008/10/10/183438.aspx) it's something I'd like to pursue! :)
andreister