Beispiel #1
0
        public void Make(Type type)
        {
            Type abstractPackage = typeof(IPacket <>).MakeGenericType(type);
            Type writerAction    = typeof(Action <,>).MakeGenericType(typeof(BinaryWriter), abstractPackage);

            Attributes.Add <Generated>();
            var packageTypes = CodeGenerator.GetUsedTypes()
                               .Where(t => t.GetInterfaces()
                                      .Where(i => i.IsGenericType)
                                      .Where(i => i.GetGenericTypeDefinition() == typeof(IPacket <>))
                                      .Any(i => i.GetGenericArguments()[0] == type)
                                      )
                               .ToArray();

            Dictionary <Type, string> descriptionByType = new Dictionary <Type, string>();

            foreach (var packageType in packageTypes)
            {
                descriptionByType.Add(packageType, Serializer.Definition(packageType));
            }

            packageTypes.OrderBy(t => descriptionByType[t]);

            List <Type> packetTypeList = new List <Type>();

            foreach (Type packetType in CodeGenerator.GetUsedTypes())
            {
                if (packetType.IsInterface || packetType.IsAbstract)
                {
                    continue;
                }
                Type packetGenericInterface = packetType.FindGenericInterface(typeof(IPacket <>));
                if (packetGenericInterface == null)
                {
                    continue;
                }
                if (packetGenericInterface.GetGenericArguments()[0] != type)
                {
                    continue;
                }
                packetTypeList.Add(packetType);
            }

            var packetTypesLines = Fields.Line;

            packetTypesLines.Add("private static readonly ")
            .Add <Type[]>()
            .Add($" _packetTypes = {{ {string.Join(", ", packetTypeList.Select(t=> $"typeof({RealTypeName(t)})"))} }};");
            packetTypesLines.Require(packetTypeList);

            Fields.AddLine($"public string {nameof(AnyProtocol.Definition)} => \"{string.Join(";", packageTypes.Select(t => descriptionByType[t]))}\";");

            Extends.Add(typeof(IProtocol <>), type);

            var getPacketTypesMethod = AddMethod(nameof(AnyProtocol.GetPacketTypes)).Public;

            getPacketTypesMethod.Return(typeof(IEnumerable <Type>));
            getPacketTypesMethod.AddLine($"return _packetTypes;");

            //private static readonly Type[] _packetTypes = { };

            /*
             * var staticConstructor = AddMethod(Name).Static;
             * var constructor = AddMethod(Name).Public;
             *
             * Require(typeof(Dictionary<Type, uint>));
             * Fields.AddLine("private static readonly Dictionary<Type, uint> _packetIdByType = new Dictionary<Type, uint>();");
             *
             *
             * AddMethod("Read")
             *  .Public.Void.AddArgument<BinaryReader>("reader")
             *  .AddLine($"{ReadingDescriptor}[reader.ReadUInt16()].Invoke(reader);");
             * var abstractWriter = AddMethod("Write<D>")
             *  .Public.Void.AddArgument<BinaryWriter>("writer")
             *  .AddArgument("in D data") //.AddWhere("D : struct")
             *  .AddWhere($"D : struct, IPacket<{SimpleName(type)}>")
             *  .AddLine($"(_descriptorWrite[_packetIdByType[typeof(D)]] as writer<D>)(writer, in data);");
             *
             * var listen = AddMethod("Listen<D>")
             *  .Public.Void.AddArgument($"PacketListener<{Name}, D> listener")
             *  .AddWhere($"D : struct, IPacket<{SimpleName(type)}>");
             * var listenSwitch = listen.AddSwitch("_packetIdByType[typeof(D)]");
             * listenSwitch.Case.Default.Add("throw new Exception();");
             *
             * Require<BinaryReader>();
             * Extends.Add(typeof(IProtocol<>), type);
             *
             * int fieldIndex = 0;
             * foreach (var packageType in packageTypes)
             * {
             *  string packageTypeName = SimpleName(packageType);
             *  string id = $"_{fieldIndex}{packageTypeName}Id";
             *  string reader = $"P{fieldIndex}{packageTypeName}Reader";
             *  string writer = $"Write";
             *  string serializer = $"_{fieldIndex}{packageTypeName}Serializer";
             *  string listener = $"_{fieldIndex}{packageTypeName}Listener";
             *
             *  Fields.Line.Add($"private const ushort {id} = {fieldIndex};");
             *
             *  Fields.Line.Add($"private ").Add(typeof(ISerializer<>), packageType).Add($" {serializer} = null;");
             *  Fields.Line.Add($"private ").Add(typeof(PacketListener<,>), type, packageType).Add($" {listener} = null;");
             *
             *  staticConstructor.AddLine($"_packetIdByType.Add(typeof(").Add(packageType).Add($"), {id});");
             *  constructor.AddLine($"{ReadingDescriptor}[{id}] = {reader};");
             *  constructor.AddLine($"{WritingDescriptor}[{id}] = (writer<").Add(packageType).Add($">){writer};");
             *
             *  var readMethod = AddMethod(reader).Private.Void.AddArgument<BinaryReader>("reader");
             *  readMethod.Line.Add(packageType).Add(" packet = default;");
             *  readMethod.Line.Add($"{serializer}.Read(ref packet, reader);");
             *  readMethod.Line.Add($"{listener}(in packet);");
             *
             *  var writeMethod = AddMethod(writer).Public.Void;
             *  writeMethod.AddArgument<BinaryWriter>("writer");
             *  writeMethod.Argument.In.Add(packageType).Add("packet");
             *  writeMethod.Line.Add($"writer.Write({id});");
             *  writeMethod.Line.Add($"{serializer}.Write(writer, in packet);");
             *
             *  listenSwitch.AddCase(id).Break.Line.Add($"{listener} = (PacketListener<{Name}, ").Add(packageType).Add(">)(object)listener;");
             *  constructor.Line.Add($"{serializer} = Serializer.Get<").Add(packageType).Add(">();");
             *
             *  fieldIndex++;
             * }
             *
             * Require(typeof(Action<>));
             * Fields.Add($"private Action<BinaryReader>[] {ReadingDescriptor} = new Action<BinaryReader>[{fieldIndex}];");
             * Fields.Line.Add($"private readonly object[] {WritingDescriptor} = new object[{fieldIndex}];");
             * Fields.Line.Add($"delegate void writer<D>(BinaryWriter writer, in D data) where D : struct, IPacket<{Name}>;");
             */
        }