Pregunta

Antes de que empieces a dispararme, NO busco hacer esto, pero alguien en otra publicación dijo que era posible. ¿Como es posible? Nunca he oído hablar de heredar de nada usando la reflexión. Pero he visto algunas cosas extrañas ...

¿Fue útil?

Solución

Sin funciones virtuales para anular, no tiene mucho sentido subclasificar una clase sellada.

Si intenta escribir una clase sellada con una función virtual, obtendrá el siguiente error de compilación:

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

Sin embargo, puede obtener funciones virtuales en clases selladas declarándolas en una clase base (como esta),

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

El problema persiste, sin embargo, no puedo ver cómo se puede pasar por alto el compilador para dejarte declarar una subclase. Intenté usar IronRuby (ruby es el más intrépido de todos los lenguajes de piratería) pero ni siquiera me lo permitió.

La parte 'sellada' está incrustada en la MSIL, por lo que supongo que el CLR en sí lo hace cumplir. Tendría que cargar el código, desmontarlo, quitar el bit 'sellado', luego volver a montarlo y cargar la nueva versión.

Otros consejos

Lo siento por publicar suposiciones incorrectas en el otro hilo, no recuerdo correctamente. Usando el siguiente ejemplo, usar Reflection.Emit, muestra cómo derivar de otra clase, pero falla en el tiempo de ejecución al lanzar una excepción 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();
   }
}

Es MIGHT (aumentaría el tamaño si pudiera). Según los chicos de freenode, implicaría modificar el código de byte, usar Reflection.Emit y entregar al JIT un nuevo conjunto de códigos de byte.

No es que sepa cómo ... era justo lo que pensaban.

Es posible que el otro póster haya estado pensando más en la línea de Reflexión. Emita en lugar de las API de Reflexión de solo lectura más habituales.

Sin embargo, todavía no es posible (al menos según este artículo ). Pero ciertamente es posible arruinar algunas cosas con Reflection.Emit que no quedan atrapadas hasta que intentes ejecutar el código emitido.

Crea una nueva clase llamada GenericKeyValueBase

pon esto en esto

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

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

Y heredar de esa ventaja, puede agregar métodos de extensión adicionales para Agregar / Eliminar (Agregar y Eliminar) a su nueva clase derivada (y convertirla en una colección / diccionario) si se siente realmente bien.

Un ejemplo de implementación simple en el que usaría un System.Collections.Generic.KeyValuePair normal para una base, pero en su lugar puede usar el código anterior

  class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
    {
        public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
        {
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top