繁体   English   中英

你如何使用哈希集<string>使用 c# 中的二进制读取器</string>

[英]How do you use hashset<string> with a binary reader in c#

我正在尝试将hashset<string>保存到数据库然后检索它,但我不知道如何为此使用二进制阅读器。

#region Types

TypeList = new Dictionary<string, Type>

我有:

[typeof(HashSet<string>).FullName]=typeof(HashSet<string>)

写它我有:

[typeof(HashSet<string>)] = (v,w) =>
            {
                w.Write(v != null);
                if (v == null) return;
                HashSet<string> datas = (HashSet<string>)v;
                w.Write(datas.Count);
                foreach(string data in datas)
                {
                    w.Write(data);
                }
            }

但我不知道如何将它从数据库读回哈希集

            [typeof(HashSet<string>)] = r=>
            {
                int length = r.ReadInt32();
                HashSet<string> data = new HashSet<string>();
                for (int i = 0; i < length; i++)
                    data.Add(r.ReadString());

                return data;
            }

这失败并出现错误:

超出 stream 的末尾后无法读取。

我对二进制阅读器的了解非常低,我不确定如何从数据库中读取哈希集。 显然循环不会完全正确,因为哈希集中没有length() ,值没有索引等,优点(以及为什么我需要在代码的其他地方使用它)是它永远不能包含两个相同的价值。

