Question

J'essaie de construire une bibliothèque pour simplifier les appels de liaison tardifs en C #, et j'ai des problèmes avec les paramètres de référence. J'ai la méthode suivante pour ajouter un paramètre utilisé dans un appel de méthode

    public IInvoker AddParameter(ref object value)
    {
        //List<object> _parameters = new List<object>();
        _parameters.Add(value);          

        //List<bool> _isRef = new List<bool>();
        _isRef.Add(true);

        return this;
    }

Et cela ne fonctionne pas avec les types de valeur, car ils sont mis en boîte en tant qu'objet, ils ne sont donc pas modifiés. E.g:

int param1 = 2;
object paramObj = param1;
//MulFiveRef method multiplies the integer passed as a reference parameter by 5:
//void MulFiveRef(ref int value) { value *= 5; }
fi.Method("MulFiveRef").AddParameter(ref paramObj);

Cela ne fonctionne pas. L’appel de liaison tardif a abouti et la liste interne qui contient les paramètres (_parameters) est modifiée, mais pas la valeur en dehors de l’appel.

Est-ce que quelqu'un connaît un moyen simple de surmonter cette limitation? La signature AddParameter ne peut pas être modifiée, comme pour les appels de liaison tardifs, vous ne pouvez pas connaître à l'avance le type des paramètres (et dans les deux cas, vous insérez tous les paramètres d'un appel dans un tableau d'objets avant de passer l'appel).

Merci d'avance.

Était-ce utile?

La solution

Si la valeur change dans la méthode , vous devez déclarer une variable temp ( objet ) à transmettre ( ref ) à la méthode et décompressez-la ensuite:

    int i = 3;
    //...
    object obj = i;
    Foo(ref obj);
    i = (int)obj;

Notez que cela ne vous permettra pas de mettre à jour la valeur après l'événement. Quelque chose comme un événement ou un rappel pourrait être un autre moyen de renvoyer les modifications à l'appelant.

Notez également que C # 4.0 a quelques astuces pour vous aider avec ce uniquement dans le contexte des appels COM (où objet de référence est si courant [plus bien sûr dynamique pour la liaison tardive, comme le note Jon]].

Autres conseils

De toute façon, votre méthode ne change pas la valeur - pourquoi la transmettez-vous par référence? Cela peut avoir un sens, mais ce n'est pas vraiment clair pour moi. Notez que l'exemple de code que vous avez fourni ne compilerait de toute façon pas, car les arguments ref doivent être exactement du même type que le paramètre.

(Savez-vous également que C # 4.0 et .NET 4.0 prendront en charge les liaisons tardives? Il est probable que la version intégrée au langage sera plus facile à utiliser qu'une version réservée aux bibliothèques. Etes-vous sûr ça vaut la peine de passer du temps à la bibliothèque en ce moment?)

EDIT: Le code que vous avez fourni ne compilera pas vraiment. Vous ne recevez pas de boxe pour les paramètres ref , précisément parce que les types d'argument et de paramètre doivent être exactement les mêmes. Voici un exemple de code pour le prouver:

public class Test
{
    static void Main()
    {
        int i;
        Foo(ref i); // Won't compile - error CS1502/1503
    }

    static void Foo(ref object x)
    {
    }
}

Si votre code actuel est en cours de compilation , il ne s'agit pas du code que vous avez présenté dans la question. Peut-être avez-vous une autre surcharge pour AddParameter qui accepte ref int ?

Ok, grâce aux corrections de Jon Skeet et au code de Mark Gravell, je viens de créer cette interface:

        //This will be created with a factory
        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());

        int param1 = 2;
        object paramObj = param1;

        invoker.AddParameter(ref paramObj).Invoke("MulFiveRef");

        param1 = (int)invoker.Parameters[0];

N’est pas exactement comme je l’ai imaginé, mais bien plus simple et lisible que mon interface précédente:

        IOperationInvoker invoker = new OperationInvoker(Activator.CreateInstance<MyLateBindingTestType>());
        int refValue = 10;
        object[] args = Args.Build(refValue);

        invoker.Call("MulFiveRef", Args.ByRefIndexs(0), args);

        refValue = (int)args[0];

Merci beaucoup pour votre aide les gens:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top