2010-12-15 3 views
3

Dans mon application C# j'ai un objet avec par exemple. propriétés Color et Size, et son peuplé à partir de valeurs db.Comment obtenir une référence à une instance d'un objet à partir d'une classe créée dynamique

J'ai une application concepteur qui permet à un utilisateur d'ajouter C#/code VB (une classe entière avec des méthodes spécifiques) qui peuvent ou ne peuvent pas utiliser/modifier les valeurs de propriétés de l'objet

Lorsque l'application exécute la classe sera créée (codeprovider) en mémoire à partir d'une chaîne créée par l'application designer, et une méthode spécifique appelée (réflexion) à l'exécution

Comment autoriser la méthode du code dynamique à référencer mon objet (non statique et rempli à partir de données spécifiques de l'utilisateur) de sorte que si l'utilisateur a ajouté le code pour, par exemple:

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

Je peux l'obtenir pour travailler si je passe l'objet à une méthode dans la classe dynamique en tant que paramètre d'entrée:

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

mais ne peux pas savoir où mettre l'objet afin que le code dynamique peut référencer (le code dynamique sera généré et exécuté pour chaque utilisateur, mais il doit référencer l'objet créé pour sa session.

Le code de l'utilisateur devrait être facile à écrire et ne pas avoir à obtenir une référence d'un pour par exemple. Dictionary<String,Object> statique (référencé via le code utilisateur AppDic["UserName"].Color), puis supprimez-le à nouveau du dictionnaire lors de l'exécution du code dynamique.

Le code utilisateur doit simplement être: TheObject.Color (comme une méthode statique puisque le code utilisateur n'aura pas besoin de créer une instance, le code créant le code dynamique a déjà rempli les valeurs de la propriété. changer/lire);

Quelqu'un peut-il aider?

+3

Veuillez mettre en forme le code correctement. Aussi, quelle langue demandez-vous? – Robert

+0

Mise à jour de la question – DeWet

+1

'TheObject' damn! J'ai classe avec ce nom. – Andrey

Répondre

1

Fondamentalement, une fois que vous avez trouvé le MethodInfo que vous voulez sur le Type que vous avez créé à partir du code de l'utilisateur, il n'y a aucun problème à simplement lui envoyer l'objet en tant que paramètre. Comme dans:

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); 

Si vous voulez que l'utilisateur ait seulement à writa:

theObject.Color; 

vous devez envelopper le code de l'utilisateur pour produire quelque chose comme ça:

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

theObject.Color = Color.Red; 

// BEGIN SUFFIX 
    } 
} 
// END SUFFIX 

Par Bien sûr, il y a de sérieuses conséquences sur la sécurité de la conception que vous avez choisie. Par exemple, rien ne peut empêcher le code utilisateur de faire des choses qui provoqueront l'arrêt de votre application, ne répondront plus, ou d'autres choses. Intentionnellement ou non. Par exemple, si l'utilisateur entre quelque chose comme System.Windows.Forms.Application.Exit();, il n'y a rien que vous puissiez faire.

La solution à ces volnurabilités serait exécuter le code utilisateur dans un AppDomain séparé, et lui envoyer l'objet cible, par exemple par Remoting.

Editer: Essayez de suggérer une méthode qui ne nécessite pas le passage de l'objet en tant que paramètre.

Vous pouvez créer un assemblage avec une classe unique qui exposerait une instance statique de votre objet. Quelque chose comme:

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

Alors maintenant, le code utilisateur sera en mesure de faire des choses comme:

TheInstance.TheObject.Color = Color.Red; 

Et vous ne serez pas à se soucier d'envoyer le paramètre.

Pour que le code utilisateur puisse accéder à la classe dans cet assembly, tout ce que vous avez à faire est de spécifier cet assembly comme référence lorsque vous utilisez le ICodeCompiler pour compiler le code utilisateur.

Est-ce ce que vous cherchiez?

+0

Pas trop concerné par le code d'utilisateur brisant l'application. Toutes les modifications seront enregistrées et puisque cela sera utilisé comme une application d'entreprise, l'employé qui a "cassé" le système sera traité :) J'utilise la méthode des paramètres d'entrée actuellement oType.GetMethod ("OnLoad", nouveau type [] {typeof (myObj)}); mais juste pensé qu'il doit y avoir un moyen d'exposer l'objet d'ailleurs pour obtenir le même résultat dans le code utilisateur que vous avez posté: theObject.Color = Color.Red; – DeWet

+0

Kinda, mais c'est pourquoi j'ai d'abord posté la question ....... ce qui se passera si mon système est utilisé par environ 5000 utilisateurs simultanés? Ne vont-ils pas écraser TheInstance.TheObject de l'autre provoquant l'échec du code d'utilisateur? – DeWet

Questions connexes