| File: System\ComponentModel\NestedContainer.cs | Web Access |
| Project: src\runtime\src\libraries\System.ComponentModel.TypeConverter\src\System.ComponentModel.TypeConverter.csproj (System.ComponentModel.TypeConverter) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; using System.Globalization; namespace System.ComponentModel { /// <summary> /// A nested container is a container that is owned by another component. Nested /// containers can be found by querying a component site's services for NestedConainter. /// Nested containers are a useful tool to establish owner relationships among components. /// All components within a nested container are named with the owning component's name /// as a prefix. /// </summary> public class NestedContainer : Container, INestedContainer { /// <summary> /// Creates a new NestedContainer. /// </summary> public NestedContainer(IComponent owner) { ArgumentNullException.ThrowIfNull(owner); Owner = owner; Owner.Disposed += new EventHandler(OnOwnerDisposed); } /// <summary> /// The component that owns this nested container. /// </summary> public IComponent Owner { get; } /// <summary> /// Retrieves the name of the owning component. This may be overridden to /// provide a custom owner name. The default searches the owner's site for /// INestedSite and calls FullName, or ISite.Name if there is no nested site. /// If neither is available, this returns null. /// </summary> protected virtual string? OwnerName { get { string? ownerName = null; if (Owner != null && Owner.Site != null) { if (Owner.Site is INestedSite nestedOwnerSite) { ownerName = nestedOwnerSite.FullName; } else { ownerName = Owner.Site.Name; } } return ownerName; } } /// <summary> /// Creates a site for the component within the container. /// </summary> protected override ISite CreateSite(IComponent component, string? name) { ArgumentNullException.ThrowIfNull(component); return new Site(component, this, name); } /// <summary> /// Override of Container's dispose. /// </summary> protected override void Dispose(bool disposing) { if (disposing) { Owner.Disposed -= new EventHandler(OnOwnerDisposed); } base.Dispose(disposing); } protected override object? GetService(Type service) { if (service == typeof(INestedContainer)) { return this; } else { return base.GetService(service); } } /// <summary> /// Called when our owning component is destroyed. /// </summary> private void OnOwnerDisposed(object? sender, EventArgs e) => Dispose(); /// <summary> /// Simple site implementation. We do some special processing to name the site, but /// that's about it. /// </summary> private sealed class Site : INestedSite { private string? _name; internal Site(IComponent component, NestedContainer container, string? name) { Component = component; Container = container; _name = name; } // The component sited by this component site. public IComponent Component { get; } // The container in which the component is sited. public IContainer Container { get; } public object? GetService(Type service) { return ((service == typeof(ISite)) ? this : ((NestedContainer)Container).GetService(service)); } // Indicates whether the component is in design mode. public bool DesignMode { get { IComponent owner = ((NestedContainer)Container).Owner; if (owner != null && owner.Site != null) { return owner.Site.DesignMode; } return false; } } public string? FullName { get { if (_name != null) { string? ownerName = ((NestedContainer)Container).OwnerName; string childName = _name; if (ownerName != null) { childName = ownerName + "." + childName; } return childName; } return _name; } } // The name of the component. public string? Name { get => _name; [RequiresUnreferencedCode("The Type of components in the container cannot be statically discovered to validate the name.")] set { if (value == null || _name == null || !value.Equals(_name)) { ((NestedContainer)Container).ValidateName(Component, value); _name = value; } } } } } }