.Netのリフレクションを使用して、シールされたクラスからどのように継承できますか?
-
03-07-2019 - |
質問
あなたが私に発砲する前に、私はこれをするつもりはありませんが、別の投稿はそれが可能であると言った。どうして可能ですか?リフレクションを使用して何かを継承することは聞いたことがありません。しかし、私はいくつかの奇妙なものを見てきました...
解決
オーバーライドする仮想関数がなければ、封印されたクラスをサブクラス化することにはあまり意味がありません。
仮想関数を含むシールドクラスを記述しようとすると、次のコンパイラエラーが発生します。
// error CS0549: 'Seal.GetName()' is a new virtual member in sealed class 'Seal'
ただし、基本クラス(このように)で宣言することにより、仮想関数を封印されたクラスに入れることができます。
public abstract class Animal
{
private readonly string m_name;
public virtual string GetName() { return m_name; }
public Animal( string name )
{ m_name = name; }
}
public sealed class Seal : Animal
{
public Seal( string name ) : base(name) {}
}
問題はまだ残っていますが、サブクラスを宣言するためにコンパイラをすり抜ける方法がわかりません。 IronRubyを使用してみました(ルビーはすべてのハッケな言語の中で最もハッキングな言語です)が、それでも私を許しません。
「シールされた」部分はMSILに埋め込まれているため、CLR自体が実際にこれを実施していると思います。コードをロードし、それを逆アセンブルし、「封印された」ビットを削除してから再アセンブルし、新しいバージョンをロードする必要があります。
他のヒント
他のスレッドに誤った仮定を投稿してすみません、正しく思い出せませんでした。 Reflection.Emitを使用した次の例を使用して、別のクラスから派生する方法を示しますが、実行時にTypeLoadExceptionをスローして失敗します。
sealed class Sealed
{
public int x;
public int y;
}
class Program
{
static void Main(string[] args)
{
AppDomain ad = Thread.GetDomain();
AssemblyName an = new AssemblyName();
an.Name = "MyAssembly";
AssemblyBuilder ab = ad.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder mb = ab.DefineDynamicModule("MyModule");
TypeBuilder tb = mb.DefineType("MyType", TypeAttributes.Class, typeof(Sealed));
// Following throws TypeLoadException: Could not load type 'MyType' from
// assembly 'MyAssembly' because the parent type is sealed.
Type t = tb.CreateType();
}
}
It MIGHT (できればサイズを大きくします)。 freenodeの関係者によると、Reflection.Emitを使用してバイトコードを変更し、JITに新しいバイトコードのセットを渡す必要があります。
私が知っているということではなく...彼らが思っていた通りでした。
他のポスターは、より一般的な読み取り専用のReflection APIではなく、Reflection.Emitに沿って考えていた可能性があります。
ただし、それでも不可能です(少なくともこの記事)。しかし、Reflection.Emitで何かを台無しにすることは確かに可能です。それは、放出されたコードを実際に実行しようとするまでトラップされません。
GenericKeyValueBaseという新しいクラスを作成します
これを入れてください
public class GenericKeyValueBase<TKey,TValue>
{
public TKey Key;
public TValue Value;
public GenericKeyValueBase(TKey ItemKey, TValue ItemValue)
{
Key = ItemKey;
Value = ItemValue;
}
}
それから継承して、本当にクールだと感じたら、Add / Remove(AddAtとRemoveAt)の追加の拡張メソッドを新しい派生クラスに追加(およびコレクション/辞書)できます。
ベースに通常のSystem.Collections.Generic.KeyValuePairを使用するが、代わりに上記のコードを使用できる単純な実装例
class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
{
public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
{
}
}