You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.2 KiB
129 lines
4.2 KiB
using Apewer.Internals;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace Apewer.Source
|
|
{
|
|
|
|
/// <summary>数据库中的表。</summary>
|
|
/// <remarks>
|
|
/// <para>Name: 数据库的表名。</para>
|
|
/// <para>Store: 数据存储区名称。</para>
|
|
/// </remarks>
|
|
[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;
|
|
|
|
/// <summary>标记表属性。</summary>
|
|
public TableAttribute(string name = null, string store = null)
|
|
{
|
|
_name = name.ToTrim();
|
|
_store = store.ToTrim();
|
|
}
|
|
|
|
/// <summary>表名。</summary>
|
|
public string Name { get => _name; }
|
|
|
|
/// <summary>存储名。</summary>
|
|
public string Store { get => _store; }
|
|
|
|
/// <summary>使用此特性的类型。</summary>
|
|
public Type Model { get => _model; }
|
|
|
|
/// <summary>模型实现了 <see cref="IRecordPrimaryKey"/> 接口。</summary>
|
|
public bool PrimaryKey { get => _primarykey; }
|
|
|
|
/// <summary>从 <see cref="TableAttribute"/> 到 Boolean 的隐式转换,判断 <see cref="TableAttribute"/> 有效。</summary>
|
|
public static implicit operator bool(TableAttribute instance)
|
|
{
|
|
if (instance == null) return false;
|
|
if (instance._name.IsEmpty()) return false;
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region 可修改特性
|
|
|
|
/// <summary>表的说明信息。(需要数据库客户端支持)</summary>
|
|
public string Description { get; set; }
|
|
|
|
/// <summary>独立结构,不依赖 Record 公共属性。</summary>
|
|
internal bool Independent { get; set; }
|
|
|
|
/// <summary>使用模型的所有属性,对缺少 Column 特性的属性使用默认参数的 Column 特性。</summary>
|
|
public bool AllProperties { get; set; }
|
|
|
|
#endregion
|
|
|
|
#region cache
|
|
|
|
private static Dictionary<string, TableAttribute> _tac = new Dictionary<string, TableAttribute>();
|
|
private static Type InterfacePrimaryKey = typeof(IRecordPrimaryKey);
|
|
|
|
/// <summary>解析表特性,默认使用缓存以提升性能。</summary>
|
|
public static TableAttribute Parse<T>(bool useCache = true) where T : class, new() => Parse(typeof(T), useCache);
|
|
|
|
/// <summary>解析表特性,默认使用缓存以提升性能。</summary>
|
|
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<IndependentAttribute>(type, true);
|
|
ta._primarykey = RuntimeUtility.IsInherits(type, InterfacePrimaryKey);
|
|
|
|
if (useCache)
|
|
{
|
|
lock (_tac)
|
|
{
|
|
if (!_tac.ContainsKey(cacheKey)) _tac.Add(cacheKey, ta);
|
|
}
|
|
}
|
|
|
|
return ta;
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|
|
|