2011-12-13 16 views
5

Esiste un modo per ereditare da una classe astratta interna in una classe di runtime generata dinamicamente (come tramite riflessione) utilizzando .NET Framework 4.0?Assegna dinamicamente dalla classe interna tramite la riflessione

+2

Ecco non possibile. –

+4

Forse un po 'di background su cosa stai cercando di ottenere e perché sarebbe utile ottenere una risposta utile. –

+0

Non vedo perché questa domanda è stata chiusa come "non è una vera domanda". Penso che sia chiaro cosa volesse chiedere l'OP. Ammetto che è davvero piuttosto "perverso" (come ha scritto @John Hanna nella sua risposta), ma in realtà ho un problema (una classe che in precedenza era pubblica, è stata resa interna da una versione all'altra del framework da cui dipende), che possiamo "risolvere" ereditando da una classe interna, se fosse possibile ... – pholpar

risposta

18

Fuori da un senso generale di perversità di fronte a cose che non dovrebbero essere possibili, ho fatto un tentativo di vedere come lontano proverei a creare una classe ereditata da System.CurrentSystemTimeZone (una classe interna in mscorlib). Si arriva fino alla creazione di un TypeBuilder ma quando si chiama CreateType si getta un TypeLoadException con il messaggio "Accesso negato: 'System.CurrentSystemTimeZone'."

Un po 'più di giocherellando mi ha portato a concludere che è possibile creare un assembly dinamicamente con il nome sicuro che lo identifica come un assembly amico dell'assieme in cui è definito il tipo interno. Ma allora, in quel caso potresti semplicemente scrivere il codice class Foo : CurrentSystemTimeZone, senza lasciare trucchi.

In ogni caso, il codice per quanto riguarda la linea che getta è al di sotto, nel caso in cui uno è in vena di provare qualche variante ancora più perversa l'idea, e vuole un punto di partenza:

using System; 
using System.Reflection; 
using System.Reflection.Emit; 
using System.Threading; 

namespace ReflectPerversely 
{ 
    class SuicidallyWrong 
    { 
     private static ModuleBuilder mb; 
     public static Assembly ResolveEvent(Object sender, ResolveEventArgs args) 
     { 
      return mb.Assembly; 
     } 
     public static void Main(string[] args) 
     { 
      Assembly sys = Assembly.GetAssembly(typeof(string)); 
      Type ic = sys.GetType("System.CurrentSystemTimeZone",true); 
      AssemblyName an = new AssemblyName(); 
      an.Name = "CheatingInternal"; 
      AssemblyBuilder ab = Thread.GetDomain().DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave); 
      mb = ab.DefineDynamicModule("Mod", "CheatingInternal.dll"); 
      AppDomain currentDom = Thread.GetDomain(); 
      currentDom.TypeResolve += ResolveEvent; 

      TypeBuilder tb = mb.DefineType("Cheat", TypeAttributes.NotPublic | TypeAttributes.Class, ic); 

      Type cheatType = tb.CreateType(); 
     } 
    } 
} 
1

Non è possibile. Puoi usare tipi che non sono pubblici usando Assembly.GetType(), ma non puoi ereditarli. Jon Skeet explains in this article perché in genere è una cattiva idea accedere ai membri non pubblici e rispondere alla tua domanda in modo più approfondito di quanto avrei potuto.

+1

È possibile accedere a tipi interni tramite Reflection. –

+0

@YuriyFaktorovich Puoi accedervi, ma per quanto ne so non puoi ereditarne. – aevitas

+0

In realtà suppongo che tu possa utilizzare ILGenerator, ma non l'ho ancora provato. –

5

Certo che puoi e non hai bisogno di riflettere per quello. La classe ereditata solo bisogno di essere nello stesso assieme :)

È anche possibile impostare amicizia tra assiemi: http://msdn.microsoft.com/en-us/library/0tke9fxk%28v=VS.100%29.aspx, che consentirebbe l'accesso alle classi interne di un complesso. Questo approccio è a volte utile nella creazione di assemblaggi di Unit-Test che richiedono l'accesso interno agli assembly testati

+0

+1 per il valore di intrattenimento. Ma non si può fare amicizia tramite la riflessione, quindi non è veramente utile per EOG. –

+0

Interpreto "ex". come "ad esempio", quindi la riflessione potrebbe non essere un requisito difficile. – surfen

+0

Buon punto ... Immagino che @EOG debba ottenere -1 per il titolo che non corrisponde alla domanda ... ma penso che -2 sia troppo per questa domanda. –

Problemi correlati