namespace NewLife.Data;
/// <summary>具有可读写的扩展数据(仅扩展属性,不含基本属性)</summary>
/// <remarks>
/// 用于在对象上携带“非模型/非常规”属性的数据字典,区别于 <see cref="IModel"/> 的“模型属性”访问。
/// - 常用于网络会话、上下文对象等需要按需挂载临时数据的场景
/// - 推荐实现为永不为 null 的字典;高频场景可选用可空字典以避免 KeyNotFoundException
/// - 约定:索引读取缺失键时应返回 null,而非抛出异常
/// - 线程安全由实现方自行保证(如必要可使用并发字典)
/// </remarks>
public interface IExtend
{
/// <summary>扩展数据项字典</summary>
/// <remarks>
/// 建议返回非空实例,避免调用方判空;具体大小写敏感性由实现决定(建议 OrdinalIgnoreCase)。
/// </remarks>
IDictionary<String, Object?> Items { get; }
/// <summary>设置 或 获取 扩展数据项</summary>
/// <param name="key">扩展数据键</param>
/// <returns>存在则返回对应值;未命中应返回 null</returns>
/// <remarks>典型实现可直接代理到 <see cref="Items"/>:get 使用 TryGetValue,set 直接赋值。</remarks>
Object? this[String key] { get; set; }
}
///// <summary>扩展数据助手</summary>
//public static class ExtendHelper
//{
// /// <summary>名值字典转扩展接口</summary>
// /// <param name="dictionary">字典</param>
// /// <returns></returns>
// public static IExtend ToExtend(this IDictionary<String, Object> dictionary)
// {
// if (dictionary is IExtend ext) return ext;
// return new ExtendDictionary { Items = dictionary };
// }
// /// <summary>扩展接口转名值字典</summary>
// /// <remarks>
// /// 需要注意,还有一个 Object.ToDictionary() 扩展,位于 CollectionHelper
// /// </remarks>
// /// <param name="extend">扩展对象</param>
// /// <returns></returns>
// public static IDictionary<String, Object> ToDictionary(this IExtend extend)
// {
// if (extend == null) return null;
// // 泛型字典
// if (extend is IDictionary<String, Object> dictionary) return dictionary;
// if (extend is ExtendDictionary edic) return edic.Items;
// if (extend is IExtend3 ext3) return ext3.Items;
// //// IExtend2
// //if (extend is IExtend2 ext2 && ext2.Keys != null)
// //{
// // var dic = new Dictionary<String, Object>();
// // foreach (var item in ext2.Keys)
// // {
// // dic[item] = extend[item];
// // }
// // return dic;
// //}
// // 普通字典
// if (extend is IDictionary dictionary2)
// {
// var dic = new Dictionary<String, Object>();
// foreach (DictionaryEntry item in dictionary2)
// {
// dic[item.Key + ""] = item.Value;
// }
// return dic;
// }
// // 反射 Items
// var pis = extend.GetType().GetProperties(true);
// var pi = pis.FirstOrDefault(e => e.Name == "Items");
// if (pi != null && pi.PropertyType.As<IDictionary<String, Object>>()) return pi.GetValue(extend, null) as IDictionary<String, Object>;
// // 反射属性
// return new ExtendDictionary2 { Data = extend, Keys = pis.Select(e => e.Name).ToList() };
// //var dic2 = new Dictionary<String, Object>();
// //foreach (var item in pis)
// //{
// // dic2[item.Name] = extend[item.Name];
// //}
// //return dic2;
// }
// /// <summary>从源对象拷贝数据到目标对象</summary>
// /// <param name="target">目标对象</param>
// /// <param name="source">源对象</param>
// public static void Copy(this IExtend target, IExtend source)
// {
// var dst = target.ToDictionary();
// var src = source.ToDictionary();
// foreach (var item in src)
// {
// if (dst.ContainsKey(item.Key)) dst[item.Key] = item.Value;
// }
// }
//}
///// <summary>扩展字典。引用型</summary>
//public class ExtendDictionary : IExtend, /*IExtend2,*/ IExtend3
//{
// /// <summary>数据项</summary>
// public IDictionary<String, Object> Items { get; set; }
// //IEnumerable<String> IExtend2.Keys => Items?.Keys;
// /// <summary>获取 或 设置 数据</summary>
// /// <param name="item"></param>
// /// <returns></returns>
// public Object this[String item]
// {
// get
// {
// if (Items == null) return null;
// if (Items.TryGetValue(item, out var v)) return v;
// return default;
// }
// set
// {
// if (Items == null) Items = new Dictionary<String, Object>();
// Items[item] = value;
// }
// }
//}
//internal class ExtendDictionary2 : IDictionary<String, Object>
//{
// public IExtend Data { get; set; }
// public ICollection<String> Keys { get; set; }
// public Object this[String key] { get => Data[key]; set => Data[key] = value; }
// public ICollection<Object> Values => Keys.Select(e => Data[e]).ToList();
// public Int32 Count => Keys.Count;
// public Boolean IsReadOnly => false;
// public void Add(String key, Object value) => throw new NotImplementedException();
// public void Add(KeyValuePair<String, Object> item) => throw new NotImplementedException();
// public void Clear() => throw new NotImplementedException();
// public Boolean Contains(KeyValuePair<String, Object> item) => Keys.Contains(item.Key);
// public Boolean ContainsKey(String key) => Keys.Contains(key);
// public void CopyTo(KeyValuePair<String, Object>[] array, Int32 arrayIndex) => throw new NotImplementedException();
// public IEnumerator<KeyValuePair<String, Object>> GetEnumerator()
// {
// foreach (var item in Keys)
// {
// yield return new KeyValuePair<String, Object>(item, Data[item]);
// }
// }
// public Boolean Remove(String key) => throw new NotImplementedException();
// public Boolean Remove(KeyValuePair<String, Object> item) => throw new NotImplementedException();
// public Boolean TryGetValue(String key, out Object value)
// {
// if (Keys.Contains(key))
// {
// value = Data[key];
// return true;
// }
// else
// {
// value = null;
// return false;
// }
// }
// IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
//}
|