.net - 在动态程序集中扩展私有(private)类

标签 .net reflection.emit

我正在开发一个框架,它允许为任意对象定义我所谓的表示——您可以将此类表示理解为对象的一个​​方面。例如:某个应用程序的对象应该由渲染引擎可视化。您无需扩展对象本身的类型,而是提供由服务(呈现引擎)提供的表示,该服务从对象中读取数据(并且可以在其他表示的上下文中写入数据)。

框架期望一些接口(interface)由应用程序类型实现,以便使用功能。但是,如果应用程序不提供这些接口(interface)的实现,框架会自动子类化该类型并为这些接口(interface)添加默认实现,如下所示:

框架(托管 C++):

namespace Spoc::Claire
{
  public interface class IEntity
  {
    void DoSomething() ;
  } ;
} 

这是一个简单的应用程序 (C#):

namespace Spoc.Samples
{
  class Hello
  {
    public Hello()
    {
      Console.WriteLine("Hello world") ;
    }

    static void Main(string[] args)
    {
      Entity.New(typeof(Hello)) ; // creates the "Hello" object within the context of the framework
    }
  }
}

框架在动态程序集中通过反射创建的内容是:

namespace Internal
{
  class Hello : Spoc.Samples.Hello, Spoc.Claire.IEntity
  {
    public void Hello()
    {
      // call the base class constructor
    }
    public void DoSomething()
    {
      // default implementation for IEntity
    }
  }
}

该对象返回给应用程序,由于继承自给定类型,因此可以不受任何限制地使用。

那么问题是什么?如果应用程序将它们的类型定义为“公共(public)”,则一切运行良好。如果不是,就像在上面描述的示例中一样,我将从 TypeBuilder::CreateType() 方法中得到一个 TypeLoadException,提示“对类型 Spoc.Samples.Hello 的访问被拒绝”。

乍一看,您可能会说:好吧,您正试图在其程序集之外扩展一个私有(private)类。我的论点是:是的,我确实派生自一个私有(private)类,但在一个动态程序集中,顺便说一句,它被标记为“RunAndCollect”,因此它永远无法保存,因此,类型不能在其他地方使用,但在当前实例中应用域。从理论上讲,我没有违反私有(private)原则,因为新类型仍然是私有(private)的,坦率地说,在更严格的意义上:对 AppDomain 的当前实例私有(private)。

我玩过 friend 装配范例,但除了友谊确实违反严格的面向对象设计这一事实外,我很难将我的动态装配指定为 friend 。我还找到了 ReflectionPermission 属性,但也停止了该属性。

有没有人可以给我一些建议?

PS:是的,我可以用一种务实的方式说,每个试图利用该框架的对象都需要公开。不幸的是,我将框架视为一种工具,它不一定会限制底层语言的可能性,也不应该包含隐含的知识。

最佳答案

既然有人建议我这样做,我最终将我的发现作为答案。

通过为托管动态程序集的 AppDomain 实例设置 RefectionPermissionFlag::MemberAccess 并为程序集提供足够的证据以使其完全受信任地运行,动态程序集应该能够调用/设置甚至私有(private)成员/类型受信任的程序集。然而,事实并非如此,并且 MicroSoft 明确指出 - RefectionPermissionFlag::MemberAccess 不适用于动态程序集。

有效的是:[assembly:InternalsVisibleTo("")] 在程序集的 AssemblyInfo.cs 中设置,应从动态程序集中访问其私有(private)类型/方法。痛苦的是,您不能对来自第三方的程序集执行此操作。

关于.net - 在动态程序集中扩展私有(private)类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13100835/

相关文章:

c# - 在 C# .NET 框架中获取蓝牙设备列表

c# - IL 短格式指令不短?

c# - 使用 propertyBuilder 在运行时向现有对象添加属性

.net - Viewstate 隐藏字段如此之大,以至于一切都崩溃了

c# - 为什么 ForEach 方法只适用于列表

.net - 在 .NET 中获取图像元数据,而不考虑元数据格式

c# - Reflection.Emit 如何分配不兼容的类型?

c# - 自定义属性未正确添加到 Reflection.Emit 程序集中

c# - 是否可以对在 C# 中运行时创建的类型使用隐式强制转换?

c# - 在序列中获取 "next"元素的最简单方法?