入門書には、クラスの設定系のメンバーは、公開する必要が無ければprivateにせよ、
みたいなことがよく書かれています。

ですが、例えば自作クラス ClassA, ClassBがあるとして、
ClassA
{
 public int IntVal { get; private set; }
 public ClassB BVal { get; private set; }
}

IntValはいいとして、BValに関しては、getプロパティでBValへの参照を取得できてしまいます。
その参照を通してBValにある設定メソッドを呼べば、BValの内容を外部から変更し放題です。

これを防ぐ方法として
1. ClassBを不変にする(ClassB内には、コンストラクタ以外に設定方法を用意しない)
2. ClassBのクローンを返す
3. ClassB内の取得系メソッドのみを集めたインターフェースを返す
4. ClassBを値型(構造体)にする
一応、以上のようなことを思いつくのですが、ここで質問です。

この問題(メンバがクラス型の場合に、セッターを単にprivateにしてもカプセル化できない)について、
皆さんはどう対処してますか?

単に「カプセル化したければこんなテクニックもあるよ」というのを紹介してほしいのではありません。
皆さんが(使い捨てでない)プログラムを書く際に、実際に、どういう考え方で、どう対処しているのか、
あるいは特に対処していないのか、を知りたいです。

よろしくお願いします。