using System; using System.Collections.Generic; using System.Text; using log4net; using Quadarax.Foundation.Common.Object; using StructureMap; namespace Quadarax.Foundation.Infrastructure.Layers { public abstract class Layer : DisposableObject { private IContainer _container; private IList _childLayers = new List(); private Layer _parentLayer; protected ILog Log { get; } public string Name { get; } public int ChildLayersCount => _childLayers.Count; public LayerClassificationEnum LayerType { get; protected set; } protected Layer(string name, Layer parentLayer = null) { if (string.IsNullOrEmpty(name)) throw new ArgumentNullException(nameof(name), "Infrastucture layer must have a name."); _parentLayer = parentLayer; Log = LogManager.GetLogger(GetType()); Name = name; InitializeInternal(); Log.Info($"Layer '{Name}' fully created."); } private void InitializeInternal() { _container = _parentLayer == null ? new Container() : _parentLayer._container.CreateChildContainer(); OnModuleRegistry(_container); OnLayerRegistry(); Log.Info($"Layer '{Name}' initialization done"); } protected void AddChildLayer(Layer layer) { if (layer==null) throw new ArgumentNullException(nameof(layer)); _childLayers.Add(layer); Log.Info($"Layer 'Name' append child layer '{layer.Name}'. Current child count on layer '{Name}' is {ChildLayersCount} childs."); } protected abstract void OnLayerRegistry(); protected abstract void OnModuleRegistry(IContainer container); protected override void OnDisposing() { _parentLayer?.Dispose(); _parentLayer = null; if (_childLayers != null) { foreach (var layer in _childLayers) { layer.Dispose(); } } Log.Info($"Layer '{Name}' disposed."); } public TModule Get() where TModule : IModule { return _container.GetInstance(); } public string Dump() { var sb = new StringBuilder(); sb.Append("*** Layer: ").Append(Name).Append(" [").Append(LayerType).Append("] * BEGIN ***").AppendLine(); sb.Append("Parent:").AppendLine(); sb.Append(_parentLayer == null ? "none" : _parentLayer.Name); sb.AppendLine(); sb.Append("Childs:").AppendLine(); foreach (var child in _childLayers) sb.Append(child.Dump()).AppendLine(); sb.Append("*** Layer: ").Append(Name).Append(" [").Append(LayerType).Append("] * END ***").AppendLine(); return sb.ToString(); } } }