Comment pouvez-vous hériter d'une classe scellée en utilisant la réflexion en .Net?

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

  •  03-07-2019
  •  | 
  •  

Question

Avant que vous ne tiriez dessus, je ne cherche PAS à le faire, mais quelqu'un dans un autre message disait que c'était possible. Comment est-ce possible? Je n'ai jamais entendu parler d'hériter de quelque chose en utilisant la réflexion. Mais j'ai vu des choses étranges ...

Était-ce utile?

La solution

Sans fonctions virtuelles à remplacer, il est inutile de sous-classer une classe scellée.

Si vous essayez d'écrire une classe scellée avec une fonction virtuelle, vous obtenez l'erreur de compilation suivante:

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

Cependant, vous pouvez obtenir des fonctions virtuelles dans des classes scellées en les déclarant dans une classe de base (comme celle-ci),

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

Cependant, le problème persiste, je ne vois pas comment vous pourriez vous faufiler devant le compilateur pour vous permettre de déclarer une sous-classe. J’ai essayé d’utiliser IronRuby (le ruby ??est la langue la plus difficile de toutes les langues hackety), mais même cela ne m’a pas laissé.

La partie 'scellée' est incorporée dans le MSIL, donc je suppose que le CLR lui-même applique cela. Vous devez charger le code, le désassembler, retirer le bit "scellé", puis le réassembler et charger la nouvelle version.

Autres conseils

Je suis désolé d'avoir publié des hypothèses incorrectes dans l'autre fil de discussion, je ne me suis pas rappelé correctement. L'exemple suivant, à l'aide de Reflection.Emit, montre comment dériver d'une autre classe, mais échoue lors de l'exécution d'une exception 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();
   }
}

Il PEUT (augmenterait la taille si je le pouvais). Selon les responsables de Freenode, cela impliquerait de modifier le code octet, d’utiliser Reflection.Emit et de remettre à la JIT un nouvel ensemble de code octet.

Ce n'est pas que je sache comment… c'était exactement ce qu'ils pensaient.

L’autre affiche a peut-être été plus inspirée par Reflection.Emmit que par les API de réflexion en lecture seule plus habituelles.

Cependant, cela n’est toujours pas possible (du moins selon cet article ). Mais il est certainement possible de visser quelque chose avec Reflection.Emmit qui ne soit pas pris au piège tant que vous n'avez pas essayé d'exécuter le code émis.

Créez une nouvelle classe appelée GenericKeyValueBase

mettre cela dedans

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

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

Et en hériter, vous pouvez ajouter des méthodes d'extension supplémentaires pour Ajouter / Supprimer (AddAt et RemoveAt) à votre nouvelle classe dérivée (et en faire une collection / dictionnaire) si vous vous sentez vraiment cool.

Un exemple d'implémentation simple dans lequel vous utiliseriez un System.Collections.Generic.KeyValuePair normal pour une base, mais pouvez à la place utiliser le code ci-dessus

  class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
    {
        public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
        {
        }
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top