在动态程序集中扩展私有类

时间:2012-10-27 14:00:55

标签: .net reflection.emit

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

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

框架(Managed 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类型拒绝访问”。

第一眼看,有人可能会说:嗯,你正在尝试将私人类扩展到其程序集之外。我的论点是:是的,我确实从一个私有类派生,但是在动态程序集中,通过标记为“RunAndCollect”的方式,因此它永远不会被保存,因此,类型不能在别处使用,但在当前的实例中AppDomain。从理论上讲,我并没有违反私人原则,因为新类型仍然是私有的,并且坦率地说,在更为严格的意义上说:对于AppDomain的当前实例是私有的。

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

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

PS:是的,我可以用一种实用的方式说,试图利用框架的每个对象都需要公开。不幸的是,我认为一个框架作为一种工具,不一定会限制基础语言的可能性,而不应该隐含知识。

1 个答案:

答案 0 :(得分:1)

由于我被建议这样做,我最终将我的发现作为答案。

为托管动态程序集的AppDomain实例设置RefectionPermissionFlag :: MemberAccess并为程序集提供足够的证据以使其完全受信任运行,动态程序集应该能够在其中调用/设置甚至私有成员/类型可信组件。但它没有,MicroSoft明确说明了这一点 - RefectionPermissionFlag :: MemberAccess不适用于动态装配。

有效的是:[assembly:InternalsVisibleTo(“”)]在程序集的AssemblyInfo.cs中设置,其私有类型/方法应该在动态程序集中访问。痛苦的是,你不能为来自第三方的集会做到这一点。