栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

C# 7.3 .Net 4.6.1 如何将一个对象里的任意字段作为键去找这个对象

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C# 7.3 .Net 4.6.1 如何将一个对象里的任意字段作为键去找这个对象

写了一个超级吃内存的“疯狂数据库”。用空间换时间。
本集合可以拓展一下作为一个泛型List使用。适用于引索常量对象。
并发List(ConcurrentList)集合依赖于开源项目:
https://github.com/azborgonovo/SlimConcurrentCollections

using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using SlimConcurrentCollections;

namespace Inspector_For_Test_Sieves.Model.Entities
{
    /// 
    /// 专门用于存储偏向常量、字段类型独立不重复的数据,提供高效查询。
    /// 偏向只增不减。(非线程安全)
    /// 
    public class CrazyAddOnlyDatabase : IEnumerable where T : class
    {
        public class ReadWriteMethod
        {
            public const string GetValueMethodName = "GetValue";
            public const string SetValueMethodName = "SetValue";

            public static readonly Type[] GetValueMethodParams = {typeof(object)};

            public static readonly Type[] SetValueMethodParams = {typeof(object), typeof(object)};

            public static readonly MethodInfo FieldInfoRead =
                typeof(FieldInfo).GetMethod(GetValueMethodName, GetValueMethodParams);

            public static readonly MethodInfo FieldInfoWrite =
                typeof(FieldInfo).GetMethod(SetValueMethodName, SetValueMethodParams);

            public static readonly MethodInfo PropertyInfoRead =
                typeof(PropertyInfo).GetMethod(GetValueMethodName, GetValueMethodParams);

            public static readonly MethodInfo PropertyInfoWrite =
                typeof(PropertyInfo).GetMethod(SetValueMethodName, SetValueMethodParams);

            protected object MethodProvider;
            protected MethodInfo ReadMethod;
            protected MethodInfo WriteMethod;

            public object Read(object operationTarget)
            {
                return ReadMethod.Invoke(MethodProvider, new[] {operationTarget});
            }

            public object Write(object operationTarget, object inputValue)
            {
                return WriteMethod.Invoke(MethodProvider, new[] {operationTarget, inputValue});
            }

            public ReadWriteMethod(FieldInfo fieldInfo)
            {
                MethodProvider = fieldInfo;
                ReadMethod = FieldInfoRead;
                WriteMethod = FieldInfoWrite;
            }

            public ReadWriteMethod(PropertyInfo propertyInfo)
            {
                MethodProvider = propertyInfo;
                ReadMethod = PropertyInfoRead;
                WriteMethod = PropertyInfoWrite;
            }
        }

        /// 
        /// 记录每一列的类型(有序)
        /// 
        protected List MyColumnTypeList = new List();

        /// 
        /// 记录每一列的反射类型(有序)
        /// 
        protected List MemberInfoList = new List();

        /// 
        /// 记录每一列的读写方法(有序)
        /// 
        protected List MethodInfoList = new List();

        /// 
        /// 记录每一列的类型 的 字段名称(有序)
        /// 
        protected List MyColumnNameList = new List();

        /// 
        /// 每一列的引索。以对象里的每一个字段的值作为 键,值 是 行下标。
        /// 
        protected List>> RowIndexDatabase =
            new List>>();

        /// 
        /// 记录每一行的对象
        /// 
        protected ConcurrentList RowList = new ConcurrentList();

        // /// 
        // /// 记录主键列(不允许重复)
        // /// 
        // protected Dictionary PrimaryKeyColumn = new Dictionary();

        /// 
        /// 字段名称做主键,加速引索查询
        /// 
        protected IDictionary ColumnNameListCache = new Dictionary();

        /// 
        /// Type 字段做主键,加速引索查询。
        /// (注意!这只会引索到同类型的其中一个!
        /// 最好是在类型不重复的情况下使用)
        /// 
        protected IDictionary ColumnTypeListCache = new Dictionary();

        /// 
        /// C#泛型如果不是class类型则无法使用“as”关键词来无损拆箱。
        /// 为了克服泛型支持性不佳而使用反射强行调用
        /// 
        protected MethodInfo MethodInfoGetListByColumnWithClassType;

        /// 
        /// 是否为字段值为 null 的 字段 添加引索
        /// 
        public bool NoIndex4Null { get; set; }

        public IReadOnlyList ColumnTypeList => MyColumnTypeList.AsReadOnly();
        public IReadOnlyList ColumnNameList => MyColumnNameList.AsReadOnly();
        
        public System.Collections.ObjectModel.ReadOnlyDictionary ColumnNameDictionary =>
            new System.Collections.ObjectModel.ReadOnlyDictionary(ColumnNameListCache);

        public System.Collections.ObjectModel.ReadOnlyDictionary ColumnTypeDictionary =>
            new System.Collections.ObjectModel.ReadOnlyDictionary(ColumnTypeListCache);

        public CrazyAddOnlyDatabase() : this(false)
        {
        }

