Wie kann man aus einem verschlossenen Klasse erbt mithilfe von Reflektion in .NET?

StackOverflow https://stackoverflow.com/questions/155087

  •  03-07-2019
  •  | 
  •  

Frage

Bevor Sie mich beginnen Brennen, ich bin nicht die Suche, dies zu tun, aber jemand in , sagte ein anderer Post es möglich ist. Wie ist es möglich? Ich habe noch nie zu erben alles unter Reflexion gehört. Aber ich habe einige seltsame Dinge gesehen ...

War es hilfreich?

Lösung

Ohne virtuelle Funktionen außer Kraft zu setzen, gibt es nicht viel Sinn, in Subklassen eine versiegelte Klasse.

Wenn Sie eine versiegelte Klasse mit einer virtuellen Funktion darin versuchen, schreiben Sie den folgenden Compiler-Fehler:

// error CS0549: 'Seal.GetName()' is a new virtual member in sealed class 'Seal'

Sie können jedoch virtuelle Funktionen in versiegelten Klassen erhalten, indem sie in einer Basisklasse (wie diese) zu erklären,

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) {}
}

Das Problem bleibt aber, ich kann nicht sehen, wie Sie vorbei an den Compiler schleichen könnten Sie eine Unterklasse lassen erklären. Ich habe versucht, mit IronRuby (Rubin die hackiest aller hackety Sprachen), aber auch, es würde mich nicht.

Der ‚versiegelt‘ Teil wird in die MSIL eingebettet, also würde ich vermuten, dass der CLR selbst dies tatsächlich erzwingt. Sie würden den Code zu laden haben, ZERLEGEN es, entfernen Sie das ‚versiegelt‘ Bit, dann ist es wieder zusammenzusetzen, und laden Sie die neue Version.

Andere Tipps

Es tut mir Leid für falsche Annahmen in dem anderen Thread posten, scheiterte ich mich richtig wieder zu verwenden. Mit dem folgende Beispiel mit Reflection.Emit, zeigt, wie von einer anderen Klasse abgeleitet werden, aber es funktioniert nicht zur Laufzeit eine Type werfen.

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();
   }
}

Es MACHT (würde die Größe erhöhen, wenn ich könnte). Nach den Jungs auf freenode, wäre es ging es um den Byte-Code zu modifizieren, indem Reflection.Emit, und die JIT einen neuen Satz von Byte-Code übergeben.

Nicht, dass I KNOW , wie ... es war genau das, was sie dachten.

Das andere Plakat denkt eher entlang der Linien von Reflection.Emit mehr sein kann als das üblichere Nur-Lese-Reflection-APIs.

Allerdings ist nach wie vor nicht möglich ist (zumindest nach diesem Artikel ). Aber es ist sicherlich möglich Somethings mit Reflection.Emit vermasseln, die nicht gefangen werden, bis Sie versuchen, um tatsächlich das ausgestrahlte Code auszuführen.

Erstellen

eine neue Klasse namens GenericKeyValueBase

setzen diese in ihm

  public class GenericKeyValueBase<TKey,TValue>
    {
        public TKey Key;
        public TValue Value;

        public GenericKeyValueBase(TKey ItemKey, TValue ItemValue)
        {
            Key = ItemKey;
            Value = ItemValue;
        }
    }

Und von diesem erben plus Sie können für Hinzufügen / Entfernen (AddAt und RemoveAt) zu Ihrer neuen abgeleiteten Klasse (und machen es eine Sammlung / Wörterbuch) zusätzliche Erweiterungsmethoden hinzufügen, wenn Sie wirklich cool fühlen.

Ein einfaches implentation Beispiel, in dem Sie eine normale System.Collections.Generic.KeyValuePair für eine Basis verwenden würde, aber stattdessen können Sie den obigen Code verwenden

  class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
    {
        public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
        {
        }
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top