【问题标题】:How do I get reference to an instance of an object from a dynamic created class如何从动态创建的类中获取对对象实例的引用
【发布时间】:2011-05-25 18:12:53
【问题描述】:

在我的 C# 应用程序中,我有一个对象,例如。属性 ColorSize,并从 db 值填充。

然后我有一个设计器应用程序,它允许用户添加 C#/VB 代码(具有特定方法的整个类),这些代码可能会或可能不会使用/更改对象属性中的值

当应用程序运行时,将根据设计器应用程序创建的字符串在内存中创建(codeprovider)类,并在运行时调用特定方法(反射)

我如何允许动态代码的方法引用我的对象(非静态并从用户特定数据填充),以便如果用户添加代码,例如:

if(TheObject.Color == "Blue")
    TheObject.Width="150";

如果我将对象作为输入参数传递给动态类中的方法,我可以让它工作:

....
ocResults = oCodeProvider,CompileAssemblyFromSource(oCParams, userCode);
oAssy = oCResults.CompiledAssembly;
oExecInstance = oAssy.CreateInstance("userClass");
oType = oExecInstance.GetType();
oType.GetMethod("OnLoad", new Type[] { typeof(myObj) });

但无法确定将对象放置在何处以便动态代码可以引用它(动态代码将为每个用户生成并执行,但他们必须引用为其会话创建的对象。

用户的代码应该易于编写,并且不必从例如获取参考。静态Dictionary<String,Object>(通过用户代码AppDic["UserName"].Color引用),然后在执行动态代码时再次将其从字典中删除。

用户代码应该是:TheObject.Color(就像一个静态方法,因为用户代码不需要创建实例,创建动态代码的代码已经填充了属性值。用户必须能够改变/阅读);

谁能帮忙?

【问题讨论】:

  • 请正确格式化代码。另外,你问的是什么语言?
  • TheObject该死的!我有这个名字的课。

标签: c# .net reflection dynamic


【解决方案1】:

基本上,一旦您在从用户代码创建的Type 上找到了您想要的MethodInfo,只需将对象作为参数发送就没有问题。如:

object userType = ... // compile user's code, load user's type from compiled assembly
MethodInfo myMethod = ... // find the wanted method on the user's type

// assuming the user code is in a static method to avoid having to create instances.
myMethod.Invoke(null, targetObj); 

如果你希望用户只需要写:

theObject.Color;

那么你应该包装用户的代码来产生类似的东西:

// BEGIN PREFIX
public static class UserType
{
    public static UserMethod(TheObject theObject);
    {
// END PREFIX, user code follows

theObject.Color = Color.Red;

// BEGIN SUFFIX
    }
}
// END SUFFIX

顺便说一句,您选择的设计有一些严重的安全后果。

例如,没有什么可以阻止用户代码执行会导致您的应用程序终止、无响应或其他事情的事情。有意无意。例如,如果用户输入System.Windows.Forms.Application.Exit(); 之类的内容,则您无能为力。

解决此类漏洞的方法是在单独的AppDomain 中运行用户代码,并将目标对象发送给它,例如通过Remoting

编辑:尝试提出一种不需要将对象作为参数传递的方法。

您可以使用单个类创建一个程序集,该类会公开对象的静态实例。比如:

public class TheInstance
{
    public static TheObject TheObject = new TheObject();
}

所以现在用户代码将能够执行以下操作:

TheInstance.TheObject.Color = Color.Red;

而且您不必费心发送参数。

为了使用户代码能够访问该程序集中的类,您只需在使用ICodeCompiler 编译用户代码时将该程序集指定为引用。

这就是你要找的吗?

【讨论】:

  • 不太担心用户代码会破坏应用程序。所有的编辑都将被记录下来,因为这将被用作一个商业应用程序,“破坏”系统的员工将被处理:) 我正在使用当前的输入参数方法 oType.GetMethod("OnLoad", new Type[] { typeof(myObj) });但只是认为必须有一种方法可以从其他地方公开对象以在您发布的用户代码中获得相同的结果:theObject.Color = Color.Red;
  • 有点,但这就是我最初发布问题的原因......如果我的系统被 5000 个并发用户使用会发生什么?他们不会覆盖彼此的 TheInstance.TheObject 导致用户代码失败吗?
猜你喜欢
  • 1970-01-01
  • 2013-10-20
  • 2014-01-26
  • 1970-01-01
  • 2021-09-17
  • 1970-01-01
  • 2020-06-18
相关资源
最近更新 更多