        public CrazyAddOnlyDatabase(bool noIndex4Null) :
            this(BindingFlags.Instance | BindingFlags.Public, noIndex4Null)
        {
        }

        public CrazyAddOnlyDatabase(BindingFlags bindingAttr, bool noIndex4Null)
        {
            MethodInfoGetListByColumnWithClassType = this.GetType().GetMethod(
                nameof(GetListByColumnWithClassType)
            );

            Type type = typeof(T);
            PropertyInfo[] propertyInfos = type.GetProperties(bindingAttr);
            FieldInfo[] fieldInfos = type.GetFields(bindingAttr);
            NoIndex4Null = noIndex4Null;

            int column = 0;
            for (int j = 0; j < propertyInfos.Length; j++, column++)
            {
                PropertyInfo propertyInfo = propertyInfos[j];
                MemberInfoList.Add(propertyInfo);
                MethodInfoList.Add(new ReadWriteMethod(propertyInfo));
                MyColumnTypeList.Add(propertyInfo.PropertyType);
                MyColumnNameList.Add(propertyInfo.Name);
                ColumnNameListCache[propertyInfo.Name] = column;
                ColumnTypeListCache[propertyInfo.PropertyType] = column;
                RowIndexDatabase.Add(new ConcurrentDictionary>());
            }
            
            for (int j = 0; j < fieldInfos.Length; j++, column++)
            {
                FieldInfo fieldInfo = fieldInfos[j];
                MemberInfoList.Add(fieldInfo);
                MethodInfoList.Add(new ReadWriteMethod(fieldInfo));
                MyColumnTypeList.Add(fieldInfo.FieldType);
                MyColumnNameList.Add(fieldInfo.Name);
                ColumnNameListCache[fieldInfo.Name] = column;
                ColumnTypeListCache[fieldInfo.FieldType] = column;
                RowIndexDatabase.Add(new ConcurrentDictionary>());
            }
        }

        public int GetColumnIndexByFieldName(string fieldName) => ColumnNameListCache[fieldName];
        public int GetColumnIndexByFieldType(Type type) => ColumnTypeListCache[type];

        /// 
        /// 按 字段类型 和 确切值 查询行记录。
        /// (注意!这只会引索到同类型的其中一个!
        /// 最好是在类型不重复的情况下使用)
        /// 
        public List QueryRow(Type fieldType, object value)
        {
            List result = new List();
            if (!ColumnTypeListCache.ContainsKey(fieldType))
                return result;

            int column = ColumnTypeListCache[fieldType];
            ConcurrentDictionary> db = RowIndexDatabase[column];
            db.TryGetValue(value, out List rows);
            if (rows != null)
            {
                for (int i = 0; i < rows.Capacity; i++)
                {
                    result.Add(RowList[rows[i]]);
                }
            }

            return result;
        }

        /// 
        /// 按 字段名称 和 确切值 查询行记录。
        /// 
        public List QueryRow(string fieldName, object value)
        {
            List result = new List();
            if (!ColumnNameListCache.ContainsKey(fieldName))
                return result;

            int column = ColumnNameListCache[fieldName];
            ConcurrentDictionary> db = RowIndexDatabase[column];
            db.TryGetValue(value, out List rows);
            if (rows != null)
            {
                for (int i = 0; i < rows.Capacity; i++)
                {
                    result.Add(RowList[rows[i]]);
                }
            }

            return result;
        }

        /// 
        /// 直接按 确切值(及其类型) 查询行记录。
        /// (注意!这只会引索到同类型的其中一个!
        /// 最好是在类型不重复的情况下使用)
        /// 
        public List QueryRow(object value)
        {
            return QueryRow(value.GetType(), value);
        }

        /// 
        /// 直接按 确切值(及其类型) 查询第一个匹配的行记录。
        /// (注意!这只会引索到同类型的其中一个!
        /// 最好是在类型不重复的情况下使用)
        /// 
        public T QueryFirstRow(object value)
        {
            T result = null;
            Type fieldType = value.GetType();
            if (ColumnTypeListCache.ContainsKey(fieldType))
            {
                // 定位 到 列
                int column = ColumnTypeListCache[fieldType];
                // 检索同值的 行 的 下标
                ConcurrentDictionary> db = RowIndexDatabase[column];
                db.TryGetValue(value, out List rows);
                if (rows != null)
                {
                    //添加检索到的行
                    result = RowList[rows[0]];
                }
            }

            return result;
        }

        public ArrayList GetListByFieldName(string fieldName) =>
            GetListByColumnIndex(GetColumnIndexByFieldName(fieldName));

        public ArrayList GetListByFieldType(Type fieldType) =>
            GetListByColumnIndex(GetColumnIndexByFieldType(fieldType));

        public ArrayList GetListByColumnIndex(int column)
        {
            ReadWriteMethod rw = MethodInfoList[column];
            ArrayList result = new ArrayList();
            for (int i = 0; i < RowList.Count; i++)
            {
                result.Add(rw.Read(RowList[i]));
            }

            return result;
        }

