首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >.NET:从动态程序集中访问非公共成员

.NET:从动态程序集中访问非公共成员
EN

Stack Overflow用户
提问于 2011-04-23 03:00:33
回答 2查看 3.1K关注 0票数 19

我正在开发一个允许用户输入任意表达式的库。然后,我的库将这些表达式作为较大表达式的一部分编译为委托。现在,由于未知的原因,使用Compile编译表达式有时/通常会导致代码比不编译表达式时要慢得多。我以前使用过asked a question about this,一个解决办法是不使用Compile,而是使用CompileToMethod,并在新的动态程序集中的新类型上创建一个static方法。这是可行的,而且代码速度很快。

但用户可以输入任意表达式,如果用户调用非公共函数或访问表达式中的非公共字段,则在调用委托时会抛出System.MethodAccessException (在非公共方法的情况下)。

我可以在这里做的是创建一个新的ExpressionVisitor来检查表达式是否访问任何非公共成员,并在这些情况下使用较慢的Compile,但我更希望动态程序集以某种方式获得访问非公共成员的权限。或者看看我能不能对Compile变慢(有时)做些什么。

重现此问题的完整代码:

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;

namespace DynamicAssembly
{
  public class Program
  {
    private static int GetValue()
    {
      return 1;
    }

    public static int GetValuePublic()
    {
      return 1;
    }

    public static int Foo;

    static void Main(string[] args)
    {
      Expression<Func<int>> expression = () => 10 + GetValue();

      Foo = expression.Compile()();

      Console.WriteLine("This works, value: " + Foo);

      Expression<Func<int>> expressionPublic = () => 10 + GetValuePublic();

      var compiledDynamicAssemblyPublic = (Func<int>)CompileExpression(expressionPublic);

      Foo = compiledDynamicAssemblyPublic();

      Console.WriteLine("This works too, value: " + Foo);

      var compiledDynamicAssemblyNonPublic = (Func<int>)CompileExpression(expression);

      Console.WriteLine("This crashes");

      Foo = compiledDynamicAssemblyNonPublic();
    }

    static Delegate CompileExpression(LambdaExpression expression)
    {
      var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
        new AssemblyName("MyAssembly"+ Guid.NewGuid().ToString("N")), 
        AssemblyBuilderAccess.Run);

      var moduleBuilder = assemblyBuilder.DefineDynamicModule("Module");

      var typeBuilder = moduleBuilder.DefineType("MyType", TypeAttributes.Public);

      var methodBuilder = typeBuilder.DefineMethod("MyMethod", 
        MethodAttributes.Public | MethodAttributes.Static);

      expression.CompileToMethod(methodBuilder);

      var resultingType = typeBuilder.CreateType();

      var function = Delegate.CreateDelegate(expression.Type, 
        resultingType.GetMethod("MyMethod"));

      return function;
    }
  }
}
EN

回答 2

Stack Overflow用户

发布于 2011-04-23 03:45:27

我曾经在使用DynamicMethod从生成的IL代码访问类的私有元素时遇到过一个问题。

结果是,类DynamicMethod的构造函数有一个重载,它将类类型接收到私有访问将被允许的地方:

http://msdn.microsoft.com/en-us/library/exczf7b9.aspx

此链接包含如何访问私有数据的示例...我知道这与表达式树无关,但它可能会给你一些关于如何做的线索。

在编译表达式树时可能会有一些类似的事情...或者您可以将该表达式树创建为DynamicMethod。

票数 1
EN

Stack Overflow用户

发布于 2011-05-02 00:16:41

如果非动态程序集是由您构建的,那么您实际上可以为动态程序集包含一个InternalsVisibleTo (甚至可以使用强名称)。这将允许使用内部成员,这在您的情况下可能就足够了?

为了得到一个概念,这里有一个示例,它展示了如何使Moq的动态装配能够使用来自另一个装配的内部内容:http://blog.ashmind.com/2008/05/09/mocking-internal-interfaces-with-moq/

如果这种方法还不够充分,我会采用Rick和Miguel的组合建议:为每个对非公共成员的调用创建“代理”DynamicMethods,并更改表达式树,以便使用它们而不是原始调用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5758999

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档