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.