如何从动态创建的类中引用对象的实例

时间:2021-05-18 21:21:05

In my C# app I have an object with for eg. properties Color and Size, and its populated from db values.

在我的C#应用​​程序中,我有一个对象,例如。属性颜色和大小,以及从db值填充的属性。

Then I have a designer app that allows a user to add C#/VB code (a whole class with specific methods) that may or may not use/change values from the object's properties

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

When the app runs the class will be created(codeprovider) in memory from a string created by the designer app, and a specific method called(reflection) at runtime

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

How do I allow the dynamic code's method to reference my object (non static and populated from user specific data) so that if the user added code for eg:

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

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

I can get it to work if I pass the object to a method in the dynamic class as an input parameter:

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

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

but cant figure out where to put the object so that the dynamic code can reference it (the dynamic code will be generated and executed for each user, but they must reference the object created for their session.

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

The user's code should be easy to write and not have to get reference from a for eg. static Dictionary<String,Object> (referenced via user code AppDic["UserName"].Color) and then remove it again from the dictionary when the dynamic code executed.

用户的代码应该易于编写,而不必从例如。 static Dictionary (通过用户代码AppDic [“UserName”]。颜色引用),然后在执行动态代码时再从字典中删除它。 ,object>

The user code should just have to be : TheObject.Color (like a static method since user code won’t need to create an instance, the code creating the dynamic code already did populated the property values. User must only be able to change/read);

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

Can anyone help ?

有人可以帮忙吗?

1 个解决方案

#1


1  

Basically, once you found the MethodInfo you want on the Type you created from the user's code, there is no problem with just sending it the object as a parameter. As in:

基本上,一旦你在用户代码创建的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); 

If you want the user to only have to writa:

如果您希望用户只需要写入:

theObject.Color;

Then you should wrap the user's code to produce something like that:

然后你应该包装用户的代码来生成类似的东西:

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

theObject.Color = Color.Red;

// BEGIN SUFFIX
    }
}
// END SUFFIX

By the way, there are some serious security consequences to the design that you chose.

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

For example, nothing can prevent the user code from doing things that will cause your application to terminate, become unresponsive, or other stuff. Intentionally or not. For example, if the user enters something like System.Windows.Forms.Application.Exit();, there's nothing you can do.

例如,没有什么可以阻止用户代码执行会导致应用程序终止,无响应或其他内容的操作。有意或无意。例如,如果用户输入类似System.Windows.Forms.Application.Exit();的内容,则无法执行任何操作。

The solution to such volnurabilities would be run the user code in a separate AppDomain, and send to it the target object, for example through Remoting.

这种可编程性的解决方案是在单独的AppDomain中运行用户代码,并向其发送目标对象,例如通过远程处理。

Edit: Trying to suggest a way that would not require passing the object as a parameter.

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

You can create an Assembly with a single class that would expose a static instance of your object. Something like:

您可以使用单个类创建一个程序集,该类将公开对象的静态实例。就像是:

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

So now the user code will be able to do things like:

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

TheInstance.TheObject.Color = Color.Red;

And you will not have to bother with sending the parameter.

而且你不必费心去发送参数。

In order for the user code to be able to access the class in this assembly, all you have to do is specify this assembly as a reference when you use the ICodeCompiler to compile the user code.

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

Is that what you were looking for?

那是你在找什么?

#1


1  

Basically, once you found the MethodInfo you want on the Type you created from the user's code, there is no problem with just sending it the object as a parameter. As in:

基本上,一旦你在用户代码创建的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); 

If you want the user to only have to writa:

如果您希望用户只需要写入:

theObject.Color;

Then you should wrap the user's code to produce something like that:

然后你应该包装用户的代码来生成类似的东西:

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

theObject.Color = Color.Red;

// BEGIN SUFFIX
    }
}
// END SUFFIX

By the way, there are some serious security consequences to the design that you chose.

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

For example, nothing can prevent the user code from doing things that will cause your application to terminate, become unresponsive, or other stuff. Intentionally or not. For example, if the user enters something like System.Windows.Forms.Application.Exit();, there's nothing you can do.

例如,没有什么可以阻止用户代码执行会导致应用程序终止,无响应或其他内容的操作。有意或无意。例如,如果用户输入类似System.Windows.Forms.Application.Exit();的内容,则无法执行任何操作。

The solution to such volnurabilities would be run the user code in a separate AppDomain, and send to it the target object, for example through Remoting.

这种可编程性的解决方案是在单独的AppDomain中运行用户代码,并向其发送目标对象,例如通过远程处理。

Edit: Trying to suggest a way that would not require passing the object as a parameter.

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

You can create an Assembly with a single class that would expose a static instance of your object. Something like:

您可以使用单个类创建一个程序集,该类将公开对象的静态实例。就像是:

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

So now the user code will be able to do things like:

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

TheInstance.TheObject.Color = Color.Red;

And you will not have to bother with sending the parameter.

而且你不必费心去发送参数。

In order for the user code to be able to access the class in this assembly, all you have to do is specify this assembly as a reference when you use the ICodeCompiler to compile the user code.

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

Is that what you were looking for?

那是你在找什么?