C# ProtocolTypeManager.GetInstance

Inscrit
19 Mai 2013
Messages
68
Reactions
0
#1
Bonjour tout le monde !

J'ai actuellement besoin de la méthode ProtocolTypeManager.GetInstance() dans la classe ObjectItem et, j'y comprenais un peu rien donc je suis aller pomper chez BiM (qui, codé en C# m'a paru plus compréhensible)... :oops:

Rappel du principal de la classe ProtocolTypeManager de BiM :

Code:
        private static readonly Dictionary<short, Type> m_types = new Dictionary<short, Type>(200);
        private static readonly Dictionary<short, Func<object>> m_typesConstructors = new Dictionary<short, Func<object>>(200);

        static ProtocolTypeManager()
        {
            Assembly asm = Assembly.GetAssembly(typeof(ProtocolTypeManager));

            foreach (Type type in asm.GetTypes())
            {
                if (type.Namespace == null || !type.Namespace.StartsWith(typeof(ProtocolTypeManager).Namespace))
                    continue;

                FieldInfo field = type.GetField("Id");

                if (field != null)
                {
                    // le cast uint est obligatoire car l'objet n'a pas de type
                    short id = (short)(field.GetValue(type));

                    m_types.Add(id, type);

                    ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);

                    if (ctor == null)
                        throw new Exception(string.Format("'{0}' doesn't implemented a parameterless constructor", type));

                    m_typesConstructors.Add(id, ctor.CreateDelegate<Func<object>>());
                }
            }
        }

        public static T GetInstance<T>(short id) where T : class
        {
            if (!m_types.ContainsKey(id))
            {
                throw new ProtocolTypeNotFoundException(string.Format("Type <id:{0}> doesn't exist", id));
            }

            return m_typesConstructors[id]() as T;
        }

Là, il se trouve que ça fonctionne pas très bien. Je fais appel à ProtocolTypeManager.GetInstance :

Code:
                        loc_5 = ProtocolTypeManager.GetInstance<ObjectEffect>((short)loc_4);
(A savoir que loc_5 est un ObjectEffect non instancié (j'ai essayé aussi en l'instanciant) qui sera ajouté ensuite à une List<ObjectEffecct>.)

Là, il me retourne un ObjectEffectInteger (comme il faut, étant donné que loc_4 vaut 70 et que protocolId d'ObjectEffectInteger vaut 70) mais il se trouve qu' à la ligne suivante ... :

Code:
                        loc_5.ReadPacket(big_Endian_Reader);
(ReadPacket correspond au deserialize, big_Endian_Reader, au reader, mais il n'y à pas de soucis à ce niveau.)
(Mieux comprendre en image : http://puu.sh/5hjjE.png)

... il n'ira lire que dans ObjectEffect et pas dans ObjectEffectInteger (puis ObjectEffect car il lit la base de ObjectEffectInteger, qui hérite de ObjectEffect, avant de retourner dans ObjectEffectInteger pour finir la lecture). (Mieux comprendre en image : http://puu.sh/5hjno.png et http://puu.sh/5hjoZ.png)

Donc ça me décalle d'un short (censé être lu dans ObjectEffectInteger) et au deuxième tour de la boucle, il lit la valeur normalement de ObjectEffectInteger.value (10), et sauf qu'il cherche l'instance pour 10 (soit LoginQueueMessage), et ça plante.

Personne à des suggestions ?! :S
 

asyade

Membre Actif
Inscrit
26 Avril 2013
Messages
368
Reactions
1
#2
Fait ton propre protocole type manager ,je pence que ta pas bien compris a quoi sa sert (j'ais fait la méme chose a mes début) enfait ton protocoletypemanager retourn une instance d'un type et pour savoire quelle type d'instance il doit retourner tu cherche le type qui a cette id ,par example pour les actor dans le 226 il y a des monstre, des pnj et des joueur et pour chaque il y a un type dédiée,

un petit example

public INetworkType GetInstance(int id)
{
switch(id)
{
case 100
return new TypeQuiALid100();
break;
}
}
 
Inscrit
19 Mai 2013
Messages
68
Reactions
0
#3
asyade a dit:
Fait ton propre protocole type manager ,je pence que ta pas bien compris a quoi sa sert (j'ais fait la méme chose a mes début) enfait ton protocoletypemanager retourn une instance d'un type et pour savoire quelle type d'instance il doit retourner tu cherche le type qui a cette id ,par example pour les actor dans le 226 il y a des monstre, des pnj et des joueur et pour chaque il y a un type dédiée,

un petit example

public INetworkType GetInstance(int id)
{
switch(id)
{
case 100
return new TypeQuiALid100();
break;
}
}
J'ai bien compris l'utilité de ProtocolTypeManager. Bouh2 fait de la Reflection, qu'il faut avouer, est plus optimal que le switch/case. Je pourrai à la rigueur mettre un switch/case, mais jusqu'à avoir le temps de me pencher sur la Reflection.
 

asyade

Membre Actif
Inscrit
26 Avril 2013
Messages
368
Reactions
1
#4
J'ais bien vue ce que bim utillise mais c'est compliqué ,en plus si je ne me trompe tu ne doit pas étre entrain de dévloper un gros bot mais juste un test donc pas la peine de ce prendre la téte niveau performance tout de suite :)
 
Inscrit
19 Mai 2013
Messages
68
Reactions
0
#5
asyade a dit:
J'ais bien vue ce que bim utillise mais c'est compliqué ,en plus si je ne me trompe tu ne doit pas étre entrain de dévloper un gros bot mais juste un test donc pas la peine de ce prendre la téte niveau performance tout de suite :)
Oui, c'est plutôt pour une utilisation personnelle donc c'est sûr pas obligé d'optimiser niveau performances. Mais quand on peut mieux, autant tenter. Mais je vais me raviser aux switch/case pour l'instant.
 

bouh2

Membre Actif
Inscrit
12 Septembre 2008
Messages
184
Reactions
21
#6
Sur le papier un switch est plus rapide que de chercher dans un dictionnaire un objet associé, mais c'est absolument infime, qui va chercher à gagner quelques micro secondes et avoir un code dégeulasse et difficilement maintenable au lieu de faire quelque chose de compact, propre et facilement modifiable.

Pour résoudre ton problème c'est simple, ajoute virtual sur la méthode d'ObjectEffect et override sur celle de ObjectEffectInteger. En fait si tu ne virtualise pas la méthode il ne va pas savoir que c'est une surchage de celle-ci. En gros tu as deux méthode ObjectEffect.ReadPacket() et ObjectEffectInteger.ReadPacket() alors que tu voudrais que ce soit la même.
 
Inscrit
19 Mai 2013
Messages
68
Reactions
0
#7
bouh2 a dit:
Sur le papier un switch est plus rapide que de chercher dans un dictionnaire un objet associé, mais c'est absolument infime, qui va chercher à gagner quelques micro secondes et avoir un code dégeulasse et difficilement maintenable au lieu de faire quelque chose de compact, propre et facilement modifiable.

Pour résoudre ton problème c'est simple, ajoute virtual sur la méthode d'ObjectEffect et override sur celle de ObjectEffectInteger. En fait si tu ne virtualise pas la méthode il ne va pas savoir que c'est une surchage de celle-ci. En gros tu as deux méthode ObjectEffect.ReadPacket() et ObjectEffectInteger.ReadPacket() alors que tu voudrais que ce soit la même.
Ooooooook ! Ca pète, j'essaie ça ! Merci mec :)
 
Haut Bas