Ceci est similaire à quelques autres threads que j'ai trouvés, mais je n'ai pas trouvé la réponse dont j'ai besoin. J'apprécierais une réponse directe, même si c'est «Non, vous ne pouvez pas faire cela».
Y a-t-il un moyen d'utiliser un bloc de code si une classe / type existe et une autre si elle ne le fait pas. Le résultat serait identique à l'utilisation de directives de préprocesseur, mais sans la nécessité de #define et de commenter manuellement ou de commenter quelque chose dans un fichier. P>
Ceci peut être un cas particulier. Je ne suis pas sûr. Je travaille dans un environnement où des ensembles de fichiers peuvent être installés ou non, avant que rien ne soit compilé. Donc, quelqu'un pouvait acheter un plugin qui obtient "installé" (fichiers ajoutés au projet) qui rend les classes / types disponibles pour une utilisation (comme prolonger une API). J'ai besoin de fournir une solution de contournement si quelqu'un n'a pas l'un de nos autres packages de plugin. J'espère que cela à du sens. P>
Il ne serait tout simplement pas convivial de demander à quelqu'un d'ouvrir l'un de nos fichiers, s'ils disposent d'un autre plug-in, de la directive de préprocesseur, à moins que nous ne l'aient à. p>
par exemple Je sais que cela ne fonctionne pas car il ne teste que booléen si #define est utilisé #define, mais il illustre ce que j'essaie de faire ... p> Je ne vois pas comment reflet serait capable de faire cela, mais je suis nouveau à c #, alors des exemples utilisant la relexion, si cela est possible, serait génial. P> P>
3 Réponses :
au lieu d'utiliser des déclarations pré-compilatrice (que je ne sais pas si elles fonctionnaient de toute façon si le client n'avait pas à recompiler après l'installation de votre plug-in), je vous suggérerais d'interroger l'assemblage et d'essayer d'instancier un instance de la classe par chaîne comme on le voit ici:
C # - Correction de la méthode de chargement, recherchez la méthode de la classe et de l'exécution de l'appel () p> Si le type n'est pas NULL, utilisez-le pour créer une instance du type souhaité. P> var obj = Activator.CreateInstance(type);
Cela semble très prometteur. J'ai trouvé que je peux obtenir l'assemblée actuelle à l'aide de GetExecutingAmbly (non testée, il existe d'autres options). Le problème est, même si je reçois le type de variable, Intelluesnse ne peut pas reconnaître les membres parce que le type est System.type et je ne peux pas déclarer le type parce que je dois le vérifier d'abord ... du poulet de l'œuf. Je pense que la seule voie à suivre serait d'utiliser également la réflexion pour appeler la méthode dont j'ai besoin, mais il s'agit d'une zone sensible à la performance. Je vais tester avec Singleton et voir comment ça se passe, puis venez et éditer cela.
@Rafe, je pense que je suis un peu confus? Vous appelez un type que vous vous attendez à être là-bas s'ils ont chargé un assemblage spécifique de branchez-vous? Si la référence de l'assemblage n'est pas nulle et que le type n'est pas null, vous pouvez supposer qu'ils ont chargé cette assemblée et peuvent créer une instance via l'activateur qui fait ce dont vous avez besoin ... J'ai modifié ma réponse pour montrer le Appel d'activateur ...
J'ai marqué cela comme la réponse parce que c'est le meilleur qui puisse être fourni sans devenir situationnel. Malheureusement, je ne vais pas descendre cette route pour fournir ma propre solution car le coût d'effort de création de cela ne vaut pas la peine d'être bénéfique. Pour nous, ce serait bien d'avoir mais n'est pas critique. Il convient toutefois de préciser le simple "faire quelque chose" devrait être remplacé par "lots plus de travail de réflexion va ici". Même si vous allez un niveau profond à une méthode statique est une autre étape. Aller plus loin dans les instances est un peu plus de code en fonction de ce dont vous avez besoin.
À Rikon (mon symbole de 'à' est en train de devenir dépouillé!): Oui, en quelque sorte ... En fait, dans mon cas très spécifique, j'essaie de gérer une méthode stockée dans un dictionnaire statique, alors mytype.dict [" Nom "]. Themethod (3args). Si ce n'est pas là, je fais quelque chose d'autre. L'accès statique devrait être un peu moins de code, mais vous obtiendrez le même problème avec l'activateur, lequel vous devez utiliser la réflexion jusqu'à présent. Dans votre exemple, si OBJ avait une méthode 'myMethod', vous ne seriez pas en mesure de taper obj.mymeThod () puisque Obj est de type System.Type, pas le type réel tel que défini dans le code d'origine.
Vous pouvez définir des interfaces pour vos types / services que votre code de code fourni par votre évaluation, mais ne fournit pas. Ensuite, vous pouvez utiliser un cadre de plug-in comme MEF , qui est intégré à la structure .NET (V4.0). p>
mef fera la réflexion et l'énumération de l'assemblage pour vous. Il vous suffit de définir des points d'extension simples dans votre code. P>
Voici une documentation de base pour le MEF. Il peut être spécifique à la version de CodePlex du code (pas sûr), mais elle ne devrait pas être trop âgée et devrait vous donner une bonne idée de la façon dont cela fonctionne: p>
Je ne sais pas comment le MEF fonctionnerait ici. Nous n'avons pas de contrôle sur l'application, seul un code de code quelqu'un peut utiliser dans leur propre code, qui est tout ce qui est utilisé dans l'application (il s'agit d'un moteur de jeu si cela compte) ... la distribution dans ce cas n'a pas de réelle installation. Pour simplifier, vous obtiendriez simplement des fichiers à ajouter à un projet comme si vous aviez écrit le code. Si le fichier est là, le type est là. Nous déclarons une licence, mais c'est de nature assez simple. Vous pouvez l'utiliser si vous ne redistribuez pas, etc. Nous ne nous inquiétons même pas des peuples déshonorantes de la communauté.
@RAFE: Vous avez dit "fichiers" dans votre op, que j'ai pris pour signifier des assemblages. Presque tous les projets non open-source .NET sont distribués en tant qu'assemblages, vous avez donc certainement un cas particulier ici. Ça va bien et bien, mais c'est pourquoi je n'ai pas dit plus que simplement "utiliser Mef" :) Si vous distribuez les plugins i> en tant qu'assemblages (la réponse acceptée ne fonctionnera que si vous êtes), puis Vous pouvez utiliser Mef. Vous distribueriez un assemblage contenant uniquement les interfaces du plug-in, utilisez ces interfaces pour créer des points d'extension dans vos fichiers source et implémenter ces interfaces avec vos plugins.
@Rafe: C'est à vous de décider si le MEF fournit suffisamment d'avantages pour le justifier. Vous allez devoir définir un contrat entre le plugin et le code de toute façon, et il sera plus facile d'écrire du code par rapport à une interface que celle-ci contre objet code>. Cela donnera également bon perf (juste des appels de fonction virtuelle une fois le type chargé). D'autres solutions impliquent que vous appelez avec une utilisation prolongée des réflexions (chaque appel, accès à la propriété, etc.), en utilisant
dynamique code> pour faire de même, ou éventuellement compiler des méthodes dynamiques (voir:
@Rafe: En outre, msdn.microsoft.com/fr -Us / Bibliothèque / ...
Merci beaucoup pour toutes ces informations. Je ne peux tout simplement pas justifier tout le temps qu'il faudrait pour apprendre cette affaire pour une fonctionnalité «agréable d'avoir» à l'aide de code, je n'ai probablement jamais besoin. Je ne vois pas pourquoi C # n'a pas ceci comme une directive de préprocesseur. Cela rendrait tout aussi simple. Je préfère faire une vidéo de formation à l'ONU-Commentaire que #define. Si Intelluesense peut comprendre si un type existe et fournit des commentaires, en temps réel, cela ne devrait pas être un problème pour un compilateur! Espérons que tout aident le prochain gars.
@RAFE: Je crois qu'ils ont essayé de limiter le prétraiteur en général car une pente glissante est une pente glissante. Vous pouvez définir un #idif hasplugin code> Définition du préprocesseur à la place.
Vous souciez-vous vraiment de ce qui est présent à la compilée, ou à l'heure d'exécution? Vous pourrez peut-être utiliser un motif d'usine pour encapsuler la logique pour laquelle la classe pour instancier en supposant que le polymorphisme soit possible (ils partagent tous les deux une interface ou une classe de base). P>
Oui, compilez l'heure, si j'utilise la terminologie à droite. Il faut travailler avec IntelliSense, par exemple.