public string GetQueryAddressString()
 {
     using (NativeBuffer buffer = NativeBuffer.CopyToNative(this))
     {
         IntPtr stringPtr = NativeMethods.MatchmakingServerNetworkAddress_GetQueryString(buffer.UnmanagedMemory);
         return(NativeHelpers.ToStringAnsi(stringPtr));
     }
 }
        private ServerListRequestHandle ServerRequest(ServerRequestType requestType, AppID appID,
                                                      MatchMakingKeyValuePair[] filters, MatchmakingServerListResponse requestResponse)
        {
            // Code reuse FTW!

            // Allocate an array that will hold addresses to native MatchMakingKeyValuePair objects
            using (NativeBuffer arrayBuffer = new NativeBuffer(Marshal.SizeOf(typeof(IntPtr)) * filters.Length))
            {
                NativeBuffer[] nativeObjects = new NativeBuffer[filters.Length];
                // Fill each array slot with an address to an actual object
                try
                {
                    for (int i = 0; i < filters.Length; i++)
                    {
                        // Copy the managed objects to native memory
                        NativeBuffer buffer = NativeBuffer.CopyToNative(filters[i]);
                        nativeObjects[i] = buffer;
                        // Add the native address to the array
                        Marshal.WriteInt32(arrayBuffer.UnmanagedMemory, i * Marshal.SizeOf(typeof(int)), buffer.UnmanagedMemory.ToInt32());
                    }

                    // Now do the actual request

                    switch (requestType)
                    {
                    case ServerRequestType.Internet:
                        return(new ServerListRequestHandle(
                                   NativeMethods.MatchmakingServers_RequestInternetServerList(appID.AsUInt32,
                                                                                              arrayBuffer.UnmanagedMemory, (uint)filters.Length, requestResponse.ObjectId)));

                    case ServerRequestType.Friends:
                        return(new ServerListRequestHandle(
                                   NativeMethods.MatchmakingServers_RequestFriendsServerList(appID.AsUInt32,
                                                                                             arrayBuffer.UnmanagedMemory, (uint)filters.Length, requestResponse.ObjectId)));

                    case ServerRequestType.Favorites:
                        return(new ServerListRequestHandle(
                                   NativeMethods.MatchmakingServers_RequestFavoritesServerList(appID.AsUInt32,
                                                                                               arrayBuffer.UnmanagedMemory, (uint)filters.Length, requestResponse.ObjectId)));

                    case ServerRequestType.History:
                        return(new ServerListRequestHandle(
                                   NativeMethods.MatchmakingServers_RequestHistoryServerList(appID.AsUInt32,
                                                                                             arrayBuffer.UnmanagedMemory, (uint)filters.Length, requestResponse.ObjectId)));

                    case ServerRequestType.Spectator:
                        return(new ServerListRequestHandle(
                                   NativeMethods.MatchmakingServers_RequestSpectatorServerList(appID.AsUInt32,
                                                                                               arrayBuffer.UnmanagedMemory, (uint)filters.Length, requestResponse.ObjectId)));

                    default:
                        // This should never happen as our code can not be allowed to make this error
                        throw new ArgumentException();
                    }
                }
                finally
                {
                    // Cleanup in all cases. Exception or not.
                    foreach (var item in nativeObjects)
                    {
                        if (item != null)
                        {
                            item.Dispose();
                        }
                    }
                }
            }
        }