Ce n'est probablement pas possible de le faire, mais je vais demander quand même. Est-il possible de créer une fonction qui reçoit une chaîne puis l'utilise comme un argument latéral droit pour la marche à l'opérateur (=>) utilisé dans Lambda? P>
En fait, ce que je veux faire, c'est de pouvoir redéfinir une méthode spécifique d'une classe spécifique pendant l'exécution. Je veux être en train d'écrire une fonction avec le programme en cours d'exécution et la joignant à un délégué. Est-ce possible? P>
8 Réponses :
Votre question est assez difficile, mais vous pouvez certainement utiliser des arbres d'expression pour créer des délégués de manière dynamique au moment de l'exécution. (Il y a d'autres façons de le faire tels que CodeDom, mais les arbres d'expression sont handtiques si em> ils font tout ce dont vous avez besoin. Il existe toutefois des restrictions significatives à ce que vous pouvez faire, ce que vous pouvez faire ce que vous pouvez faire.) C'est souvent plus facile Pour utiliser une expression de Lambda avec des variables capturées cependant. p> Par exemple, pour créer une fonction qui ajoutera la quantité spécifiée à n'importe quel entier, vous pouvez écrire: p> static Func<int, int> CreateAdder(int amountToAdd)
{
return x => x + amountToAdd;
}
...
var adder = CreateAdder(10);
Console.WriteLine(adder(5)); // Prints 15
Vous avez plusieurs façons de le faire: p>
J'aimerais pouvoir choisir les deux réponses comme la bonne. Les deux me fournissent de très bonnes solutions. Et ici, je pensais que ce serait impossible. Maintenant, le modèle de stratégie n'est pas ce que je cherchais. Pour utiliser la stratégie, je devrais mettre en œuvre les méthodes afin que je puisse les échanger.
Le moyen le plus simple de le faire est probablement DLINQ en tant que TCK suggéré. p>
Le plus rapide (je crois, en 3.5) est de créer un DynamicMethod . C'est aussi la méthode la plus effrayante. Vous construisez essentiellement une méthode utilisant IL, qui a à peu près la même sensation que d'écrire du code dans la langue de la machine. P>
J'avais besoin de le faire pour attacher de manière dynamique des gestionnaires d'événements dans une chose ou une autre (Eh bien, je n'avais pas besoin de le faire, je voulais juste faciliter les événements de test de l'unité). Il semblait un peu décourageant à l'époque parce que je ne connais pas la merde d'IL, mais j'ai compris un moyen simple d'accomplir cela. P>
Ce que vous faites est de créer une méthode qui fait exactement ce que vous voulez. Plus le mieux compact. Je fournirais un exemple si je pouvais comprendre exactement ce que vous essayez de faire. Vous écrivez cette méthode dans une classe dans un projet DLL et la compilez en mode de sortie. Ensuite, vous ouvrez la DLL dans le réflecteur et désassemblez votre méthode. Le réflecteur vous donne la possibilité de quelle langue vous souhaitez démonter pour - sélectionner IL. Vous avez maintenant les appels exacts dont vous avez besoin pour ajouter à votre méthode dynamique. Suivez simplement l'exemple sur MSDN, éteignez l'exemple de l'exemple pour votre code de méthodes réfléchi. p>
Les méthodes dynamiques, une fois construites, invoquent à peu près la même vitesse que les méthodes compilées (ont vu un test dans lequel des méthodes dynamiques pourraient être appelées à environ 20 ms où la réflexion a pris plus de 200 ms). P>
Wow, et ici, je pensais savoir quelque chose à propos de .net. Et je n'en ai jamais entendu parler. J'ai peur de demander comment as-tu déjà réussi à trébucher sur une telle caractéristique.
DynamicMethod est disponible depuis 2,0
Je ne recommande pas cela sur les autres mieux les options em>, mais il y a une méthode 7 TH sup> et c'est à utiliser Par exemple, vous pouvez les utiliser pour créer une classe proxy pour un type et une autre méthode virtuelle sur ce type. p> Pour vous aider à démarrer Voici est un code ... P> AssemblyBuilder Code>, ModuleBuilder Code>,
TypeBuilder Code> et
MethodBuilder Code> Dans le
System.reflection.emit code> Espace de noms pour créer un assemblage dynamique. C'est le même Voodoo similaire que l'utilisation
dynamicmethod code>.
using System;
using System.Reflection;
using System.Reflection.Emit;
var myAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave);
var myModule = myAssembly.DefineDynamicModule("Test.dll");
var myType = myModule.DefineType("ProxyType", TypeAttributes.Public | TypeAttributes.Class,
typeof(TypeToSeverelyModifyInAnUglyWayButItsNecessary));
var myMethod = myType.DefineMethod("MethodNameToOverride",
MethodAttributes.HideBySig | MethodAttributes.Public,
typeof(void),Type.EmptyTypes);
var myIlGenerator = myMethod.GetILGenerator();
myIlGenerator.Emit(OpCodes.Ret);
var type = myType.CreateType();
Il semble prendre à propos du même nombre de code de code pour être fait que simplement utiliser DynamicMethod. Y a-t-il une raison de l'utiliser sur DynamicMethod? Si la volonté est correcte, DynamicMethods est presque aussi rapide que le code compilé (même si 20ms est une éternité en temps d'ordinateur).
Les seuls «avantages» de l'utilisation de ces méthodes dynamiques sont que vous pouvez enregistrer l'ensemble généré et vous pouvez hériter des types et des méthodes virtuelles / propriétés. J'espère que cela t'aides. Encore une fois, je ne recommande pas cela pour la consommation générale, soulignant simplement une autre option. Lorsque vous avez dit que vous devez "redéfinir" une méthode, en fonction de ce que vous voulez dire, cela pourrait être une meilleure option puisque vous pouvez créer un type et une autre méthode de base ...
Si vous déclarez la méthode de Virtual, vous pourrez peut-être utiliser Castle's dynamicproxy a > Pour substituer une mise en œuvre générée dynamiquement (avec l'une des méthodes de la réponse) à l'exécution: p>
Castle DynamicProxy est une bibliothèque pour générer des proxies de la Lightweight .NET à la volée au moment de l'exécution. Les objets proxy permettent des appels aux membres d'un objet à intercepter sans modifier le code de la classe. Les classes et les interfaces peuvent être proxoées, mais seuls les membres virtuels peuvent être interceptés. p>
blockQuote>
J'ai tendance à éviter d'utiliser des bibliothèques tierces dans mon code. C'est pour éviter le problème du verrouillage du fournisseur. J'ai eu de graves problèmes avec cela auparavant quand j'ai codé à Delphes. Dans l'exemple, je viens de passer à l'aide de SQLite - même si je l'aime beaucoup - SQLSERVER CE Juste pour rester pleinement dans le cadre.
Il a l'avantage d'être open source, de sorte que vous n'êtes pas aussi "verrouillé" comme vous le seriez avec une solution commerciale. Parfois, il vous suffit de peser les avantages de la réinventer de la roue vs de faire effectuer des choses.
Le deuxième paragraphe de votre question suggère que vraiment ce que vous pourriez être après est directement ioc (Inversion de contrôle) p>
Au lieu de déclarer une instance de votre classe, vous déclarez une instance d'une interface et basée sur la condition que vous choisissez, vous utilisez la classe principale particulière avec la méthode correcte. J'espère que cela a du sens. P>
Non, ce n'est pas le cas. Ce que je veux, c'est de pouvoir modifier une méthode d'une classe pendant l'exécution à quelque chose que je vais taper au moment de l'exécution. À peu près similaire à un eval, sauf que je ne veux pas simplement que cela soit évalué et mourir. Je veux qu'il reste attaché à un délégué jusqu'à ce que je dois le changer à nouveau.
AH, OK, votre application pourrait donc avoir une entrée de texte qui vous permet de saisir du code pour modifier l'action d'une fonction?
Vous devez vérifier si votre problème peut être résolu avec un simple polymorphisme d'abord. Sauf si vous définissez une interopérabilité abstraite à une autre langue ou à éditer le compilateur, essayez de modifier une méthode à l'exécution est probablement la solution incorrecte au problème. P>
Je suis d'accord à 100%, cela devrait être le premier choix.
Utilisez .NET CORE 3.1, vous pouvez créer une méthode dynamique avec la langue de l'IL (mono est la même):
using System.Linq.Expressions; using System.Reflection.Emit; class Program { static void Main() { DynamicMethod hellomethod = new DynamicMethod("WriteLine", typeof(void), new[] { typeof(string) }, typeof(Program).Module); ILGenerator il = hellomethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) })); il.Emit(OpCodes.Ret); Action<string> hello4 = (Action<string>)hellomethod.CreateDelegate(typeof(Action<string>)); hello4("Hello World!"); } }
Pourriez-vous nous dire quel est votre cas d'utilisation réelle? Peut-être qu'il y a une autre façon de répondre à vos besoins.
Si je lis cela correctement, vous voulez évaluer () une chaîne? en.wikipedia.org/wiki/eval