2008-09-30 6 views
15

Avant de commencer à tirer sur moi, je ne cherche pas à le faire, mais quelqu'un au another post a dit 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 ...Comment pouvez-vous hériter d'une classe scellée en utilisant la réflexion dans .Net?

+1

mmhh Je pense ici est quand la réputation est utile. Celui qui a répondu à cette question a 19 de représentant (au 30 septembre) Les chances sont qu'il ne sait pas de quoi il parle.D'un autre côté, nous vous avons, en disant que ce n'est pas possible. Donc, vous devriez vous faire confiance dans ce cas. – OscarRyz

+0

:) Kilhoffer (2,459) vs dalle.myopenid.com (19) – OscarRyz

+0

lol, drôle, Oscar! – user18931

Répondre

13

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 du compilateur suivant:

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

Cependant, vous pouvez obtenir des fonctions virtuelles dans les classes scellées en les déclarant dans une classe de base (comme celui-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) {} 
} 

le problème reste encore bien, je ne vois pas comment vous pourriez se faufiler devant le compilateur pour vous racontons une sous-classe. J'ai essayé d'utiliser IronRuby (ruby est le plus hack de toutes les langues hackety) mais même cela ne me laisserait pas.

La partie 'scellée' est intégrée dans le MSIL, donc j'imagine que le CLR lui-même l'applique réellement. Vous devez charger le code, le désassembler, retirer le bit «scellé», puis le réassembler et charger la nouvelle version.

+1

J'ai vu un exemple où quelqu'un a corrigé le clr lui-même. Faites une recherche sur Dinis Cruz et OWASP et vous devriez le trouver – alexmac

+1

crikey. C'est hardcore –

+8

Les failles de sécurité où l'attaquant est plus fort que le système de sécurité ne sont pas des failles. "J'ai fait irruption dans votre immeuble en remplaçant tous les verrous par des verrous identiques, sauf qu'ils répondent aux commandes Bluetooth de mon téléphone portable." L'attaque Bluetooth est hors de propos par rapport à la suppression de mes serrures! –

1

Il Might (augmenterait la taille si je pouvais). Selon les gars de freenode, cela impliquerait de modifier le code de byte, en utilisant Reflection.Emit, et de donner au JIT un nouvel ensemble de code de byte.

Pas que je SAVOIR comment ... c'était juste ce qu'ils pensaient.

+0

C'est la seule façon dont cela aurait du sens. Pour le travail, comment diable pourrait-on justifier cela? C'est juste fou. – Kilhoffer

+1

vous ne pouvez pas légitimement le justifier. – MagicKat

+1

Si vous faisiez cela, alors vous ne seriez pas en train de dériver d'une classe scellée ... vous seriez en train de baiser avec la classe pour enlever le cachet, puis faire une dérivation normale. Cela peut être une solution valide à votre problème, mais je dis juste qu'il ne dérive plus d'une classe scellée :-) –

1

L'autre affiche peut-être plus penser à Reflection.Emit plutôt que les API de réflexion en lecture seule plus habituelles.

Cependant, ce n'est toujours pas possible (au moins selon this article). Mais il est certainement possible de visser quelque chose avec Reflection.Emit qui ne sont pas piégés jusqu'à ce que vous essayez d'exécuter réellement le code émis.

8

Je suis désolé de publier des hypothèses incorrectes dans l'autre thread, j'ai échoué à rappeler correctement. À l'aide de l'exemple suivant, en utilisant Reflection.Emit, montre comment dériver d'une autre classe, mais il échoue à l'exécution en lançant 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(); 
    } 
} 
+2

Si vous ne pouvez pas charger la chose que vous avez générée, je ne pense pas que cela compte comme la création d'une classe dérivée ... Après tout, vous pouvez créer toutes sortes de choses en utilisant 'Reflection.Emit', mais ne fait pas en sorte que ces choses sont en quelque sorte maintenant valables. –

+4

@OrionEdwards: C'est ce que j'ai écrit dans cette réponse. Cela ne marchera pas, et j'avais tort dans mes hypothèses précédentes. – dalle

-2

Créer une nouvelle classe appelée GenericKeyValueBase

mis cela dans ce

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

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

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

Un exemple simple implentation où vous utiliseriez un System.Collections.Generic.KeyValuePair normal pour une base, mais peut plutôt utiliser le code ci-dessus

class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue> 
    { 
     public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue) 
     { 
     } 
    } 
+0

Je ne vois pas comment cela est lié à l'héritage de classes scellées. – Abel

+0

Les classes scellées qui mettent en œuvre ce qui précède pourraient maintenant être augmentées avec un objet TCookieKey/Value pour une pseudo-extensibilité. La méthode pourrait même être cachée dans la classe de base ... – Jay

Questions connexes