0

I'm doing some internal domain-specific library development at the moment, and incidentally the stuff i'm trying to model mimicks "class" and "object" relations fairly well. So objects of my C# class MyClass should sort of act like a domain specific class for objects of my C# class MyObject who play the part of object or instance. Now I would like the code in MyObject to access methods of MyClass, which should not be accessible to other classes/code in the project. Any ideas how to enforce this, asside from documenting it at hoping my fellow developers will respect this.

I hope I made my question clear enough, otherwise let me know.

Best regards!

S.C. Madsen
  • 5,100
  • 5
  • 32
  • 50
  • Wat? To me (and I'd wager a few others) "class" == "object". –  Nov 11 '10 at 16:32
  • I'm finding your question confusing. Objects are instances of classes and I'm not sure if you've got two classes, one called MyObject and one called MyClass, or if you have a class and an object? – Dave White Nov 11 '10 at 16:34
  • 1
    @Will: I suggest you read MyClassas as MyCategory – H H Nov 11 '10 at 16:34
  • Right, I might have chosen confusing wording here, but I would like to express the same sort of relationship we normally have between a class and objects of this class, but among objects in runtime. Did that make it any clearer or even worse? – S.C. Madsen Nov 11 '10 at 16:35
  • http://stackoverflow.com/questions/1244953/c-internal-abstract-class-how-to-hide-usage-outside-assembly just to throw one more wrench into the machine .... I personally like Justin's Answer – Patrick Nov 11 '10 at 16:36
  • @Henk: Good idea. Would it make my question clearer if I edited my question and renamed "Class" as "Category" and "Object" as "Sample"? – S.C. Madsen Nov 11 '10 at 16:37
  • An object, created from the class MyObject, is intended to be the blueprint for the creation of an object, created from the class MyClass? Are you looking to reproduce the `factory pattern` where you have an object that is responsible for the creation of other objects? – Dave White Nov 11 '10 at 16:38
  • @Patrick: I'm sorry, but "Justin" who? I just read through that question and didn't spot the name "Justin". Maybe I missed it... – S.C. Madsen Nov 11 '10 at 16:39
  • @Dave: no, more like having "private" attributes on "MyObject" only accessible from "MyClass" – S.C. Madsen Nov 11 '10 at 16:41
  • 2
    @S.C. I think Henk's answer will best solve your problem. You just need to ensure that MyClass and MyObject are in the same assembly and that there is nothing else in there that should have access to MyObject's internal methods. – Dave White Nov 11 '10 at 16:45

5 Answers5

3

You could always split MyClass and MyObject up into another project, and define MyClass and/or MyObject as an internal class. That way it can only be accessed by other objects in that assembly.

See: http://msdn.microsoft.com/en-us/library/7c5ka91b(VS.80).aspx

Justin Ethier
  • 131,333
  • 52
  • 229
  • 284
  • So I should create an assembly for just these two classes? That seems a little "heavy-duty", I think. Thank you for the suggestion though. – S.C. Madsen Nov 11 '10 at 16:50
  • 1
    Perhaps but it depends on your application; if there ends up being a lot of domain-specific logic in these classes then a new project may be a good way to separate that logic from the rest of your application. – Justin Ethier Nov 11 '10 at 16:55
3

The standard approach here is to declare the members internal and make sure MyClass and MyObject are part of the same assembly. That assembly should contain little else.

Additional: This is the tool that was designed for this purpose. Other languages have other means to fine-tune accessibility (C++: friend) but in .NET a simpler model was chosen.

And you don't have to take the 'nothing else' so strictly, the 2 classes could share an assembly with other related classes. you would then have to verify the no-access rule(s) manually inside that library.

H H
  • 263,252
  • 30
  • 330
  • 514
2

I'd suggest a private nested class. That way, even if your fellow devs are writing code in the same namespace, they'll never be able to access the class.

Once the class declaration is fully enclosed within another class declaration, the class is considered nested and can only be accessed through the containing class.

spender
  • 117,338
  • 33
  • 229
  • 351
  • I'm assuming that he wants some methods on both classes publicly accessible but that he wants some methods on one of the classes only accessible to the other class and not publicly accessible. This solution makes the entire second class inaccessible publicly. – Dave White Nov 11 '10 at 16:47
  • Fair suggestion, but I need both kind of objects to instantiated from a "Factory", which will differ at runtime. I'm not sure nested classes will handle that? – S.C. Madsen Nov 11 '10 at 16:47
1

If you don't want your consumers to invoke certain implementation specific methods you could try abstracting to interfaces or abstract base classes. That way the consumer will only 'see' the properties and methods you want them to see.

You do not have to use inheritance to provide shared functionality and you do not have to rely on member accesibility to prevent others from using methods you'd rather not expose.

For example:

public interface IDomainSpecific
{
   void DoStuff();
} 

public interface IDomainService
{
   void HelpMeDoStuff();
}

public class DomainObject1 : IDomainSpecific
{
  private readonly IDomainService _service;

  public DomainObject1( IDomainService service )
  {
    _service = service;
  }

  public DoStuff()
  {
    // Do domain specific stuff here 
    // and use the service to help
    _service.HelpMeDoStuff();
  }
}

This uses classic constructor injection and works best when you already use dependency injection in your application, though it works perfectly well with factories as well.

The point is to keep responsibilities crystal clear. There's no chance of anybody invoking anything they shouldn't because the 'DomainObject' never knows what concrete type implements the shared service. The shared service is not exposed on the domain object either. The added bonus is testability and the possibility of swapping the service with another implementation without ever needing to touch the DomainObject.

Marnix van Valen
  • 13,265
  • 4
  • 47
  • 74
  • Right, i like the sound of this. Could you post an example? – S.C. Madsen Nov 11 '10 at 16:51
  • Abstraction is different than accessibility. S.C. will still run into the same problems with interfaces and abstract base classes. – Dave White Nov 11 '10 at 17:03
  • @Dave White: He'll have to hide the constructors and create factory methods to create instances, but that's not a big deal. And at least it serves as "hints to fellow developers". – TMN Nov 11 '10 at 17:27
  • @TMN - Sure. Totally feasible. But you've added the "accessibility" notion to the original answer which, by itself, is incomplete and doesn't solve the OP's problem. – Dave White Nov 11 '10 at 18:08
  • The way I interpret the problem you have two contracts; the common (public?) interface for your 'instances' and the contract between the 'instance' and its 'class'. The latter is an internal dependency that can be injected into the 'instance'. This will keep the internals completely separate from the public stuff. No matter in what assembly each class resides. – Marnix van Valen Nov 11 '10 at 20:42
  • @Marnix - That sounds like great approach. But you've added the notion of accessibility to your answer in this comment, where in your answer, you have only discussed abstraction which by itself doesn't solve the problem. – Dave White Nov 12 '10 at 16:45
  • @Dave White - I had no idea there was a rule against elaborating on an answer with a comment. Anyway, I have updated my answer. – Marnix van Valen Nov 12 '10 at 20:45
1

Pehaps your MyObject should descend from MyClass and declare the methods in MyClas as protected.

Kell
  • 3,252
  • 20
  • 19