using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Text;
namespace Apewer.Source
{
/// 数据库中的表。
///
/// Name: 数据库的表名。
/// Store: 数据存储区名称。
///
[Serializable]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
public sealed class TableAttribute : Attribute
{
#region 主要
private string _name = null;
private string _store = null;
private Type _model = null;
private bool _primarykey = false;
/// 标记表属性。
public TableAttribute(string name = null, string store = null)
{
_name = name.ToTrim();
_store = store.ToTrim();
}
/// 表名。
public string Name { get => _name; }
/// 存储名。
public string Store { get => _store; }
/// 使用此特性的类型。
public Type Model { get => _model; }
/// 模型实现了 接口。
public bool PrimaryKey { get => _primarykey; }
/// 从 到 Boolean 的隐式转换,判断 有效。
public static implicit operator bool(TableAttribute instance)
{
if (instance == null) return false;
if (instance._name.IsEmpty()) return false;
return true;
}
#endregion
#region 可修改特性
/// 表的说明信息。(需要数据库客户端支持)
public string Description { get; set; }
/// 独立结构,不依赖 Record 公共属性。
internal bool Independent { get; set; }
/// 使用模型的所有属性,对缺少 Column 特性的属性使用默认参数的 Column 特性。
public bool AllProperties { get; set; }
#endregion
#region cache
private static Dictionary _tac = new Dictionary();
private static Type InterfacePrimaryKey = typeof(IRecordPrimaryKey);
/// 解析表特性,默认使用缓存以提升性能。
public static TableAttribute Parse(bool useCache = true) where T : class, new() => Parse(typeof(T), useCache);
/// 解析表特性,默认使用缓存以提升性能。
public static TableAttribute Parse(Type type, bool useCache = true, bool force = false)
{
if (type == null) return null;
var cacheKey = type.FullName;
if (useCache)
{
var hint = null as TableAttribute;
lock (_tac)
{
if (_tac.ContainsKey(cacheKey)) hint = _tac[cacheKey];
}
if (hint != null) return hint;
}
if (!type.IsClass) return null;
if (type.IsAbstract) return null;
// throw new Exception($"类型 {type.FullName} 不包含 {typeof(TableAttribute).FullName}。");
var tas = type.GetCustomAttributes(typeof(TableAttribute), false);
var ta = null as TableAttribute;
var exists = tas.Length > 0;
if (exists) ta = (TableAttribute)tas[0];
else
{
if (!force) return null;
ta = new TableAttribute();
ta.AllProperties = true;
ta.Independent = true;
}
ta._model = type;
if (string.IsNullOrEmpty(ta.Name)) ta._name = type.Name;
ta.Independent = RuntimeUtility.Contains(type, true);
ta._primarykey = RuntimeUtility.IsInherits(type, InterfacePrimaryKey);
if (useCache)
{
lock (_tac)
{
if (!_tac.ContainsKey(cacheKey)) _tac.Add(cacheKey, ta);
}
}
return ta;
}
#endregion
}
}