Advertisement
dburner

Dynamic packets

Nov 9th, 2013
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.03 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Reflection;
  7. using System.Runtime.CompilerServices;
  8. using System.Linq.Expressions;
  9. using System.Reflection.Emit;
  10. using System.Threading;
  11.  
  12. namespace MirrorNet
  13. {
  14.     // Base class for packets
  15.     // This will be derived by users and should only contain basic type fields
  16.     public class UserPacket
  17.     {
  18.     }
  19.    
  20.     public class MirrorNetManager
  21.     {
  22.         private static MirrorNetManager instance = new MirrorNetManager();
  23.  
  24.         public static MirrorNetManager Instance
  25.         {
  26.             get { return instance; }
  27.         }
  28.  
  29.         // Dictionary: packetType -> field -> getter | setter
  30.         private class PropertyDictionary : Dictionary<Type, Dictionary<FieldInfo, Delegate>>
  31.         {
  32.         }
  33.  
  34.         private Dictionary<int, PacketConstructor> m_packetConstructors = new Dictionary<int, PacketConstructor>();
  35.         private PropertyDictionary m_packetFieldGetters = new PropertyDictionary();
  36.         private PropertyDictionary m_packetFieldSetters = new PropertyDictionary();
  37.  
  38.         public void SetValue(UserPacket packet, FieldInfo field, object value)
  39.         {
  40.             var setDelegate = m_packetFieldSetters[packet.GetType()][field];
  41.  
  42.             dynamic setAction = setDelegate; //Convert.ChangeType(setDelegate, setDelegate.GetType());
  43.             dynamic setObject = packet;      //Convert.ChangeType(packet, packet.GetType());
  44.             dynamic setValue  = value;       //Convert.ChangeType(value, value.GetType());
  45.  
  46.             setAction.Invoke(setObject, setValue);
  47.  
  48.             //setDelegate.DynamicInvoke(packet, value);
  49.         }
  50.  
  51.         public object GetValue(UserPacket packet, FieldInfo field)
  52.         {
  53.             var getDelegate = m_packetFieldGetters[packet.GetType()][field];
  54.            
  55.             dynamic getFunction = getDelegate; //Convert.ChangeType(getDelegate, getDelegate.GetType());
  56.             dynamic getObject   = packet;      //Convert.ChangeType(packet, packet.GetType());
  57.            
  58.             return getFunction.Invoke(getObject);
  59.            
  60.             //return getDelegate.DynamicInvoke(packet);
  61.         }
  62.  
  63.         public void InitializePackets(Assembly packetsAssembly)
  64.         {
  65.             var typesArray = packetsAssembly.GetTypes();
  66.  
  67.             foreach (Type type in typesArray)
  68.             {
  69.                 if (type.BaseType == typeof(UserPacket))
  70.                 {
  71.                     InsertPacketConstructor(type);
  72.                     InsertSettersAndGetters(type);
  73.                 }
  74.             }
  75.         }
  76.  
  77.         private void InsertSettersAndGetters(Type type)
  78.         {
  79.             Dictionary<FieldInfo, Delegate> getters = new Dictionary<FieldInfo, Delegate>();
  80.             Dictionary<FieldInfo, Delegate> setters = new Dictionary<FieldInfo, Delegate>();
  81.            
  82.             foreach (FieldInfo field in type.GetFields())
  83.             {
  84.                 Delegate getDelegate = CreateGetter(type, field.FieldType, field);
  85.                 Delegate setDelegate = CreateSetter(type, field.FieldType, field);
  86.  
  87.                 getters.Add(field, getDelegate);
  88.                 setters.Add(field, setDelegate);
  89.             }
  90.  
  91.             m_packetFieldGetters.Add(type, getters);
  92.             m_packetFieldSetters.Add(type, setters);
  93.         }
  94.  
  95.         private Delegate CreateGetter(Type classType, Type getReturnType, FieldInfo field)
  96.         {
  97.             string methodName = field.ReflectedType.FullName + ".get_" + field.Name;
  98.  
  99.             Type[] parameterTypes      = new Type[1] { classType };
  100.             DynamicMethod getterMethod = new DynamicMethod(methodName, getReturnType, parameterTypes, true);
  101.             ILGenerator gen = getterMethod.GetILGenerator();
  102.  
  103.             if (field.IsStatic)
  104.             {
  105.                 gen.Emit(OpCodes.Ldsfld, field);
  106.             }
  107.             else
  108.             {
  109.                 gen.Emit(OpCodes.Ldarg_0);
  110.                 gen.Emit(OpCodes.Ldfld, field);
  111.             }
  112.             gen.Emit(OpCodes.Ret);
  113.  
  114.             // Create the specific Func<,> instance
  115.             Type[] typeArgs    = new Type[] { classType, getReturnType };
  116.             Type   generic     = typeof(Func<,>);
  117.             Type   genInstance = generic.MakeGenericType(typeArgs);
  118.            
  119.             Delegate getterDelegate = getterMethod.CreateDelegate(genInstance);
  120.  
  121.             return getterDelegate;
  122.         }
  123.         private Delegate CreateSetter(Type classType, Type setValueType,  FieldInfo field)
  124.         {
  125.             string methodName = field.ReflectedType.FullName + ".set_" + field.Name;
  126.             Type[] parameters = new Type[2]
  127.             {
  128.                 classType,
  129.                 setValueType
  130.             };
  131.             DynamicMethod setterMethod = new DynamicMethod(methodName, null, parameters);
  132.             ILGenerator gen = setterMethod.GetILGenerator();
  133.  
  134.             if (field.IsStatic)
  135.             {
  136.                 gen.Emit(OpCodes.Ldarg_1);
  137.                 gen.Emit(OpCodes.Stsfld, field);
  138.             }
  139.             else
  140.             {
  141.                 gen.Emit(OpCodes.Ldarg_0);
  142.                 gen.Emit(OpCodes.Ldarg_1);
  143.                 gen.Emit(OpCodes.Stfld, field);
  144.             }
  145.             gen.Emit(OpCodes.Ret);
  146.  
  147.             // Create the specific Action<,> instance
  148.             Type[] typeArgs    = new Type[] { classType, setValueType };
  149.             Type   generic     = typeof(Action<,>);
  150.             Type   genInstance = generic.MakeGenericType(typeArgs);
  151.  
  152.             Delegate ret = setterMethod.CreateDelegate(genInstance);
  153.             return ret;
  154.         }
  155.  
  156.  
  157.         private void InsertPacketConstructor(Type packetType)
  158.         {
  159.             foreach (var member in packetType.GetFields())
  160.             {
  161.                Console.WriteLine(member);
  162.                // TODO: Implement
  163.             }
  164.         }
  165.     }
  166. }
  167.  
  168. // THIS IS IN A DIFERENT ASSEMBLY
  169. namespace MirrorNetTesting
  170. {
  171.     // This is just an example packet
  172.     public class StudentPacket : UserPacket
  173.     {
  174.         public int    age;
  175.         public int    height;
  176.         public double grades;
  177.         public string firstName;
  178.         public string lastName;
  179.     }
  180.    
  181.     class Program
  182.     {
  183.         static void Main(string[] args)
  184.         {
  185.             Assembly asm = Assembly.GetAssembly(typeof(StudentPacket));
  186.             MirrorNetManager.Instance.InitializePackets(asm);
  187.  
  188.             PerformanceTesting();
  189.  
  190.             Console.ReadLine();
  191.         }
  192.  
  193.         public static void PerformanceTesting()
  194.         {
  195.             int studentsCount = 1000 * 100;
  196.             StudentPacket[] studentsArray = new StudentPacket[studentsCount];
  197.  
  198.             //////////////////////////////////////////////////////////////////////////
  199.  
  200.             Random rnd = new Random();
  201.  
  202.             for (int i = 0; i < studentsArray.Length; i++)
  203.             {
  204.                 StudentPacket student = new StudentPacket();
  205.  
  206.                 student.age    = rnd.Next();
  207.                 student.height = rnd.Next();
  208.                 student.grades = rnd.NextDouble();
  209.                 student.firstName = "First " + rnd.Next().ToString();
  210.                 student.lastName  = "Last "  + rnd.Next().ToString();
  211.  
  212.                 studentsArray[i] = student;
  213.             }
  214.  
  215.             var fieldsArray = typeof(StudentPacket).GetFields().ToArray();
  216.  
  217.             //////////////////////////////////////////////////////////////////////////
  218.  
  219.             // Begin normal getter test
  220.             Console.WriteLine("Testing normal getters");
  221.             Stopwatch normalGetterSw = new Stopwatch();
  222.  
  223.             normalGetterSw.Start();
  224.  
  225.             foreach (var student in studentsArray)
  226.             {
  227.                 //object getValue;
  228.  
  229.                 var getAge       = student.age;
  230.                 var getHeight    = student.height;
  231.                 var getGrades    = student.grades;
  232.                 var getFirstName = student.firstName;
  233.                 var getLastName  = student.lastName;
  234.             }
  235.  
  236.             normalGetterSw.Stop();
  237.  
  238.             //////////////////////////////////////////////////////////////////////////
  239.  
  240.             // Begin reflection getter test
  241.             Console.WriteLine("Testing reflection getters");
  242.             Stopwatch reflectionGetterSw = new Stopwatch();
  243.  
  244.             reflectionGetterSw.Start();
  245.  
  246.             foreach (var student in studentsArray)
  247.             {
  248.                 object getValue;
  249.  
  250.                 for (int i = 0; i < fieldsArray.Length; i++ )
  251.                 {
  252.                     FieldInfo field = fieldsArray[i];
  253.                     getValue = MirrorNetManager.Instance.GetValue(student, field);
  254.                 }
  255.             }
  256.  
  257.             reflectionGetterSw.Stop();
  258.  
  259.             //////////////////////////////////////////////////////////////////////////
  260.  
  261.             // Begin normal setter test
  262.             Console.WriteLine("Testing normal setters");
  263.             Stopwatch normalSetterSw = new Stopwatch();
  264.  
  265.             int    age       = 10;
  266.             int    height    = 12;
  267.             double grades    = 1432.523d;
  268.             string firstName = "first name";
  269.             string lastName  = "last name";
  270.  
  271.             normalSetterSw.Start();
  272.  
  273.             foreach (var student in studentsArray)
  274.             {
  275.                 student.age       = age;
  276.                 student.height    = height;
  277.                 student.grades    = grades;
  278.                 student.firstName = firstName;
  279.                 student.lastName  = lastName;
  280.             }
  281.  
  282.             normalSetterSw.Stop();
  283.  
  284.             //////////////////////////////////////////////////////////////////////////
  285.  
  286.             // Begin reflection setter test
  287.             Console.WriteLine("Testing reflection setters ");
  288.             Stopwatch reflectionSetterSw = new Stopwatch();
  289.  
  290.             object[] setValues = new object[]
  291.             {
  292.                 age,
  293.                 height,
  294.                 grades,
  295.                 firstName,
  296.                 lastName
  297.             };
  298.  
  299.             reflectionSetterSw.Start();
  300.  
  301.             foreach (var student in studentsArray)
  302.             {
  303.                 for (int i = 0; i < fieldsArray.Length; i++ )
  304.                 {
  305.                     FieldInfo field = fieldsArray[i];
  306.                     MirrorNetManager.Instance.SetValue(student, field, setValues[i]);
  307.                 }
  308.             }
  309.  
  310.             reflectionSetterSw.Stop();
  311.  
  312.             //////////////////////////////////////////////////////////////////////////
  313.  
  314.             Console.WriteLine("Normal getter:     \t {0}",     normalGetterSw.ElapsedMilliseconds);
  315.             Console.WriteLine("Normal setter:     \t {0}",     normalSetterSw.ElapsedMilliseconds);
  316.             Console.WriteLine("Reflection getter: \t {0}", reflectionGetterSw.ElapsedMilliseconds);
  317.             Console.WriteLine("Reflection setter: \t {0}", reflectionSetterSw.ElapsedMilliseconds);
  318.  
  319.             //////////////////////////////////////////////////////////////////////////
  320.         }
  321.     }
  322. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement