如何在 .Net 中使用反射从密封类继承?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/155087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:10:23  来源:igfitidea点击:

How can you inherit from a sealed class using reflection in .Net?

.netinheritance

提问by Kilhoffer

Before you start firing at me, I'm NOT looking to do this, but someone in another postsaid it was possible. How is it possible? I've never heard of inheriting from anything using reflection. But I've seen some strange things...

在你开始向我开火之前,我不打算这样做,但有人在另一篇文章中说这是可能的。这怎么可能?我从未听说过使用反射从任何东西继承。但是我看到了一些奇怪的东西......

采纳答案by Orion Edwards

Without virtual functions to override, there's not much point in subclassing a sealed class.

如果没有要覆盖的虚函数,则对密封类进行子类化就没有多大意义。

If you try write a sealed class with a virtual function in it, you get the following compiler error:

如果您尝试编写一个带有虚函数的密封类,则会出现以下编译器错误:

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

However, you can get virtual functions into sealed classes by declaring them in a base class (like this),

但是,您可以通过在基类中声明虚函数来将它们放入密封类中(像这样),

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

The problem still remains though, I can't see how you could sneak past the compiler to let you declare a subclass. I tried using IronRuby (ruby is the hackiest of all the hackety languages) but even it wouldn't let me.

问题仍然存在,我看不出你如何偷偷溜过编译器让你声明一个子类。我尝试使用 IronRuby(ruby 是所有 hackety 语言中最黑客的),但即使它也不让我使用。

The 'sealed' part is embedded into the MSIL, so I'd guess that the CLR itself actually enforces this. You'd have to load the code, dissassemble it, remove the 'sealed' bit, then reassemble it, and load the new version.

“密封”部分嵌入到 MSIL 中,因此我猜想 CLR 本身实际上会强制执行此操作。您必须加载代码,反汇编它,移除“密封”位,然后重新组装它,并加载新版本。

回答by dalle

I'm sorry for posting incorrect assumptions in the other thread, I failed to recall correctly. Using the following example, using Reflection.Emit, shows how to derive from another class, but it fails at runtime throwing an TypeLoadException.

我很抱歉在另一个线程中发布了不正确的假设,我没能正确回忆。使用以下示例,使用 Reflection.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();
   }
}

回答by MagicKat

It MIGHT(would increase the size if I could). According to the guys on freenode, it would involved modifying the byte code, using Reflection.Emit, and handing the JIT a new set of byte code.

MIGHT(会增加大小,如果我能)。根据 freenode 上的人的说法,这将涉及修改字节码,使用 Reflection.Emit,并将一组新的字节码交给 JIT。

Not that I KNOWhow ... it was just what they thought.

并不是说我知道如何......这正是他们的想法。

回答by Rob Walker

The other poster may have been thinking more along the lines of Reflection.Emit rather than the more usual read-only Reflection APIs.

另一位发布者可能更多地考虑了 Reflection.Emit 而不是更常见的只读 Reflection API。

However, still isn't possible (at least according to this article). But it is certainly possible to screw somethings up with Reflection.Emit that are not trapped until you try to actually execute the emitted code.

但是,仍然不可能(至少根据本文)。但是,在您尝试实际执行发出的代码之前,使用 Reflection.Emit 肯定可以搞砸一些不会被捕获的东西。

回答by Rob Walker

Create a new class called GenericKeyValueBase

创建一个名为 GenericKeyValueBase 的新类

put this in it

把这个放进去

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

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

And inherit from that plus you can add additional extension methods for Add/Remove (AddAt and RemoveAt) to your new derived class (and make it a collection/dictionary) if you are feeling really cool.

如果您感觉很酷,那么您还可以从该继承基础上将添加/删除(AddAt 和 RemoveAt)的其他扩展方法添加到您的新派生类(并使其成为集合/字典)。

A simple implentation example where you would use a normal System.Collections.Generic.KeyValuePair for a base, but instead can use the above code

一个简单的实现示例,您可以使用普通的 System.Collections.Generic.KeyValuePair 作为基础,但可以使用上面的代码

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