在我的C#应用程序中,我有一个对象,例如。属性Color
和Size
,以及从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
(就像静态方法一样,因为用户代码不需要创建实例,创建动态代码的代码已经填充了属性值。用户必须只能够改变/阅读);
有人可以帮忙吗?
答案 0 :(得分:1)
基本上,一旦您在用户代码创建的MethodInfo
上找到了所需的Type
,就可以将对象作为参数发送给它。如:
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
编译用户代码时将此程序集指定为引用。
那是你在找什么?