Question

ci-dessous est un exemple de code et la question, s'il vous plaît noter que je ne peux pas utiliser C # 4.0 et le mot-clé dynamique.

static class TestClass
{
    static void Main(string[] args)
    {
        Object o = "Previous value";
        Test(ref o);
        Trace.WriteLine(o);
    }

    static public void Test<T>(ref T obj)
    {
        //  The goal is to somehow invoke Test2 with the real type of obj, i.e the type in obj.GetType() 

        //  1st try:
        Test2(ref obj); // This doesn't work because the type in Test2 will be the same as T here.

        //  2nd try:
        MethodInfo mi = typeof(TestClass).GetMethod("Test2");
        mi = mi.MakeGenericMethod(new Type[] { obj.GetType() });
        mi.Invoke(null, new Object[] { obj }); // obj is no longer by reference so we need to store the object array and copy back the result after the call

        //  3rd try, successful implementation by the smartest mind of stack overflow :)
    }

    static public void Test2<T>(ref T s)
    {
        if (typeof(T) == typeof(String))
        {
            s = (T)(Object)"Hello world!";
        }
    }
}

J'ai essayé aussi quelques autres méthodes utilisant Delegate.CreateDelegate mais sans chance. Est-ce possible?

Edit:. Je ne suis pas peur d'utiliser une méthode dynamique (et assembleur MSIL), mais mes connaissances dans ce domaine est très limitée

Edit2: Voici un exemple qui est plus proche de ce que je vraiment essayer de faire:

public static class TypeHandler<T>
{
    public delegate void ProcessDelegate(ref T value);

    public static readonly ProcessDelegate Process = Init();

    private static ProcessDelegate Init()
    {
        //  Do lot's of magic stuff and returns a suitable delegate depending on the type
        return null;
    }
}


static class TestClass
{
    static public void Main(string[] args)
    {
        Object o = "Previous value";
        Test(ref o);
        Trace.WriteLine(o);
    }

    static public void Test<T>(ref T obj)
    {
        if (obj is T)
        {
        //  Optimized, common case
            TypeHandler<T>.Process(ref obj);
            return;
        }
        Type t = obj.GetType();
        //  How to call the delegate found in TypeHandler<t>.Process ? (I can get delegate but I can't call it).


    }

}
Était-ce utile?

La solution

Mise à jour 3 : OK, puisque vous êtes très bien avec une solution laide, vous voudrez peut-être vérifier les sans-papiers et __refvalue __makeref mots-clés .


Il semble que votre problème est que vous voulez être en mesure de préciser le type d'un paramètre de ref object être converti ou changé .

Le problème avec cela est que vous ne pouvez pas attribuer arbitrairement une variable de tout type T à un string, par exemple. Donc, vous auriez besoin de passer dans un ref object ou ref string pour que le travail tout .

Il me semble que oberfreak clouées ce que vous essayez d'atteindre (je l'origine ne vous a pas remarqué avait initialisé o comme string et donc voulu clairement son réelle le type d'influencer le comportement de la fonction Test2). Sa réponse a la bonne approche pour vous.

Mise à jour : vous mentionnez dans un commentaire que ce que vous essayez de faire est d'avoir un comportement dynamique qui pourrait être réalisé en utilisant un dictionnaire. Je devine que ressemble à quelque chose comme ça?

Mise à jour 2 :. Mise à jour ce exemple à base de votre par exemple mis à jour

public static class TypeHandler // note: get rid of generic T parameter
{
    delegate void ProcessDelegate(ref object obj); // again, not generic

    static Dictionary<Type, ProcessDelegate> processors = new Dictionary<Type, ProcessDelegate>()
    {
        { typeof(string), (ref object obj) => { obj = "Hello, world!"; } }
        // etc.
    };

    public static void Process(ref object obj)
    {
        processors[obj.GetType()].Invoke(ref obj);
    }
}

que devrait fonctionner. Mais vous ne pouvez pas vraiment réaliser la même chose avec les médicaments génériques parce qu'il n'y a aucun moyen de le faire (comme vous le savez):

//          not allowed
//               |
//          -----------
//         |           |
TypeHandler<o.GetType()>.Process(ref o);

Si étaient , alors vous seriez tous ensemble. Mais la seule façon possible, vous pouvez le faire est en utilisant la réflexion, ce qui est laid et cher pour quelque chose comme ça et serait clairement vaincre votre intention de garder ce simple et d'assurer une bonne performance.

Autres conseils

Votre commentaire semble que vous comprenez déjà comment le faire:

MethodInfo mi = typeof(TestClass).GetMethod("Test2");
mi = mi.MakeGenericMethod(new Type[] { obj.GetType() });
object[] args = new object[] { obj };
mi.Invoke(null, args);
obj = (T) args[0];

C'est vraiment juste transformer votre commentaire en code. Est-ce que d'une certaine manière pas ce que vous voulez?

Les principales questions, à mon avis, que voulez-vous faire?

Si vous voulez juste assigner une chaîne à un objet de référence, vous pouvez essayer ceci:

Génériques peut être définie lors de l'exécution, mais ce n'est pas verry confortable et doit être fait par la réflexion ... dans mon oppinion il est un « no go », mais juste un oppinion

Essayez d'utiliser le object.GetType() pour obtenir le type actuel de l'objet.

static class TestClass {
    static void Main(string[] args) {
        Object o = "Previous value";
        Test(ref o);
        Console.WriteLine(o);
        Console.ReadLine();
    }

    static public void Test<T>(ref T obj) {
        Object o = (Object)obj;
        Test2(ref o);
        obj = (T)o;
    }

    static public void Test2(ref object s) {
        if (s.GetType().Equals(typeof(String))) {
            s = "Hello world!";
        }
    }
}

La bonne façon de mettre en œuvre la méthode Test2 serait

static public void Test2<T>(ref T s)
    {
        if (s is string)
        {
            s = (T)(Object)"Hello world!";
        }
}

Ou suis-je manque quelque chose ici?

Si vous pouvez modifier le ref à un retour régulier, vous pouvez tricher massivement dans 4.0 via dynamic:

dynamic foo = obj;
Test(foo);

qui est maintenant:

Test<TheActualTypeOfObj>(obj);

Exemple complet:

static void Main(string[] args)
{
    object o = "Previous value";
    o = Test2((dynamic)o);
    Trace.WriteLine(o);
}

static public T Test2<T>(T s)
{
    if (typeof(T) == typeof(string))
    {
        s = (T)(object)"Hello world!";
    }
    return s;
}

qui écrit: "Bonjour tout le monde!"

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