r.count不起作用(即使这是你找到哈希集的“长度”的方式,我不知道你如何迭代 r 中的值(或者即使你是这样做的)这让我墙了两天了。

澄清:我正在添加一个开源游戏,用户数据存储在数据库中,我的哈希集数组没有保存,似乎处理数据库的 class 需要定义每种类型,这是一个区域对我来说很陌生。 以前从未真正处理过数据存储。 我得到保证,一旦我添加了定义来告诉它如何处理哈希集,那么哈希集就会保存....但是我不知道如何做那部分,我正在尝试并且已经有一段时间了(并且仍然是)。 具有讽刺意味的是,这是我正在努力保持我的思想和心理健康,同时受到保护,后者肯定会受苦

完整的 class:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Library;

namespace MirDB
{
public sealed class DBValue
{
    internal static readonly Dictionary<string, Type> TypeList;
    private static readonly Dictionary<Type, Func<BinaryReader, object>> TypeRead;
    private static readonly Dictionary<Type, Action<object, BinaryWriter>> TypeWrite;

    static DBValue()
    {
        #region Types
        TypeList = new Dictionary<string, Type>
        {
            [typeof(Boolean).FullName] = typeof(Boolean),
            [typeof(Byte).FullName] = typeof(Byte),
            [typeof(Byte[]).FullName] = typeof(Byte[]),
            [typeof(Char).FullName] = typeof(Char),
            [typeof(Color).FullName] = typeof(Color),
            [typeof(DateTime).FullName] = typeof(DateTime),
            [typeof(Decimal).FullName] = typeof(Decimal),
            [typeof(Double).FullName] = typeof(Double),
            [typeof(Int16).FullName] = typeof(Int16),
            [typeof(Int32).FullName] = typeof(Int32),
            [typeof(Int32[]).FullName] = typeof(Int32[]),
            [typeof(Int64).FullName] = typeof(Int64),
            [typeof(Point).FullName] = typeof(Point),
            [typeof(SByte).FullName] = typeof(SByte),
            [typeof(Single).FullName] = typeof(Single),
            [typeof(Size).FullName] = typeof(Size),
            [typeof(String).FullName] = typeof(String),
            [typeof(TimeSpan).FullName] = typeof(TimeSpan),
            [typeof(UInt16).FullName] = typeof(UInt16),
            [typeof(UInt32).FullName] = typeof(UInt32),
            [typeof(UInt64).FullName] = typeof(UInt64),
            [typeof(Point[]).FullName] = typeof(Point[]),
            [typeof(Stats).FullName] = typeof(Stats),
            [typeof(BitArray).FullName] = typeof(BitArray),
            [typeof(HashSet<string>).FullName]=typeof(HashSet<string>)
        };
        #endregion

        #region Reads

        TypeRead = new Dictionary<Type, Func<BinaryReader, object>>
        {
            [typeof(Boolean)] = r => r.ReadBoolean(),
            [typeof(Byte)] = r => r.ReadByte(),
            [typeof(Byte[])] = r => r.ReadBytes(r.ReadInt32()),
            [typeof(Char)] = r => r.ReadChar(),
            [typeof(Color)] = r => Color.FromArgb(r.ReadInt32()),
            [typeof(DateTime)] = r => DateTime.FromBinary(r.ReadInt64()),
            [typeof(Decimal)] = r => r.ReadDecimal(),
            [typeof(Double)] = r => r.ReadDouble(),
            [typeof(Enum)] = r => r.ReadInt32(),
            [typeof(Int16)] = r => r.ReadInt16(),
            [typeof(Int32)] = r => r.ReadInt32(),
            [typeof(Int32[])] = r =>
            {
                if (!r.ReadBoolean()) return null;

                int length = r.ReadInt32();

                Int32[] values = new Int32[length];
                for (int i = 0; i < length; i++)
                    values[i] = r.ReadInt32();

                return values;

            },
            [typeof(Int64)] = r => r.ReadInt64(),
            [typeof(Point)] = r => new Point(r.ReadInt32(), r.ReadInt32()),
            [typeof(SByte)] = r => r.ReadSByte(),
            [typeof(Single)] = r => r.ReadSingle(),
            [typeof(Size)] = r => new Size(r.ReadInt32(), r.ReadInt32()),
            [typeof(String)] = r => r.ReadString(),
            [typeof(TimeSpan)] = r => TimeSpan.FromTicks(r.ReadInt64()),
            [typeof(UInt16)] = r => r.ReadUInt16(),
            [typeof(UInt32)] = r => r.ReadUInt32(),
            [typeof(UInt64)] = r => r.ReadUInt64(),
            [typeof(Point[])] = r =>
            {
                if (!r.ReadBoolean()) return null;

                int length = r.ReadInt32();

                Point[] points = new Point[length];
                for (int i = 0; i < length; i++)
                    points[i] = new Point(r.ReadInt32(), r.ReadInt32());

                return points;

            },
            [typeof(Stats)] = r => r.ReadBoolean() ? new Stats(r) : null,
            [typeof(BitArray)] = r =>
            {
                if (!r.ReadBoolean()) return null;

                return new BitArray(r.ReadBytes(r.ReadInt32()));
            },
            [typeof(HashSet<string>)] = r=>
            {
                int length =r.ReadInt32();
                string[] temp = new string[length];


                for (int i = 0; i < length; i++)
                {
                    temp[i] = r.ReadString();
                }
                HashSet<string> data = new HashSet<string>();
                foreach(string indata in temp)
                {
                    data.Add(indata);
                }
                return data;               
            }
        };

        #endregion

        #region Writes

        TypeWrite = new Dictionary<Type, Action<object, BinaryWriter>>
        {
            [typeof(Boolean)] = (v, w) => w.Write((bool) v),
            [typeof(Byte)] = (v, w) => w.Write((Byte) v),
            [typeof(Byte[])] = (v, w) =>
            {
                w.Write(((Byte[]) v).Length);
                w.Write((Byte[]) v);
            },
            [typeof(Char)] = (v, w) => w.Write((Char) v),
            [typeof(Color)] = (v, w) => w.Write(((Color) v).ToArgb()),
            [typeof(DateTime)] = (v, w) => w.Write(((DateTime) v).ToBinary()),
            [typeof(Decimal)] = (v, w) => w.Write((Decimal) v),
            [typeof(Double)] = (v, w) => w.Write((Double) v),
            [typeof(Int16)] = (v, w) => w.Write((Int16) v),
            [typeof(Int32)] = (v, w) => w.Write((Int32) v),
            [typeof(Int32[])] = (v, w) =>
            {
                w.Write(v != null);
                if (v == null) return;
                Int32[] values = (Int32[]) v;

                w.Write(values.Length);

                foreach (Int32 value in values)
                    w.Write(value);
            },
            [typeof(Int64)] = (v, w) => w.Write((Int64) v),
            [typeof(Point)] = (v, w) =>
            {
                w.Write(((Point) v).X);
                w.Write(((Point) v).Y);
            },
            [typeof(SByte)] = (v, w) => w.Write((SByte) v),
            [typeof(Single)] = (v, w) => w.Write((Single) v),
            [typeof(Size)] = (v, w) =>
            {
                w.Write(((Size) v).Width);
                w.Write(((Size) v).Height);
            },
            [typeof(String)] = (v, w) => w.Write((String) v ?? string.Empty),
            [typeof(TimeSpan)] = (v, w) => w.Write(((TimeSpan) v).Ticks),
            [typeof(UInt16)] = (v, w) => w.Write((UInt16) v),
            [typeof(UInt32)] = (v, w) => w.Write((UInt32) v),
            [typeof(UInt64)] = (v, w) => w.Write((UInt64) v),
            [typeof(Point[])] = (v, w) =>
            {
                w.Write(v != null);
                if (v == null) return;
                Point[] points = (Point[]) v;

                w.Write(points.Length);

                foreach (Point point in points)
                {
                    w.Write(point.X);
                    w.Write(point.Y);
                }
            },
            [typeof(Stats)] = (v, w) =>
            {
                w.Write(v != null);
                if (v == null) return;

                ((Stats)v).Write(w);
            },
            [typeof(BitArray)] = (v, w) =>
            {
                w.Write(v != null);
                if (v == null) return;

                BitArray array = (BitArray) v;


                byte[] bytes = new byte[(int) Math.Ceiling(array.Length/8d)];
                array.CopyTo(bytes, 0);

                w.Write(bytes.Length);
                w.Write(bytes);
            },
            [typeof(HashSet<string>)] = (v,w) =>
            {
                w.Write(v != null);
                if (v == null) return;
                HashSet<string> datas = (HashSet<string>)v;
                w.Write(datas.Count);
                foreach(string data in datas)
                {
                    w.Write(data);
                }
            }
        };

        #endregion
    }

    public string PropertyName { get; }
    public Type PropertyType { get; }
    public PropertyInfo Property { get; }

    public DBValue(BinaryReader reader, Type type)
    {
        PropertyName = reader.ReadString();
        PropertyType = TypeList[reader.ReadString()];


        PropertyInfo property = type?.GetProperty(PropertyName);

        if (property != null)
            if (property.GetCustomAttribute<IgnoreProperty>() != null) 
return;

        Property = property;
    }
    public DBValue(PropertyInfo property)
    {
        Property = property;

        PropertyName = property.Name;

        if (property.PropertyType.IsEnum)
        {
            PropertyType = property.PropertyType.GetEnumUnderlyingType();
            return;
        }

        if (property.PropertyType.IsSubclassOf(typeof(DBObject)))
        {
            PropertyType = typeof(int);
            return;
        }

        PropertyType = property.PropertyType;
    }

    public void Save(BinaryWriter writer)
    {
        writer.Write(PropertyName);
        writer.Write(PropertyType.FullName);
    }

    public object ReadValue(BinaryReader reader)
    {
        return TypeRead[PropertyType](reader);
    }
    public void WriteValue(object value, BinaryWriter writer)
    {
        TypeWrite[PropertyType](value, writer);
    }


    public bool IsMatch(DBValue value)
    {
        return string.Compare(PropertyName, value.PropertyName, StringComparison.Ordinal) == 0 && PropertyType == value.PropertyType;
    }
}

}

整个操作的某些东西似乎是错误的:

你在 memory 中有一个字符串集合。

但是,不是将其存储到具有 ForeignKey 和 VARCHAR 列的表中,而是将它们转换为字节 stream 来存储字节?

数据应尽可能长时间地保存为 DB 可处理格式。 数据完整性应该尽可能长时间地留给数据库。 您将无法对图像文件、大多数 Office 文档或类似的 BLOB 进行有意义的处理或数据完整性是不可避免的,但实际上您有可处理的字符串。

鉴于信息有限,我将创建一个包含以下内容的表:

  • ID。 只是这个表的主键
  • Fk_WhateverThisRelatesTo 保存 HashSet 的任何内容的键
  • VARCHAR StringValue - 每个字符串的值

然后对Fk_WhateverThisRelatesToStringValue组合设置一个 UNIQUE 约束。 Fk 和 StringValues 可以重复,但两者的组合都不能。

似乎我一开始并没有阅读 boolean ......这条线让我绕弯了两天......只是看不出它不见了。

[typeof(HashSet<string>)] = r=>
            {
                if (!r.ReadBoolean()) return null;
                int length =r.ReadInt32();
                string[] temp = new string[length];

                for (int i = 0; i < length; i++)
                {
                    temp[i] = r.ReadString();
                }
                HashSet<string> data = new HashSet<string>();
                foreach(string indata in temp)
                {
                    data.Add(indata);
                }
                return data;               
            }

需要这一行:

if (!r.ReadBoolean()) return null;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM