Как вы можете наследовать от закрытого класса, используя отражение в .Net?

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

  •  03-07-2019
  •  | 
  •  

Вопрос

Прежде чем вы начнете стрелять в меня, я НЕ собираюсь этого делать, но кое-кто в еще одно сообщение сказал, что это возможно.Как это возможно?Я никогда не слышал о наследовании от чего-либо с помощью отражения.Но я видел кое-какие странные вещи...

Это было полезно?

Решение

Без переопределяемых виртуальных функций нет особого смысла создавать подклассы для закрытого класса.

Если вы попытаетесь написать закрытый класс с виртуальной функцией в нем, вы получите следующую ошибку компилятора:

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

Однако вы можете преобразовать виртуальные функции в закрытые классы, объявив их в базовом классе (например, так).,

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

Однако проблема все еще остается, я не вижу, как вы могли бы проскользнуть мимо компилятора, чтобы позволить вам объявить подкласс.Я пробовал использовать IronRuby (ruby - самый хакерский из всех хакерских языков), но даже он мне не позволил.

"Запечатанная" часть встроена в MSIL, так что я бы предположил, что сама среда CLR фактически обеспечивает это.Вам пришлось бы загрузить код, разобрать его, удалить "запечатанный" бит, затем собрать его заново и загрузить новую версию.

Другие советы

Я прошу прощения за публикацию неверных предположений в другой теме, я не смог правильно вспомнить.Используя следующий пример, используя отражение.Emit , показано, как получить производное от другого класса, но во время выполнения происходит сбой, вызывающий исключение 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();
   }
}

IT МОГ БЫ (увеличил бы размер, если бы мог).По словам ребят из freenode, это потребовало бы изменения байтового кода с использованием Reflection.Emit и передачи JIT нового набора байтового кода.

Не то чтобы я ЗНАТЬ как ...это было именно то, что они думали.

Другой участник, возможно, больше думал о Рефлексии.Emit, а не о более обычных API-интерфейсах Reflection, доступных только для чтения.

Однако это по-прежнему невозможно (по крайней мере, в соответствии с эта статья).Но, безусловно, можно что-то испортить с отражением.Излучение, которое не попадает в ловушку, пока вы не попытаетесь фактически выполнить переданный код.

Создайте новый класс под названием GenericKeyValueBase

положи в него вот это

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

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

И унаследуйте от этого, плюс вы можете добавить дополнительные методы расширения для Add / Remove (AddAt и RemoveAt) в свой новый производный класс (и сделать его коллекцией / словарем), если вам действительно нравится.

Простой пример внедрения, в котором вы могли бы использовать обычную систему.Коллекции.Generic.KeyValuePair для базы, но вместо этого можно использовать приведенный выше код

  class GenericCookieItem<TCookieKey, TCookieValue> : GenericKeyValueBase<TCookieKey,TCookieValue>
    {
        public GenericCookieItem(TCookieKey KeyValue, TCookieValue ItemValue) : base(KeyValue, ItemValue)
        {
        }
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top