#プログラマが思春期の娘に言われると傷つく一言 – Togetterまとめ
http://togetter.com/li/294232
を見ていて、「お父さんと同じ名前空間に居たくない!」と「パパのコードと一緒にビルドしないで!」が秀逸だったので C# で実現してみました。正確には名前空間じゃなくて Prada というクラス名を見せないようにします(まあ、クラス名をネストの深い名前空間に入れておけば、名前空間自体を探ることも難しいと思うのですが…これはあとで調べてみよう)。
単純に AliceRoom のアセンブリのクラスを他のアセンブリに公開したくない場合は、private なり internal を使えばよいのですが、そうなると Lolita に Prada を渡したく。Lewis(今回はお父さん役)には見せたくないけども、友達の Lolita とは共有したい場合は、InternalsVisibleTo 属性を使ってフレンド共有をします。こうすることで internal クラスが LolitaRoom から見えるという状態になります。
// Lolita クラスにのみ公開する
[assembly: InternalsVisibleTo("LolitaRoom")]
namespace AliceRoom
{
public class Alice : Room.IPerson
{
public void Init()
{
var bag = new Prada();
bag.Owner = "Alice";
bag.Content = "my secret";
this.box = bag;
}
public string GetBagContent()
{
var bag = box as AliceRoom.Prada;
if (bag == null)
return "NONE";
else
return bag.Content;
}
}
/// <summary>
/// Plada クラスは LolitaRoom にのみ公開
/// </summary>
internal class Prada
{
// Owner を設定できるのは Alice だけ
public string Owner { get; internal protected set; }
// コンテンツは Lolita も取得できる
public string Content { get; set; }
}
}
さて、もうひと息やって、Prada オブジェクトを Lolita に渡すことにします。
渡し方をどうするかというと、Alice.Post( Lolita ) みたいに渡したいですよね。実際に渡す Prada オブジェクトは、以下の Main から見えない(公開しているのは LolitaRoom アセンブリのみ)ので、何を誰に渡すのかが必要です。しかし「何を」渡すか自体は、Alice と Lolita しか知らないので、どうやって渡すかは試案のしどころ。
class Program
{
static void Main(string[] args)
{
var alice = new AliceRoom.Alice();
var lolita = new LolitaRoom.Lolita();
var lewis = new LewisRoom.Lewis();
// Pradaを作成
alice.Init();
// AliceRoom.Prada は見れない
Console.WriteLine("alice room : {0}",
alice.GetBagContent());
Console.WriteLine("lolita room: {0}",
lolita.GetBagContent());
// Lolitaに渡す
alice.Post(lolita);
Console.WriteLine("alice room : {0}",
alice.GetBagContent());
Console.WriteLine("lolita room: {0}",
lolita.GetBagContent());
// Lwewis から AliceRoom.Prada は見れない
}
}
仕方がないので、渡すためのインターフェースを作ります。ここでは、IPerson インターフェースを作って object 型で渡しているのですが、途中シリアライズ化する方法もあります。そういう意味では INotify を使ってもいいと思います。
namespace Room
{
public abstract class IPerson
{
protected object box { get; set; }
public void Post(IPerson dest) {
dest.box = this.box;
this.box = null;
}
}
}
あと、Prada の Owner 情報は Alice なので、Lolita が勝手に書き換えてはいけません。クラス情報は Lolita に公開するけど、Prada.Owner.set は Alice だけが使えるように「internal protected set」にしておきます。
namespace LolitaRoom
{
public class Lolita : Room.IPerson
{
public void Post(Room.IPerson dest, object obj)
{
this.box = obj;
}
public string GetBagContent()
{
var bag = box as AliceRoom.Prada;
if (bag == null)
return "none";
else
return bag.Content;
}
}
}
そんな訳で「お父さんと同じ名前空間に居たくない!」を実現したのがこちら。
サンプルコードは github
https://github.com/moonmile/DontLookMyNamespace

