質問
C#3.0および.NET 3.5では、インターフェースがあると想像してください:
public interface INameable
{
string Name {get;}
}
およびインターフェースを実装する多くの不変のクラス。
単一の拡張メソッドが欲しい
public static T Rename<T>(this T obj) where T : INameable
{
...
}
名前だけが変更された元のオブジェクトのラップされたインスタンスを返し、他のすべてのプロパティ読み取りとメソッド呼び出しは元のオブジェクトにルーティングされます。
すべてのINameable実装型に実装せずに、このための汎用ラッパークラスを取得する方法は?それは可能だと思いますか?
解決
いいえ、これは不可能です。ただし、 T
がインターフェイスまたはすべてのメンバー仮想を持つクラスに制限されていない限り、この制約はコンパイル時に指定できません(ただし、そのアプローチに満足している場合は、ランタイムチェックを記述できます。
任意の型に対してできないのは、 T
型のオブジェクトを取得する場合、 T
に割り当て可能なオブジェクトを返す必要があるためです。次のように見えるオブジェクトを渡すと...
public sealed class SomeClass : INameable
{
public string Name { get; }
public string Abc { get; }
}
... SomeClass
に割り当て可能な別のタイプを作成する方法はありません。型がシールされているため、 Reflection.Emit
または他のメソッドを使用していません。
ただし、前述の制限に満足している場合は、Castle DynamicProxyフレームワークなどを使用して、渡されたオブジェクトをプロキシし、次のように転送または再実装の呼び出しをインターセプトする型を作成できます適切。
他のヒント
まあ、はい、可能ですが、メモリ内でコードを生成する必要があります。
Reflection.Emit およびこちら。
多くのコードが含まれることに注意してください。
つまり、私はあなたを正しく理解していると思います。
あなたが求めているのは次のとおりです:
SomeNameableObject a1 = new SomeNameableObject("ThisIsTheFirstName");
SomeNameableObject a2 = a1.Rename("ThisIsTheSecondName");
// a1 works, still has the name ThisIsTheFirstName
// a2 works, but everything is routed to a1,
// except for the name, which is ThisIsTheSecondName
それは正しいですか?