7
votes

Créer des délégués de manière dynamique avec des noms de paramètres

hi j'essaie de créer une fonction qui crée de manière dynamique une déléguée avec la même valeur de retour et les mêmes paramètres que la méthodeInfo qu'il reçoit en tant que paramètre et également, ce qui est très important les mêmes noms de paramètres!

Qu'est-ce que je Si de loin, la fonction est créée une fonction qui renvoie une Lambda qui reçoit les mêmes types de paramètres et a la même valeur de retour que la méthodeInfo, mais elle n'a pas les noms de paramètres: P>

    static void Example()
    {
        Person adam = new Person();
        MethodInfo method = typeof(Person).GetMethod("Jump");
        Delegate result = CreateDelegate(adam, method);
        result.DynamicInvoke((uint)4, "Yeahaa");
    }

    private static Delegate CreateDelegate(object instance, MethodInfo method)
    {
        var parametersInfo = method.GetParameters();
        Expression[] expArgs = new Expression[parametersInfo.Length];
        List<ParameterExpression> lstParamExpressions = new List<ParameterExpression>();
        for (int i = 0; i < expArgs.Length; i++)
        {
            expArgs[i] = Expression.Parameter(parametersInfo[i].ParameterType, parametersInfo[i].Name);
            lstParamExpressions.Add((ParameterExpression)expArgs[i]);
        }

        MethodCallExpression callExpression = Expression.Call(Expression.Constant(instance), method, expArgs);
        LambdaExpression lambdaExpression = Expression.Lambda(callExpression, lstParamExpressions);

        return lambdaExpression.Compile();
    }

    private class Person
    {
        public void Jump(uint height, string cheer)
        {
            Console.WriteLine("Person jumped " + height + " "+ cheer);
        }
    }


0 commentaires

3 Réponses :


9
votes

Pour créer de manière dynamique un délégué, vous pouvez utiliser la réflexion. Étant donné que les délégués sont des types spéciaux dans .NET, le code pour les créer n'est pas assez évident. Ce qui suit est basé sur le code réfléchi de méthodes utilisée par expression.lambda () . Là, il est utilisé pour créer des types de délégués personnalisés dans des situations, où il n'y a pas de action ou Func Délégué disponible (plus de 17 paramètres ou paramètres avec ref ou out ). xxx

Si vous vous souciez de performances, vous pouvez créer une cache de quelque sorte, de sorte que vous ne créez pas la même chose. Type de délégué sur et plus.

La seule modification de votre code sera la ligne qui crée lambdaexpression : xxx

mais En fait, vous n'avez pas besoin de traiter avec expression s du tout. Délégué.Créatedélégate () est suffisant : xxx


2 commentaires

Merci je l'ai essayé plus tôt aujourd'hui et ça a fonctionné super !! Je comprends la majeure partie de votre code, mais je ne pouvais vraiment pas comprendre ce que vous faites avec le nom et la nomiqueBase, pourquoi est-il égal au nom de la base de type + le nom du type, quel est le numéro = 2 pour? Quoi qu'il en soit, merci beaucoup j'essayais de le faire travailler pendant des jours


@Chihamadara, c'est juste un moyen de vous assurer que le nom de type est unique, car vous ne pouvez pas avoir deux types avec le même nom dans le même assemblage. Et le numéro 2 est là pour que les noms soient comme personneJump , personjump2 , personjump3 , etc., etc.



0
votes

Le framework Open Source Impromptutrinterface (V5.6.7 Via Nuget) a une DLR Currying / partiel Appliquer la mise en œuvre que je pense fonctionnerait dans ce cas tant que vous n'avez pas besoin de délégué littéral.

Voici la version C # de la créer et d'invoquer: P>

dynamic jump =Impromptu.Curry(adam).Jump();
jump(cheer:"yay", height:(uint)3);


0 commentaires

3
votes

Je viens de tomber sur une bonne façon de résoudre ce problème, cela ressemble à ceci pour les délégués à une méthode statique: xxx pré>

Il utilise cette méthode d'extension: P>

public static IEnumerable<TSource> Append<TSource>(this IEnumerable<TSource> collection, TSource element) {
    if (collection == null) throw new ArgumentNullException("collection");

    foreach (TSource element1 in collection) yield return element1;
    yield return element;
}


0 commentaires