在我的 C# 应用程序中,我有一个对象,例如。属性 Color
和 Size
, 并且它是从数据库值中填充的。
然后我有一个设计器应用程序,它允许用户添加 C#/VB 代码(具有特定方法的整个类),这些代码可能会或可能不会使用/更改对象属性的值
当应用程序运行时,将根据设计器应用程序创建的字符串在内存中创建(代码提供者)类,并在运行时调用(反射)特定方法
我如何允许动态代码的方法引用我的对象(非静态的并且从用户特定数据填充)以便如果用户为例如添加代码:
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) });
但无法弄清楚将对象放在哪里以便动态代码可以引用它(将为每个用户生成和执行动态代码,但他们必须引用为他们的 session 创建的对象。
用户的代码应该易于编写并且不必从 for 中获取引用。静态 Dictionary<String,Object>
(通过用户代码引用 AppDic["UserName"].Color
)然后在执行动态代码时再次将其从字典中删除。
用户代码应该是:TheObject.Color
(就像静态方法一样,因为用户代码不需要创建实例,创建动态代码的代码已经填充了属性值。用户必须只能更改/读取);
有人能帮忙吗?
最佳答案
基本上,一旦您在从用户代码创建的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();
的内容,您将无能为力。
此类灵 active 的解决方案是在单独的 AppDomain
中运行用户代码,并将目标对象发送给它,例如通过 Remoting
。
编辑:尝试提出一种不需要将对象作为参数传递的方法。
您可以创建一个包含单个类的程序集,该类将公开对象的静态实例。像这样的东西:
public class TheInstance
{
public static TheObject TheObject = new TheObject();
}
所以现在用户代码将能够做这样的事情:
TheInstance.TheObject.Color = Color.Red;
而且您不必费心发送参数。
为了使用户代码能够访问此程序集中的类,您所要做的就是在使用ICodeCompiler
编译用户代码时将此程序集指定为引用。
这就是你要找的吗?
关于c# - 如何从动态创建的类中获取对对象实例的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4447601/