3

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

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

框架(托管 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
    }
  }
}

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

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

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

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

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

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

4

1 回答 1

1

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

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

有效的是:[assembly:InternalsVisibleTo("")] 在程序集的 AssemblyInfo.cs 中设置,其私有类型/方法应从动态程序集中访问。苦涩的是,你不能对来自第三方的程序集这样做。

于 2012-11-21T15:13:49.090 回答