/// <summary> /// 在表达式中查找关联查询的实体类型。 /// </summary> /// <param name="expression"></param> /// <returns></returns> internal static List <Type> Find(Expression expression) { var finder = new RelationshipFinder(); finder.Visit(expression); return(finder.types); }
/// <summary> /// 找出表达式中相关联的实体类型,进行关系维护 /// </summary> /// <param name="barrier">缓存隔离带。</param> /// <param name="key">缓存键。</param> /// <param name="cachePrefix"></param> /// <param name="expression"></param> private void Reference(string barrier, string key, Expression expression) { var types = RelationshipFinder.Find(expression); var rootKey = _serviceProvider.GetCacheKey($"{CACHE_KEY}.keys", barrier); var hashSet = _cacheMgr.GetHashSet <string, List <string> >(rootKey, checkExpiration: false); void process(string key, string subKey) { var keys = hashSet.TryGet(subKey, () => new List <string>()) ?? new List <string>(); if (!keys.Contains(key)) { keys.Add(key); hashSet.Add(subKey, keys); } } types.ForEach(s => { if (_cacheMgr is IEnhancedCacheManager ehCache) { ehCache.UseTransaction(string.Concat(rootKey, ":", s.FullName, ":Execute"), () => process(key, s.FullName), TimeSpan.FromSeconds(10)); } else { _locker.LockWrite(() => process(key, s.FullName)); } }); }
public TableModelMapper( IIdentifierDefaults identifierDefaults, IReadOnlyDictionary <Identifier, ulong> rowCounts, RelationshipFinder relationship ) { IdentifierDefaults = identifierDefaults ?? throw new ArgumentNullException(nameof(identifierDefaults)); RowCounts = rowCounts ?? throw new ArgumentNullException(nameof(rowCounts)); RelationshipFinder = relationship ?? throw new ArgumentNullException(nameof(relationship)); }
/// <summary> /// Spawns a entity in the gameworld. /// </summary> public static void SpawnEntity(EntityReferenceData entityReferenceData, Vector3 spawnPos) { Entity entity = BootStrapper.Entity_Manager.Instantiate (Database.Instance.GetDummyEntity(entityReferenceData.Value)); // Spawn the entity BootStrapper.Entity_Manager.SetComponentData(entity, new Position { Value = spawnPos }); // Set entitys position EntityColliders.AddEntityCollider(spawnPos, entity); // Spawn a collider for the entity RelationshipFinder.UpdateEntityRelationships(entity); }
/// <summary> /// 找出表达式中相关联的实体类型,进行关系维护 /// </summary> /// <param name="key">缓存键。</param> /// <param name="expression"></param> private static void Reference(string key, Expression expression) { var types = RelationshipFinder.Find(expression); foreach (var type in types) { if (referKeys.TryGetValue(type, out List <string> list)) { if (!list.Contains(key)) { list.Add(key); } } else { referKeys.GetOrAdd(type, () => new List <string> { key }); } } }
public async Task RenderAsync(CancellationToken cancellationToken = default) { var relationshipFinder = new RelationshipFinder(Tables); var mapper = new TableModelMapper(IdentifierDefaults, RowCounts, relationshipFinder); var graphvizFactory = new GraphvizExecutableFactory(); using var graphviz = graphvizFactory.GetExecutable(); var tableTasks = Tables.Select(async table => { var tableModel = mapper.Map(table); var outputPath = Path.Combine(ExportDirectory.FullName, table.Name.ToSafeKey() + ".html"); if (!ExportDirectory.Exists) { ExportDirectory.Create(); } XNamespace svgNs = "http://www.w3.org/2000/svg"; XNamespace xlinkNs = "http://www.w3.org/1999/xlink"; var dotRenderer = new DotSvgRenderer(graphviz.DotPath); foreach (var diagram in tableModel.Diagrams) { var svgFilePath = Path.Combine(ExportDirectory.FullName, diagram.ContainerId + ".svg"); var svg = await dotRenderer.RenderToSvgAsync(diagram.Dot, cancellationToken).ConfigureAwait(false); // ensure links open in new window with right attrs var doc = XDocument.Parse(svg, LoadOptions.PreserveWhitespace); doc.ReplaceTitlesWithTableNames(); var linkNodes = doc.Descendants(svgNs + "a"); foreach (var linkNode in linkNodes) { linkNode.SetAttributeValue("target", "_blank"); linkNode.SetAttributeValue("rel", "noopener noreferrer"); linkNode.SetAttributeValue(xlinkNs + "show", "new"); } using (var writer = new StringWriter()) { var svgRoot = doc.Root; svgRoot.Attribute("width")?.Remove(); svgRoot.Attribute("height")?.Remove(); svgRoot.Save(writer, SaveOptions.DisableFormatting); var svgText = writer.ToString(); if (svgText.StartsWith(XmlDeclaration)) { svgText = svgText.Substring(XmlDeclaration.Length); } diagram.Svg = svgText; } // disable links, replace them with a <g>, i.e. a dummy element linkNodes = doc.Descendants(svgNs + "a"); foreach (var linkNode in linkNodes) { linkNode.RemoveAttributes(); linkNode.Name = svgNs + "g"; } using (var writer = File.CreateText(svgFilePath)) doc.Save(writer, SaveOptions.DisableFormatting); } var renderedTable = await Formatter.RenderTemplateAsync(tableModel, cancellationToken).ConfigureAwait(false); var databaseName = !IdentifierDefaults.Database.IsNullOrWhiteSpace() ? IdentifierDefaults.Database + " Database" : "Database"; var pageTitle = table.Name.ToVisibleName() + " · Table · " + databaseName; var tableContainer = new Container(renderedTable, pageTitle, "../"); var renderedPage = await Formatter.RenderTemplateAsync(tableContainer, cancellationToken).ConfigureAwait(false); using (var writer = File.CreateText(outputPath)) { await writer.WriteAsync(renderedPage.AsMemory(), cancellationToken).ConfigureAwait(false); await writer.FlushAsync().ConfigureAwait(false); } }); await Task.WhenAll(tableTasks).ConfigureAwait(false); }