        public List GetListByColumnWithForcedType(int column)
        {
            ReadWriteMethod rw = MethodInfoList[column];
            List result = new List();

            for (int i = 0; i < RowList.Count; i++)
            {
                result.Add((T2) rw.Read(RowList[i]));
                // result.Add((T2) Convert.ChangeType(rw.Read(RowList[i]), typeof(T2)));
            }

            return result;
        }

        public List GetListByColumnWithClassType(int column) where T2 : class
        {
            ReadWriteMethod rw = MethodInfoList[column];
            List result = new List();

            for (int i = 0; i < RowList.Count; i++)
            {
                result.Add(rw.Read(RowList[i]) as T2);
            }

            return result;
        }

        public List GetListByColumnIndex(int column)
        {
            List result;
            Type type = typeof(T2);
            if (type.IsClass)
            {
                MethodInfo miConstructed = MethodInfoGetListByColumnWithClassType
                    .MakeGenericMethod(type);
                result = miConstructed.Invoke(
                    null,
                    new object[] {column}
                ) as List;
            }
            else
            {
                result = GetListByColumnWithForcedType(column);
            }

            return result;
        }

        public List GetListByFieldName(string fieldName) =>
            GetListByColumnIndex(GetColumnIndexByFieldName(fieldName));

        /// 
        /// 按 字段类型 查询列记录。
        /// (注意!这只会引索到同类型的其中一个!
        /// 最好是在类型不重复的情况下使用)
        /// 
        public List GetListByFieldType() =>
            GetListByColumnIndex(GetColumnIndexByFieldType(typeof(T2)));

        public void ThrowNotSupport(MethodBase methodInfo)
        {
            throw new NotSupportedException("Does not support " + methodInfo.Name + " operation.");
        }

        public void Add(T item)
        {
            bool isFound = false;
            int row = RowList.Count;
            RowList.Add(item);
            for (; row < RowList.Count; row++)
            {
                if (RowList[row].Equals(item))
                {
                    isFound = true;
                    break;
                }
            }

            if (!isFound)
            {
                throw new InvalidOperationException("List member changed while adding item is not complete.");
            }

            //遍历每一列
            for (int column = 0; column < MemberInfoList.Count; column++)
            {
                ReadWriteMethod rw = MethodInfoList[column];
                ConcurrentDictionary> db = RowIndexDatabase[column];
                object key = rw.Read(item);
                if (NoIndex4Null && null == key)
                {
                    continue;
                }

                List columnIndexList = db.GetOrAdd(key, new List());
                columnIndexList.Add(row);
            }
        }

        public void Clear()
        {
            // RowList.Clear();
            ThrowNotSupport(MethodBase.GetCurrentMethod());
        }

        public bool Contains(T item)
        {
            return RowList.Contains(item);
        }

        public int IndexOf(T item)
        {
            return RowList.IndexOf(item);
        }

        public bool Remove(T item)
        {
            ThrowNotSupport(MethodBase.GetCurrentMethod());
            return false;
            // return RowList.Remove(item);
        }
        
        public void Insert(int index, T item)
        {
            ThrowNotSupport(MethodBase.GetCurrentMethod());
            // RowList.Insert(index, item);
        }
        
        public void RemoveAt(int index)
        {
            ThrowNotSupport(MethodBase.GetCurrentMethod());
            // RowList.RemoveAt(index);
        }

        public int Count => RowList.Count;
        // public bool IsReadOnly => false;

        public T this[int row]
        {
            get => RowList[row];
            set
            {
                T newItem = value;
                T oldItem = RowList[row];

                //遍历每一列
                for (int column = 0; column < MemberInfoList.Count; column++)
                {
                    ReadWriteMethod rw = MethodInfoList[column];
                    ConcurrentDictionary> db = RowIndexDatabase[column];
                    object newKey = rw.Read(newItem);
                    object oldKey = rw.Read(oldItem);
                    if (!oldKey.Equals(newKey))
                    {
                        List columnIndexList;
                        columnIndexList = db.GetOrAdd(oldKey, new List());
                        columnIndexList.Remove(row);
                        if (columnIndexList.Count == 0)
                            db.TryRemove(oldKey, out _);
                        if (NoIndex4Null && null == newKey)
                        {
                            continue;
                        }

                        columnIndexList = db.GetOrAdd(newKey, new List());
                        columnIndexList.Add(row);
                    }
                }

                RowList[row] = newItem;
            }
        }

        public IEnumerator GetEnumerator()
        {
            return RowList.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void CopyTo(T[] array) => CopyTo(array, 0);

        public void CopyTo(int index, T[] array, int arrayIndex, int count)
        {
            T[] rowListArray = RowList.ToArray();
            if (rowListArray.Length - index < count)
                throw new ArgumentOutOfRangeException();
            Array.Copy(rowListArray, index, (Array) array, arrayIndex, count);
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            RowList.CopyTo(array, arrayIndex);
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/906794.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号