IServiceContainerとは? わかりやすく解説

IServiceContainer インターフェイス

サービスコンテナ提供します

名前空間: System.ComponentModel.Design
アセンブリ: System (system.dll 内)
構文構文

<ComVisibleAttribute(True)> _
Public Interface IServiceContainer
    Inherits IServiceProvider
Dim instance As IServiceContainer
[ComVisibleAttribute(true)] 
public interface IServiceContainer : IServiceProvider
[ComVisibleAttribute(true)] 
public interface class IServiceContainer :
 IServiceProvider
/** @attribute ComVisibleAttribute(true) */ 
public interface IServiceContainer extends IServiceProvider
ComVisibleAttribute(true) 
public interface IServiceContainer extends
 IServiceProvider
解説解説

定義上、サービス コンテナサービス プロバイダとなりますサービス コンテナサービス提供するだけでなく、サービス追加および削除するための機構提供しますサービスは、.NET Framework デザインアーキテクチャ基盤となるものです。サービスによって、デザインオブジェクトが、サービス提供するサービス オブジェクトによって実装されている特定の機能メソッドアクセスできるようになります

デザイン時にサービス取得するには、デザイン モードにあるコンポーネントの GetService メソッド呼び出します。デザイナその他のオブジェクトは、IDesignerHost インターフェイス使用してデザイン時にサービス追加または削除できます

サービス コンテナは、他のサービス コンテナ含まれる場合もあり、そのようにしてサービス コンテナツリー構造形成されます。既定では、IServiceContainer インターフェイスは、一番近いサービス コンテナサービス追加しますサービス追加されるときには、そのサービス昇格要求する指示追加されます。サービス昇格されると、そのサービス任意のサービス コンテナ追加されサービス コンテナ ツリー最上位達するまで続けて追加されいきます。これにより、デザイナでは、プロセス内の他のオブジェクト使用できるグローバル サービス提供できるようになります

使用例使用例

リンクされサービス コンテナネットワーク動作を示すように構成されFormコード例次に示します

Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.ComponentModel.Design
Imports System.Windows.Forms
Imports System.Windows.Forms.Design

' This sample contains a Form class that is configured to demonstrate
 
' the behavior of a network of linked service containers.   

' Notes regarding this IServiceContainer and IServiceProvider implementation:
'
' When implementing the IServiceContainer interface, you may want to
 
' implement support for a linked service container system
' which enables access to and sharing of services throughout a 
' container tree or network.
'
' To effectively share a service, a GetService, AddService or 
' RemoveService method must be able to locate a service 
' that has been added to a shared service container tree or network.
'        
' One simple approach to sharing services, suitable for container networks
 
' where each container has one parent and the tree has
' one parentless container, is to store services only at the top node
 
' (the root or grandparent) of a tree.
'
' To store services in the root node of a tree, two types of 
' consistencies must be maintained in the implementation:        
'
'   >   The GetService, AddService and RemoveService implementations
 
'       must access the root through some mechanism.
'         The ServiceContainerControl's implementations of these 
'         standard IServiceContainer methods call 
'         the same method of a parent container, if the container 
'         has been parented, to route methods to the root.  
'
'   >   The services must be maintained at the root of the tree;
 
'       therefore any new child's services should be copied to the root.
                

' ServiceContainerControl provides an example user control implmentation
 
' of the IServiceContainer interface. This implementation of 
' IServiceContainer supports a root-node linked service distribution,
 
' access and removal architecture.
Public Class ServiceContainerControl
    Inherits System.Windows.Forms.UserControl
    Implements IServiceContainer

    ' List of service instances sorted by key of service type's full
 name.
    Private localServices As SortedList
    ' List contains the Type for each service sorted by each service
 type's full name.
    Private localServiceTypes As SortedList

    ' The parent IServiceContainer, or null.
    Private parentServiceContainer As IServiceContainer

    Public Property serviceParent() As
 IServiceContainer
        Get
            Return parentServiceContainer
        End Get
        Set(ByVal Value As
 IServiceContainer)
            parentServiceContainer = Value
            ' Move any services to parent.
            Dim i As Integer
            For i = 0 To localServices.Count
 - 1
                parentServiceContainer.AddService( _
                    CType(localServiceTypes.GetByIndex(i), Type), _
                    localServices.GetByIndex(i))
            Next i
            localServices.Clear()
            localServiceTypes.Clear()
        End Set
    End Property

    ' The current state of the control, reflecting whether it has 
    ' obtained or provided a text service.
    Private state_ As TextServiceState

    Public Property state() As
 TextServiceState
        Get
            Return state_
        End Get
        Set(ByVal Value As
 TextServiceState)
            If CType(Value, TextServiceState) = _
                    TextServiceState.ServiceProvided Then
                Me.BackColor = Color.LightGreen
            ElseIf CType(Value, TextServiceState) = _
                    TextServiceState.ServiceNotObtained Then
                Me.BackColor = Color.White
            ElseIf CType(Value, TextServiceState) = _
                    TextServiceState.ServiceObtained Then
                Me.BackColor = Color.LightBlue
            ElseIf CType(Value, TextServiceState) = _
                    TextServiceState.ServiceNotFound Then
                Me.BackColor = Color.SeaShell
            End If
            state_ = Value
        End Set
    End Property

    ' Parent form reference for main program function access.
    Private Shadows parent As
 ServiceForm
    ' String for label displayed on the control to indicate 
    ' the control's current service-related configuration state.
    Public label As String

    Public Sub New(ByVal
 size As Size, ByVal location As
 Point, _
                    ByVal parent As ServiceForm)
        MyClass.New(Nothing, size, location,
 parent)
    End Sub

    Public Sub New(ByVal
 ParentServiceContainer As IServiceContainer, _
        ByVal size As Size, ByVal
 location As Point, ByVal parent As
 ServiceForm)

        Me.state_ = TextServiceState.ServiceNotObtained
        localServices = New SortedList()
        localServiceTypes = New SortedList()

        Me.BackColor = Color.Beige
        Me.label = String.Empty
        Me.Size = size
        Me.Location = location
        Me.parent = parent
        Me.serviceParent = ParentServiceContainer

        ' If a parent is specified, set the parent property of this
 
        ' linkable IServiceContainer implementation.
        If Not (ParentServiceContainer Is
 Nothing) Then
            serviceParent = ParentServiceContainer
        End If
    End Sub

    ' IServiceProvider.GetService implementation for a linked 
    ' service container architecture.
    Public Shadows Function
 GetService(ByVal serviceType As System.Type)
 As Object Implements IServiceProvider.GetService
        If Not (parentServiceContainer Is
 Nothing) Then
            Return parentServiceContainer.GetService(serviceType)
        End If
        Dim serviceInstance As Object
 = localServices(serviceType.FullName)
        If serviceInstance Is Nothing
 Then
            Return Nothing
        ElseIf serviceInstance.GetType() Is
 GetType(ServiceCreatorCallback) Then
            ' If service instance is a ServiceCreatorCallback, invoke
 it to create the service
            Return CType(serviceInstance, ServiceCreatorCallback)(Me,
 serviceType)
        End If
        Return serviceInstance
    End Function

    ' IServiceContainer.AddService implementation for a linked 
    ' service container architecture.
    Public Overloads Sub
 AddService(ByVal serviceType As System.Type,
 ByVal callback As System.ComponentModel.Design.ServiceCreatorCallback, ByVal promote As
 Boolean) Implements IServiceContainer.AddService
        If promote AndAlso Not
 (parentServiceContainer Is Nothing) Then
            parentServiceContainer.AddService(serviceType, callback, True)
        Else
            localServiceTypes(serviceType.FullName) = serviceType
            localServices(serviceType.FullName) = callback
        End If
    End Sub

    ' IServiceContainer.AddService implementation for a linked 
    ' service container architecture.
    Public Overloads Sub
 AddService(ByVal serviceType As System.Type,
 _
        ByVal callback As System.ComponentModel.Design.ServiceCreatorCallback)
 _
        Implements IServiceContainer.AddService
        AddService(serviceType, callback, True)
    End Sub

    ' IServiceContainer.AddService implementation for a linked 
    ' service container architecture.
    Public Overloads Sub
 AddService(ByVal serviceType As System.Type,
 _
        ByVal serviceInstance As Object,
 ByVal promote As Boolean)
 _
        Implements IServiceContainer.AddService
        If promote AndAlso Not
 (parentServiceContainer Is Nothing) Then
            parentServiceContainer.AddService(serviceType, serviceInstance, True)
        Else
            localServiceTypes(serviceType.FullName) = serviceType
            localServices(serviceType.FullName) = serviceInstance
        End If
    End Sub

    ' IServiceContainer.AddService (defaults to promote service addition).
    Public Overloads Sub
 AddService(ByVal serviceType As System.Type,
 _
        ByVal serviceInstance As Object)
 Implements IServiceContainer.AddService
        AddService(serviceType, serviceInstance, True)
    End Sub

    ' IServiceContainer.RemoveService implementation for a linked 
    ' service container architecture.
    Public Overloads Sub
 RemoveService(ByVal serviceType As System.Type,
 _
        ByVal promote As Boolean)
 Implements IServiceContainer.RemoveService
        If Not (localServices(serviceType.FullName)
 Is Nothing) Then
            localServices.Remove(serviceType.FullName)
            localServiceTypes.Remove(serviceType.FullName)
        End If
        If promote Then
            If Not (parentServiceContainer Is
 Nothing) Then
                parentServiceContainer.RemoveService(serviceType)
            End If
        End If
    End Sub

    ' IServiceContainer.RemoveService (defaults to promote service removal)
    Public Overloads Sub
 RemoveService(ByVal serviceType As System.Type)
 _
        Implements IServiceContainer.RemoveService
        RemoveService(serviceType, True)
    End Sub

    ' Paint method override draws the label string on the control.
    Protected Overrides Sub
 OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        e.Graphics.DrawString(label, New Font("Arial",
 8), New SolidBrush(Color.Black), 5, 5)
    End Sub

    ' Process mouse-down behavior for click.
    Protected Overrides Sub
 OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)

        '  This example control responds to mouse clicks as follows:
        '
        '      Left click - control attempts to obtain a text service
 
        '      and sets its label text to the text provided by the service
        '      Right click - if the control has already provided a text
 
        '      service, this control does nothing. Otherwise, the control
 
        '      shows a dialog to specify text to provide as a new text
 
        '      service, after clearing the tree's services.

        If e.Button = System.Windows.Forms.MouseButtons.Left Then
            If state_ <> TextServiceState.ServiceProvided
 Then
                ' Attempt to update text from the service, and set 
                ' color state accordingly.
                Dim ts As TextService = CType(GetService(GetType(TextService)),
 TextService)
                If Not (ts Is
 Nothing) Then
                    Me.label = ts.text
                    state = TextServiceState.ServiceObtained
                Else
                    Me.label = "Service Not
 Found"
                    state = TextServiceState.ServiceNotFound
                End If
            End If
        End If
        If e.Button = System.Windows.Forms.MouseButtons.Right
 Then
            If state_ = TextServiceState.ServiceProvided Then
                ' Remove the service the if the container provided it.
                If Not (GetService(GetType(TextService))
 Is Nothing) Then
                    RemoveService(GetType(TextService), True)
                    state = TextServiceState.ServiceNotObtained
                    Me.label = "Service Removed"
                End If
            Else
                ' Obtain string and provide text service.
                Dim form As New
 StringInputDialog("Test String")
                form.StartPosition = FormStartPosition.CenterParent
                If form.ShowDialog() = DialogResult.OK Then
                    If Not (GetService(GetType(TextService))
 Is Nothing) Then
                        RemoveService(GetType(TextService), True)
                    End If
                    parent.ResetServiceTree(Me, New
 EventArgs())

                    AddService(GetType(TextService), _
                        New TextService(form.inputTextBox.Text),
 True) 

                    ' The following commented method uses a service
 creator callback.
                    ' AddService(typeof(TextService), 
                    '   new ServiceCreatorCallback(this.CreateTextService));
                                                
                    state = TextServiceState.ServiceProvided
                    Me.label = "Provided Text:
 " + form.inputTextBox.Text
                End If
            End If
        End If
        parent.UpdateServiceCoverage()
    End Sub

    ' Method accesses the TextService to test the visibility of the
 service 
    ' from the control, and sets the UI state accordingly.
    Public Sub ReflectServiceVisibility()
        If state_ = TextServiceState.ServiceObtained Then
            If GetService(GetType(TextService))
 Is Nothing Then
                Me.BackColor = Color.CadetBlue
            End If
        ElseIf state_ <> TextServiceState.ServiceProvided
 Then
            If GetService(GetType(TextService))
 Is Nothing Then
                Me.BackColor = Color.White
                Return
            End If

            ' Service available.    
            If state_ = TextServiceState.ServiceNotFound Then
                Me.BackColor = Color.Khaki
            ElseIf state_ = TextServiceState.ServiceNotObtained
 _
                AndAlso label <> "Service
 Removed" Then
                Me.BackColor = Color.Khaki
            End If
        End If
    End Sub

    ' ServiceCreatorCallback method creates a text service.
    Private Function CreateTextService(ByVal
 container As IServiceContainer, _
        ByVal serviceType As System.Type) As
 Object
        Return New TextService("Test
 Callback")
    End Function
End Class

' Example form provides UI for demonstrating service sharing behavior
 
' of a network of IServiceContainer/IServiceProvider controls.
Public Class ServiceForm
    Inherits System.Windows.Forms.Form
    
    ' Root service container control for tree.
    Private root As ServiceContainerControl
  
    ' Button for clearing any provided services and resetting tree states.
    Private WithEvents reset_button As
 System.Windows.Forms.Button 
    ' Color list used to color code controls.
    Private colorkeys() As Color
    Private keystrings() As String
    ' Strings used to reflect text service 
    Public Sub New()
        InitializeComponent()
        colorkeys = New Color() {Color.Beige, Color.SeaShell,
 _
            Color.LightGreen, Color.LightBlue, Color.Khaki, Color.CadetBlue}
        keystrings = New String() {"No
 service use", "Service not accessible",
 _
            "Service provided", "Service
 obtained", "Service accessible", _
            "No further access"}
        CreateServiceControlTree()
    End Sub

    Private Sub CreateServiceControlTree()
        ' Create root service control
        Dim control1 As New
 ServiceContainerControl(Nothing, New Size(300,
 40), New Point(10, 80), Me)
        root = control1
        ' Create first tier - pass parent with service object control
 1.
        Dim control2 As New
 ServiceContainerControl(control1, New Size(200, 30), New
 Point(50, 160), Me)
        Dim control3 As New
 ServiceContainerControl(control1, New Size(200, 30), New
 Point(50, 240), Me)
        ' Create second tier A - pass parent with service object control
 2.
        Dim control4 As New
 ServiceContainerControl(control2, New Size(180, 20), New
 Point(300, 145), Me)
        Dim control5 As New
 ServiceContainerControl(control2, New Size(180, 20), New
 Point(300, 185), Me)
        ' Create second tier B - pass parent with service object control
 3.
        Dim control6 As New
 ServiceContainerControl(control3, New Size(180, 20), New
 Point(300, 225), Me)
        Dim control7 As New
 ServiceContainerControl(control3, New Size(180, 20), New
 Point(300, 265), Me)
        ' Add controls
        Me.Controls.AddRange(New Control()
 {control1, control2, control3, control4, control5, control6, control7})
    End Sub

    Friend Sub ResetServiceTree(ByVal
 sender As Object, ByVal
 e As EventArgs) Handles reset_button.Click
        ' Remove the service from the service tree.
        If Not (root.GetService(GetType(TextService))
 Is Nothing) Then
            root.RemoveService(GetType(TextService), True)
        End If
        ' Set all controls to "not obtained" and clear their
 labels.
        Dim i As Integer
        For i = 0 To Controls.Count - 1
            If Not Controls(i).Equals(reset_button)
 Then
                CType(Controls(i), ServiceContainerControl).state = TextServiceState.ServiceNotObtained
                CType(Controls(i), ServiceContainerControl).label = String.Empty
                CType(Controls(i), ServiceContainerControl).BackColor = Color.Beige
            End If
        Next i
    End Sub

    Public Sub UpdateServiceCoverage()
        ' Have each control set state to reflect service availability.
        Dim i As Integer
        For i = 0 To Controls.Count - 1
            If Not Controls(i).Equals(reset_button)
 Then
                CType(Controls(i), ServiceContainerControl).ReflectServiceVisibility()
            End If
        Next i
    End Sub

    Private Sub InitializeComponent()
        Me.reset_button = New System.Windows.Forms.Button()
        Me.SuspendLayout()
        ' 
        ' reset_button
        ' 
        Me.reset_button.Location = New System.Drawing.Point(392,
 88)
        Me.reset_button.Name = "reset_button"
        Me.reset_button.TabIndex = 0
        Me.reset_button.TabStop = False
        Me.reset_button.Text = "Reset"
        ' 
        ' ServiceForm
        ' 
        Me.ClientSize = New System.Drawing.Size(512,
 373)
        Me.Controls.AddRange(New System.Windows.Forms.Control()
 {Me.reset_button})
        Me.MinimumSize = New System.Drawing.Size(520,
 400)
        Me.Name = "ServiceForm"
        Me.Text = "Service Container Architecture
 Example"
        Me.ResumeLayout(False)
    End Sub

    <STAThread()> _
    Shared Sub Main()
        Application.Run(New ServiceForm())
    End Sub

    Protected Overrides Sub
 OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        e.Graphics.DrawString("The following tree diagram represents
 a hierarchy of linked service containers in controls.", New
 Font("Arial", 9), New SolidBrush(Color.Black), 4, 4)
        e.Graphics.DrawString("This example demonstrates the propagation
 behavior of services through a linked service object tree.", New
 Font("Arial", 8), New SolidBrush(Color.Black), 4, 26)
        e.Graphics.DrawString("Right-click a component to add
 or replace a text service, or to remove it if the component provided it.",
 New Font("Arial", 8), New SolidBrush(Color.Black), 4, 38)
        e.Graphics.DrawString("Left-click a component to update
 text from the text service if available.", New Font("Arial",
 8), New SolidBrush(Color.Black), 4, 50)

        ' Draw lines to represent tree branches.
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 20, 125, 20, 258)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 21, 175, 45, 175)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 21, 258, 45, 258)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 255, 175, 285, 175)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 255, 258, 285, 258)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 285, 155, 285, 195)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 285, 238, 285, 278)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 285, 155, 290, 155)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 285, 195, 290, 195)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 285, 238, 290, 238)
        e.Graphics.DrawLine(New Pen(New SolidBrush(Color.Black),
 1), 285, 278, 290, 278)

        ' Draw color key.
        e.Graphics.DrawRectangle(New Pen(New
 SolidBrush(Color.Black), 1), 20, 305, 410, 60)
        Dim y As Integer
 = 0
        Dim i As Integer
        For i = 0 To 2
            e.Graphics.FillRectangle(New SolidBrush(colorkeys(y)),
 _
                25 + i * 140, 310, 20, 20)
            e.Graphics.DrawRectangle(New Pen(New
 SolidBrush(Color.Black), 1), _
                25 + i * 140, 310, 20, 20)
            e.Graphics.DrawString(keystrings(y), New Font("Arial",
 8), _
                New SolidBrush(Color.Black), 50 + i * 140, 315)
            y += 1
            e.Graphics.FillRectangle(New SolidBrush(colorkeys(y)),
 _
                25 + i * 140, 340, 20, 20)
            e.Graphics.DrawRectangle(New Pen(New
 SolidBrush(Color.Black), 1), _
                25 + i * 140, 340, 20, 20)
            e.Graphics.DrawString(keystrings(y), New Font("Arial",
 8), _
                New SolidBrush(Color.Black), 50 + i * 140, 345)
            y += 1
        Next i
    End Sub
End Class

' Example service type contains a text string, sufficient to 
' demonstrate service sharing.
Public Class TextService
    Public [text] As String

    Public Sub New()
        MyClass.New(String.Empty)
    End Sub

    Public Sub New(ByVal
 [text] As String)
        Me.text = [text]
    End Sub
End Class

Public Enum TextServiceState
    ServiceNotObtained
    ServiceObtained
    ServiceProvided
    ServiceNotFound
End Enum

' Example Form for entering a string.
Friend Class StringInputDialog
    Inherits System.Windows.Forms.Form
    Private ok_button As System.Windows.Forms.Button
    Private cancel_button As System.Windows.Forms.Button
    Public inputTextBox As System.Windows.Forms.TextBox

    Public Sub New(ByVal
 [text] As String)
        InitializeComponent()
        inputTextBox.Text = [text]
    End Sub

    Private Sub InitializeComponent()
        Me.ok_button = New System.Windows.Forms.Button()
        Me.cancel_button = New System.Windows.Forms.Button()
        Me.inputTextBox = New System.Windows.Forms.TextBox()
        Me.SuspendLayout()
        Me.ok_button.Anchor = System.Windows.Forms.AnchorStyles.Bottom
 _
            Or System.Windows.Forms.AnchorStyles.Right
        Me.ok_button.Location = New System.Drawing.Point(180,
 43)
        Me.ok_button.Name = "ok_button"
        Me.ok_button.TabIndex = 1
        Me.ok_button.Text = "OK"
        Me.ok_button.DialogResult = System.Windows.Forms.DialogResult.OK
        Me.cancel_button.Anchor = System.Windows.Forms.AnchorStyles.Bottom
 _
            Or System.Windows.Forms.AnchorStyles.Right
        Me.cancel_button.Location = New System.Drawing.Point(260,
 43)
        Me.cancel_button.Name = "cancel_button"
        Me.cancel_button.TabIndex = 2
        Me.cancel_button.Text = "Cancel"
        Me.cancel_button.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.inputTextBox.Location = New System.Drawing.Point(6,
 9)
        Me.inputTextBox.Name = "inputTextBox"
        Me.inputTextBox.Size = New System.Drawing.Size(327,
 20)
        Me.inputTextBox.TabIndex = 0
        Me.inputTextBox.Text = ""
        Me.inputTextBox.Anchor = System.Windows.Forms.AnchorStyles.Top
 _
            Or System.Windows.Forms.AnchorStyles.Left Or
 _
            System.Windows.Forms.AnchorStyles.Right
        Me.ClientSize = New System.Drawing.Size(342,
 73)
        Me.Controls.AddRange(New System.Windows.Forms.Control()
 _
            {Me.inputTextBox, Me.cancel_button, Me.ok_button})
        Me.MinimumSize = New System.Drawing.Size(350,
 100)
        Me.Name = "StringInputDialog"
        Me.Text = "Text Service Provide String
 Dialog"
        Me.ResumeLayout(False)
    End Sub
End Class
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace ServiceArchitectureExample
{
    // This sample contains a Form class that is configured to demonstrate
 
    // the behavior of a network of linked service containers.   
    
    // Notes regarding this IServiceContainer and IServiceProvider 
    // implementation:
    //
    // When implementing the IServiceContainer interface, you may want
 to 
    // implement support for a linked service container system
    // which enables access to and sharing of services throughout a
 
    // container tree or network.
    //
    // To effectively share a service, a GetService, AddService or 
    // RemoveService method must be able to locate a service 
    // that has been added to a shared service container tree or network.
    //        
    // One simple approach to sharing services, suitable for container
 networks 
    // where each container has one parent and the tree has
    // one parentless container, is to store services only at the top
 node 
    // (the root or grandparent) of a tree.
    //
    // To store services in the root node of a tree, two types of 
    // consistencies must be maintained in the implementation:     
   
    //
    //   >   The GetService, AddService and RemoveService implementations
 
    //       must access the root through some mechanism.
    //         The ServiceContainerControl's implementations of these
 
    //         standard IServiceContainer methods call 
    //         the same method of a parent container, if the container
 
    //         has been parented, to route methods to the root.  
    //
    //   >   The services must be maintained at the root of the tree;
 
    //       therefore, any new child's services should be copied to
 the root.                


    // ServiceContainerControl provides an example user control implmentation
 
    // of the IServiceContainer interface. This implementation of 
    // IServiceContainer supports a root-node linked service distribution,
 
    // access. and removal architecture.
    public class ServiceContainerControl :
 System.Windows.Forms.UserControl, IServiceContainer
    {                        
        // List of service instances sorted by key of service type's
 full name.
        private SortedList localServices;               
        // List that contains the Type for each service sorted by each
 
        // service type's full name.
        private SortedList localServiceTypes;           

        // The parent IServiceContainer, or null.
        private IServiceContainer parentServiceContainer;   
        public IServiceContainer serviceParent              
        {
            get
            {
                return parentServiceContainer;
            }
            set
            {
                parentServiceContainer = value;
                // Move any services to parent.
                for( int i=0; i<localServices.Count;
 i++ )
                    parentServiceContainer.AddService(
                        (Type)localServiceTypes.GetByIndex(i), 
                        localServices.GetByIndex(i));
                localServices.Clear();
                localServiceTypes.Clear();
            }
        }
        
        // The current state of the control reflecting whether it has
 
        // obtained or provided a text service.
        private TextServiceState state_;
        public TextServiceState state              
        {                                          
            get
            {
                return state_;
            }
            set
            {
                if( (TextServiceState)value == 
                        TextServiceState.ServiceProvided )
                    this.BackColor = Color.LightGreen;
                else if( (TextServiceState)value
 == 
                        TextServiceState.ServiceNotObtained )                
                    this.BackColor = Color.White;            
                       
                else if( (TextServiceState)value
 == 
                        TextServiceState.ServiceObtained )
                    this.BackColor = Color.LightBlue;
                else if( (TextServiceState)value
 == 
                        TextServiceState.ServiceNotFound )                      
              
                    this.BackColor = Color.SeaShell;         
       
                state_ = value;
            }
        }
        
        // Parent form reference for main program function access.
        private ServiceForm parent;                 
        // String for label displayed on the control to indicate 
        // the control's current service-related configuration state.
        public string label;  
        
        public ServiceContainerControl(Size size, Point location,
 
            ServiceForm parent) : this(null,
 size, location, parent){}      
        public ServiceContainerControl(IServiceContainer ParentServiceContainer,
 
            Size size, Point location, ServiceForm parent)
        {
            this.state_ = TextServiceState.ServiceNotObtained;
            localServices = new SortedList();
            localServiceTypes = new SortedList();

            this.BackColor = Color.Beige;            
            this.label = string.Empty;    
        
            this.Size = size;
            this.Location = location;
            this.parent = parent;
            this.serviceParent = ParentServiceContainer;
            
            // If a parent is specified, set the parent property of
 this 
            // linkable IServiceContainer implementation.
            if( ParentServiceContainer != null
 )
                serviceParent = ParentServiceContainer;
        }

        // IServiceProvider.GetService implementation for a linked 
        // service container architecture.
        public new object GetService(System.Type
 serviceType)
        {
            if( parentServiceContainer != null
 )
                return parentServiceContainer.GetService(serviceType);
            

            object serviceInstance = localServices[serviceType.FullName];
            if( serviceInstance == null )
                return null;
            else if( serviceInstance.GetType()
 == typeof(ServiceCreatorCallback) )
            {
                // If service instance is a ServiceCreatorCallback,
 invoke 
                // it to create the service.
                return ((ServiceCreatorCallback)serviceInstance)(this,
 serviceType);                                
            }
            return serviceInstance;
        }
        
        // IServiceContainer.AddService implementation for a linked
 
        // service container architecture.
        public void AddService(System.Type
 serviceType, 
            System.ComponentModel.Design.ServiceCreatorCallback callback, bool
 promote)
        {
            if( promote && parentServiceContainer != null
 )            
                parentServiceContainer.AddService(serviceType, callback, true);
            
            else
            {
                localServiceTypes[serviceType.FullName] = serviceType;
                localServices[serviceType.FullName] = callback;
            }
        }
        
        // IServiceContainer.AddService implementation for a linked
 
        // service container architecture.
        public void AddService(System.Type
 serviceType, 
            System.ComponentModel.Design.ServiceCreatorCallback callback)
        {
            AddService(serviceType, callback, true);
        }

        // IServiceContainer.AddService implementation for a linked
 
        // service container architecture.
        public void AddService(System.Type
 serviceType, 
            object serviceInstance, bool promote)
        {
            if( promote && parentServiceContainer != null
 )            
                parentServiceContainer.AddService(serviceType, serviceInstance, true);
            
            else
            {
                localServiceTypes[serviceType.FullName] = serviceType;
                localServices[serviceType.FullName] = serviceInstance;
            }
        }

        // IServiceContainer.AddService (defaults to promote service
 addition).
        public void AddService(System.Type
 serviceType, object serviceInstance)
        {
            AddService(serviceType, serviceInstance, true);
        }

        // IServiceContainer.RemoveService implementation for a linked
 
        // service container architecture.
        public void RemoveService(System.Type
 serviceType, bool promote)
        {
            if( localServices[serviceType.FullName] != null
 )
            {
                localServices.Remove(serviceType.FullName);
                localServiceTypes.Remove(serviceType.FullName);
            }
            if( promote )
            {
                if( parentServiceContainer != null
 )
                    parentServiceContainer.RemoveService(serviceType);
            }
        }

        // IServiceContainer.RemoveService (defaults to promote 
        // service removal)
        public void RemoveService(System.Type
 serviceType)
        {
            RemoveService(serviceType, true);
        }

        // Paint method override draws the label string on the control.
        protected override void OnPaint(System.Windows.Forms.PaintEventArgs
 e)
        {
            e.Graphics.DrawString(label, new Font("Arial",
 8), 
                new SolidBrush(Color.Black), 5, 5);          
  
        }

        // Process mouse-down behavior for click.
        protected override void OnMouseDown(
            System.Windows.Forms.MouseEventArgs e)
        {
            //  This example control responds to mouse clicks as follows:
            //
            //      Left click - control attempts to obtain a text service
 
            //      and sets its label text to the text provided by
 the service
            //      Right click - if the control has already provided
 a text 
            //      service, this control does nothing. Otherwise, the
 control 
            //      shows a dialog box to specify text to provide as
 a new text 
            //      service, after clearing the tree's services.

            if( e.Button == MouseButtons.Left )
            {
                if( state_ != TextServiceState.ServiceProvided
 )
                {
                    // Attempt to update text from service, and set
 
                    // color state accordingly.
                    TextService ts = 
                        (TextService)GetService(typeof(TextService));
                    if( ts != null )
                    {
                        this.label = ts.text;
                        state = TextServiceState.ServiceObtained;
                    }
                    else
                    {                    
                        this.label = "Service Not Found";
                        
                        state = TextServiceState.ServiceNotFound;
                    }
                }
            }
            if( e.Button == MouseButtons.Right )
            {
                if( state_ == TextServiceState.ServiceProvided
 )
                {
                    // Remove the service if the container provided
 it.
                    if( GetService(typeof(TextService)) != null
 )
                    {
                        RemoveService(typeof(TextService), true);
                        state = TextServiceState.ServiceNotObtained; 
                        this.label = "Service Removed";
                                                                   
                    }                    
                }
                else
                {
                    // Obtain string and provide text service.
                    StringInputDialog form = 
                        new StringInputDialog("Test String");
                    form.StartPosition = FormStartPosition.CenterParent;
                    if( form.ShowDialog() == DialogResult.OK )
                    {
                        if( GetService(typeof(TextService)) != null
 )                        
                            RemoveService(typeof(TextService), true);
                                                                            
                        parent.ResetServiceTree(this, new
 EventArgs());

                        AddService(typeof(TextService), 
                            new TextService( form.inputTextBox.Text
 ), true);

                        // The following commented method uses a service
 creator callback.
                        // AddService(typeof(TextService), 
                        //  new ServiceCreatorCallback(this.CreateTextService));
                                                
                        
                        state = TextServiceState.ServiceProvided;
                        this.label = "Provided Text: "+form.inputTextBox.Text;
                                 
                    }
                }
            }
            parent.UpdateServiceCoverage();
        }

        // Method accesses the TextService to test the visibility of
 the 
        // service from the control, and sets the UI state accordingly.
        public void ReflectServiceVisibility()
        {
            if( state_ == TextServiceState.ServiceObtained )
            {
                if( GetService(typeof(TextService)) == null
 )  
                    this.BackColor = Color.CadetBlue;
            }
            else if( state_ != TextServiceState.ServiceProvided
 )
            {
                if( GetService(typeof(TextService)) == null
 )
                {
                    this.BackColor = Color.White;
                    return;
                }

                // Service available.        
                if( state_ == TextServiceState.ServiceNotFound
 )                
                    this.BackColor = Color.Khaki;            
    
                else if( state_ == TextServiceState.ServiceNotObtained
 
                         && label != "Service Removed" )
                    this.BackColor = Color.Khaki;       
            }
        }
        
        // ServiceCreatorCallback method creates a text service.
        private object CreateTextService(IServiceContainer container,
 
            System.Type serviceType)
        {
            return new TextService("Test
 Callback");
        }
    }

    // Example form provides UI for demonstrating service sharing behavior
 
    // of a network of IServiceContainer/IServiceProvider controls.
    public class ServiceForm : System.Windows.Forms.Form
    {
        // Root service container control for tree.
        private ServiceContainerControl root;                
        // Button for clearing any provided services and resetting tree
 states.
        private System.Windows.Forms.Button reset_button;   
        // Color list used to color code controls.
        private Color[] colorkeys;                       
        // Strings used to reflect text service.
        private string[] keystrings;      
                   

        public ServiceForm()
        {
        InitializeComponent();        
            colorkeys = new Color[] { Color.Beige, Color.SeaShell,
 Color.LightGreen, Color.LightBlue, Color.Khaki, Color.CadetBlue };
            keystrings = new string[] { "No
 service use", "Service not accessible", "Service provided",
 "Service obtained", "Service accessible", "No further access" };
            CreateServiceControlTree();                        
        }

        private void CreateServiceControlTree()
        {
            // Create root service control
            ServiceContainerControl control1 = new ServiceContainerControl(
                null, new Size(300, 40), new
 Point(10, 80), this);
            root = control1;
            // Create first tier - pass parent with service object control
 1.
            ServiceContainerControl control2 = new ServiceContainerControl(
                control1, new Size(200, 30), new
 Point(50, 160), this);
            ServiceContainerControl control3 = new ServiceContainerControl(
                control1, new Size(200, 30), new
 Point(50, 240), this);
            // Create second tier A - pass parent with service object
 control 2.
            ServiceContainerControl control4 = new ServiceContainerControl(
                control2, new Size(180, 20), new
 Point(300, 145), this);
            ServiceContainerControl control5 = new ServiceContainerControl(
                control2, new Size(180, 20), new
 Point(300, 185), this);
            // Create second tier B - pass parent with service object
 control 3.
            ServiceContainerControl control6 = new ServiceContainerControl(
                control3, new Size(180, 20), new
 Point(300, 225), this);
            ServiceContainerControl control7 = new ServiceContainerControl(
                control3, new Size(180, 20), new
 Point(300, 265), this);
            // Add controls
            this.Controls.AddRange( new Control[]
 { control1, control2, 
                control3, control4, control5, control6, control7 } );
        }

        internal void ResetServiceTree(object sender, EventArgs
 e)
        {
            // Remove the service from the service tree.
            if( root.GetService(typeof(TextService)) != null
 )            
                root.RemoveService(typeof(TextService), true);

            // Set all controls to "not obtained" and clear
 their labels.
            for( int i=0; i<Controls.Count;
 i++ )
                if( !Controls[i].Equals(reset_button) ) 
                {
                    ((ServiceContainerControl)Controls[i]).state = 
                        TextServiceState.ServiceNotObtained;
                    ((ServiceContainerControl)Controls[i]).label = string.Empty;
                    ((ServiceContainerControl)Controls[i]).BackColor = 
                        Color.Beige;
                }
        }

        public void UpdateServiceCoverage()
        {
            // Have each control set state to reflect service availability.
            for( int i=0; i<Controls.Count;
 i++ )
                if( !Controls[i].Equals(reset_button) )      
           
                    ((ServiceContainerControl)Controls[i]).ReflectServiceVisibility();
                                 
        }

            #region Windows Form Designer generated code
            private void InitializeComponent()
            {
            this.reset_button = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // reset_button
            // 
            this.reset_button.Location = new
 System.Drawing.Point(392, 88);
            this.reset_button.Name = "reset_button";
            this.reset_button.TabIndex = 0;
            this.reset_button.TabStop = false;
            this.reset_button.Text = "Reset";
            this.reset_button.Click += new
 System.EventHandler(this.ResetServiceTree);
            // 
            // ServiceForm
            // 
            this.ClientSize = new System.Drawing.Size(512,
 373);
            this.Controls.AddRange(new System.Windows.Forms.Control[]
 {
                                                                          this.reset_button});
            this.MinimumSize = new System.Drawing.Size(520,
 400);
            this.Name = "ServiceForm";
            this.Text = "Service Container Architecture Example";
            this.ResumeLayout(false);

            }
            #endregion

            [STAThread]
            static void Main() 
            {
                Application.Run(new ServiceForm());
            }

        protected override void OnPaint(System.Windows.Forms.PaintEventArgs
 e)
        {            
            e.Graphics.DrawString("The following tree diagram represents a "+
                "hierarchy of linked service containers in
 controls.", 
                new Font("Arial", 9), new
 SolidBrush(Color.Black), 4, 4);
            e.Graphics.DrawString("This example demonstrates the propagation
 "+
                "behavior of services through a linked service object tree.",
 
                new Font("Arial", 8), new
 SolidBrush(Color.Black), 4, 26);            
            e.Graphics.DrawString("Right-click a component to add or replace
 a "+
                "text service, or to remove it if the component
 provided it.", 
                new Font("Arial", 8), new
 SolidBrush(Color.Black), 4, 38);
            e.Graphics.DrawString("Left-click a component to update text from
 "+
                "the text service if available.", new
 Font("Arial", 8), 
                new SolidBrush(Color.Black), 4, 50);

            // Draw lines to represent tree branches.
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                20, 125, 20, 258);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                21, 175, 45, 175);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                21, 258, 45, 258);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                255, 175, 285, 175);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                255, 258, 285, 258);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                285, 155, 285, 195);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                285, 238, 285, 278);            
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                285, 155, 290, 155);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                285, 195, 290, 195);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                285, 238, 290, 238);
            e.Graphics.DrawLine(new Pen(new
 SolidBrush(Color.Black), 1), 
                285, 278, 290, 278);

            // Draw color key.
            e.Graphics.DrawRectangle(new Pen(new
 SolidBrush(Color.Black), 1), 20, 305, 410, 60);
            int y=0;
            for( int i=0; i<3; i++ )
            {
                e.Graphics.FillRectangle(new SolidBrush(colorkeys[y]),
 
                    25+(i*140), 310, 20, 20);           
                e.Graphics.DrawRectangle(new Pen(new
 SolidBrush(Color.Black), 1), 
                    25+(i*140), 310, 20, 20);     
                e.Graphics.DrawString(keystrings[y], new Font("Arial",
 8), 
                    new SolidBrush(Color.Black), 50+(i*140), 315);
                y++;
                e.Graphics.FillRectangle(new SolidBrush(colorkeys[y]),
 
                    25+(i*140), 340, 20, 20);           
                e.Graphics.DrawRectangle(new Pen(new
 SolidBrush(Color.Black), 1), 
                    25+(i*140), 340, 20, 20);              
                e.Graphics.DrawString(keystrings[y], new Font("Arial",
 8), 
                    new SolidBrush(Color.Black), 50+(i*140), 345);
                y++;
            }
        }
    }   
   
    // Example service type contains a text string, sufficient to 
    // demonstrate service sharing.
    public class TextService
    {
        public string text;

        public TextService() : this(string.Empty)
        {
        }

        public TextService(string text)
        {
            this.text = text;
        }
    }

    public enum TextServiceState
    {
        ServiceNotObtained,
        ServiceObtained,
        ServiceProvided,
        ServiceNotFound
    }

    // Example Form for entering a string.
    internal class StringInputDialog : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button ok_button;
        private System.Windows.Forms.Button cancel_button;
        public System.Windows.Forms.TextBox inputTextBox;

        public StringInputDialog(string text)
        {
            InitializeComponent();
            inputTextBox.Text = text;
        }

        private void InitializeComponent()
        {
            this.ok_button = new System.Windows.Forms.Button();
            this.cancel_button = new System.Windows.Forms.Button();
            this.inputTextBox = new System.Windows.Forms.TextBox();
            this.SuspendLayout();
            this.ok_button.Anchor = (System.Windows.Forms.AnchorStyles.Bottom
 | 
                System.Windows.Forms.AnchorStyles.Right);
            this.ok_button.Location = new System.Drawing.Point(180,
 43);
            this.ok_button.Name = "ok_button";
            this.ok_button.TabIndex = 1;
            this.ok_button.Text = "OK";      
            this.ok_button.DialogResult = System.Windows.Forms.DialogResult.OK;
            
            this.cancel_button.Anchor = (System.Windows.Forms.AnchorStyles.Bottom
 | 
                System.Windows.Forms.AnchorStyles.Right);
            this.cancel_button.Location = new
 System.Drawing.Point(260, 43);
            this.cancel_button.Name = "cancel_button";
            this.cancel_button.TabIndex = 2;
            this.cancel_button.Text = "Cancel";    
        
            this.cancel_button.DialogResult = System.Windows.Forms.DialogResult.Cancel;
            this.inputTextBox.Location = new
 System.Drawing.Point(6, 9);
            this.inputTextBox.Name = "inputTextBox";
            this.inputTextBox.Size = new System.Drawing.Size(327,
 20);
            this.inputTextBox.TabIndex = 0;
            this.inputTextBox.Text = "";           
 
            this.inputTextBox.Anchor = ((System.Windows.Forms.AnchorStyles.Top
 | 
                System.Windows.Forms.AnchorStyles.Left) 
                | System.Windows.Forms.AnchorStyles.Right);
            this.ClientSize = new System.Drawing.Size(342,
 73);
            this.Controls.AddRange(new System.Windows.Forms.Control[]
 {
                                                                          this.inputTextBox
,
                                                                          this.cancel_button
,
                                                                          this.ok_button});
            this.MinimumSize = new System.Drawing.Size(350,
 100);
            this.Name = "StringInputDialog";
            this.Text = "Text Service Provide String Dialog";
            this.ResumeLayout(false);
        }
    }
}
#using <System.Windows.Forms.dll>
#using <System.dll>
#using <System.Drawing.dll>

using namespace System;
using namespace System::Drawing;
using namespace System::Collections;
using namespace System::ComponentModel;
using namespace System::ComponentModel::Design;
using namespace System::Windows::Forms;
using namespace System::Windows::Forms::Design;

// This sample contains a Form class that is configured to demonstrate
 
// the behavior of a network of linked service containers.   
// Notes regarding this IServiceContainer and IServiceProvider 
// implementation:
//
// When implementing the IServiceContainer interface, you may want to
 
// implement support for a linked service container system
// which enables access to and sharing of services throughout a 
// container tree or network.
//
// To effectively share a service, a GetService, AddService or 
// RemoveService method must be able to locate a service 
// that has been added to a shared service container tree or network.
//        
// One simple approach to sharing services, suitable for container networks
 
// where each container has one parent and the tree has
// one parentless container, is to store services only at the top node
 
// (the root or grandparent) of a tree.
//
// To store services in the root node of a tree, two types of 
// consistencies must be maintained in the implementation:        
//
//   >   The GetService, AddService and RemoveService implementations
 
//       must access the root through some mechanism.
//         The ServiceContainerControl's implementations of these 
//         standard IServiceContainer methods call 
//         the same method of a parent container, if the container 
//         has been parented, to route methods to the root.  
//
//   >   The services must be maintained at the root of the tree;
 
//       therefore, any new child's services should be copied to the
 root.                
ref class ServiceForm;

// forward declaration
public enum class TextServiceState
{
   ServiceNotObtained, ServiceObtained, ServiceProvided, ServiceNotFound
};

// Example service type contains a text string, sufficient to 
// demonstrate service sharing.
public ref class TextService
{
public:
   String^ text;
   TextService()
   {
      this->text = String::Empty;
   }

   TextService( String^ text )
   {
      this->text = text;
   }
};

// ServiceContainerControl provides an example user control implmentation
 
// of the IServiceContainer interface. This implementation of 
// IServiceContainer supports a root-node linked service distribution,
 
// access. and removal architecture.
public ref class ServiceContainerControl: public
 System::Windows::Forms::UserControl, public IServiceContainer
{
private:

   // List of service instances sorted by key of service type's full
 name.
   SortedList^ localServices;

   // List that contains the Type for each service sorted by each 
   // service type's full name.
   SortedList^ localServiceTypes;

   // The parent IServiceContainer, or null.
   IServiceContainer^ parentServiceContainer;

public:

   property IServiceContainer^ serviceParent 
   {
      IServiceContainer^ get()
      {
         return parentServiceContainer;
      }

      void set( IServiceContainer^ value )
      {
         parentServiceContainer = value;

         // Move any services to parent.
         for ( int i = 0; i < localServices->Count;
 i++ )
            parentServiceContainer->AddService( dynamic_cast<Type^>(localServiceTypes->GetByIndex(
 i )), localServices->GetByIndex( i ) );
         localServices->Clear();
         localServiceTypes->Clear();
      }
   }

private:

   // The current state of the control reflecting whether it has 
   // obtained or provided a text service.
   TextServiceState state_;

public:

   property TextServiceState state 
   {
      TextServiceState get()
      {
         return state_;
      }

      void set( TextServiceState value )
      {
         if ( (TextServiceState)value == TextServiceState::ServiceProvided
 )
                  this->BackColor = Color::LightGreen;
         else
         if ( (TextServiceState)value == TextServiceState::ServiceNotObtained
 )
                  this->BackColor = Color::White;
         else
         if ( (TextServiceState)value == TextServiceState::ServiceObtained
 )
                  this->BackColor = Color::LightBlue;
         else
         if ( (TextServiceState)value == TextServiceState::ServiceNotFound
 )
                  this->BackColor = Color::SeaShell;

         state_ = value;
      }
   }

private:

   // Parent form reference for main program function access.
   ServiceForm^ parent;

public:

   // String for label displayed on the control to indicate 
   // the control's current service-related configuration state.
   String^ label;
   ServiceContainerControl( IServiceContainer^ ParentServiceContainer, System::Drawing::Size
 size, Point location, ServiceForm^ parent )
   {
      this->state_ = TextServiceState::ServiceNotObtained;
      localServices = gcnew SortedList;
      localServiceTypes = gcnew SortedList;
      this->BackColor = Color::Beige;
      this->label = String::Empty;
      this->Size = size;
      this->Location = location;
      this->parent = parent;
      this->serviceParent = ParentServiceContainer;

      // If a parent is specified, set the parent property of this 
      // linkable IServiceContainer implementation.
      if ( ParentServiceContainer != nullptr )
            serviceParent = ParentServiceContainer;
   }

   // IServiceProvider.GetService implementation for a linked 
   // service container architecture.
   virtual Object^ GetService( System::Type^ serviceType ) override
   {
      if ( parentServiceContainer != nullptr )
            return parentServiceContainer->GetService( serviceType
 );

      Object^ serviceInstance = localServices[ serviceType->FullName ];
      if ( serviceInstance == nullptr )
            return nullptr;
      else
      if ( serviceInstance->GetType() == ServiceCreatorCallback::typeid
 )
      {
         // If service instance is a ServiceCreatorCallback, invoke
 
         // it to create the service.
         return (dynamic_cast<ServiceCreatorCallback^>(serviceInstance));
         (this,serviceType);
      }

      return serviceInstance;
   }

   // IServiceContainer.AddService implementation for a linked 
   // service container architecture.
   virtual void AddService( System::Type^ serviceType, System::ComponentModel::Design::ServiceCreatorCallback^
 callback, bool promote )
   {
      if ( promote && parentServiceContainer != nullptr
 )
            parentServiceContainer->AddService( serviceType, callback, true
 );
      else
      {
         localServiceTypes[ serviceType->FullName ] = serviceType;
         localServices[ serviceType->FullName ] = callback;
      }
   }

   // IServiceContainer.AddService implementation for a linked 
   // service container architecture.
   virtual void AddService( System::Type^ serviceType, System::ComponentModel::Design::ServiceCreatorCallback^
 callback )
   {
      AddService( serviceType, callback, true );
   }

   // IServiceContainer.AddService implementation for a linked 
   // service container architecture.
   virtual void AddService( System::Type^ serviceType, Object^
 serviceInstance, bool promote )
   {
      if ( promote && parentServiceContainer != nullptr
 )
            parentServiceContainer->AddService( serviceType, serviceInstance,
 true );
      else
      {
         localServiceTypes[ serviceType->FullName ] = serviceType;
         localServices[ serviceType->FullName ] = serviceInstance;
      }
   }

   // IServiceContainer.AddService (defaults to promote service addition).
   virtual void AddService( System::Type^ serviceType, Object^
 serviceInstance )
   {
      AddService( serviceType, serviceInstance, true );
   }

   // IServiceContainer.RemoveService implementation for a linked 
   // service container architecture.
   virtual void RemoveService( System::Type^ serviceType, bool
 promote )
   {
      if ( localServices[ serviceType->FullName ] != nullptr
 )
      {
         localServices->Remove( serviceType->FullName );
         localServiceTypes->Remove( serviceType->FullName );
      }

      if ( promote )
      {
         if ( parentServiceContainer != nullptr )
                  parentServiceContainer->RemoveService( serviceType );
      }
   }

   // IServiceContainer.RemoveService (defaults to promote 
   // service removal)
   virtual void RemoveService( System::Type^ serviceType )
   {
      RemoveService( serviceType, true );
   }

protected:

   // Paint method override draws the label string on the control.
   virtual void OnPaint( System::Windows::Forms::PaintEventArgs^
 e ) override
   {
      e->Graphics->DrawString( label, gcnew System::Drawing::Font( "Arial",8
 ), gcnew SolidBrush( Color::Black ), 5, 5 );
   }

   // Process mouse-down behavior for click.
   virtual void OnMouseDown( System::Windows::Forms::MouseEventArgs^
 e ) override;

public:

   // Method accesses the TextService to test the visibility of the
 
   // service from the control, and sets the UI state accordingly.
   void ReflectServiceVisibility()
   {
      if ( state_ == TextServiceState::ServiceObtained )
      {
         if ( GetService( TextService::typeid ) == nullptr )
                  this->BackColor = Color::CadetBlue;
      }
      else
      if ( state_ != TextServiceState::ServiceProvided )
      {
         if ( GetService( TextService::typeid ) == nullptr )
         {
            this->BackColor = Color::White;
            return;
         }
         
         // Service available.        
         if ( state_ == TextServiceState::ServiceNotFound )
                  this->BackColor = Color::Khaki;
         else
         if ( state_ == TextServiceState::ServiceNotObtained &&
  !label->Equals( "Service Removed" ) )
                  this->BackColor = Color::Khaki;
      }
   }

private:

   // ServiceCreatorCallback method creates a text service.
   Object^ CreateTextService( IServiceContainer^ /*container*/, System::Type^ /*serviceType*/
 )
   {
      return gcnew TextService( "Test Callback" );
   }
};

// Example form provides UI for demonstrating service sharing behavior
 
// of a network of IServiceContainer/IServiceProvider controls.
public ref class ServiceForm: public
 System::Windows::Forms::Form
{
private:

   // Root service container control for tree.
   ServiceContainerControl^ root;

   // Button for clearing any provided services and resetting tree states.
   System::Windows::Forms::Button^ reset_button;

   // Color list used to color code controls.
   array<Color>^colorkeys;

   // Strings used to reflect text service.
   array<String^>^keystrings;

public:
   ServiceForm()
   {
      InitializeComponent();
      colorkeys = gcnew array<Color>(6);
      colorkeys[ 0 ] = Color::Beige;
      colorkeys[ 1 ] = Color::SeaShell;
      colorkeys[ 2 ] = Color::LightGreen;
      colorkeys[ 3 ] = Color::LightBlue;
      colorkeys[ 4 ] = Color::Khaki;
      colorkeys[ 5 ] = Color::CadetBlue;
      array<String^>^temp3 = {"No service use","Service not
 accessible","Service provided","Service obtained","Service
 accessible","No further access"};
      keystrings = temp3;
      CreateServiceControlTree();
   }

private:
   void CreateServiceControlTree()
   {
      // Create root service control
      ServiceContainerControl^ control1 = gcnew ServiceContainerControl( nullptr,System::Drawing::Size(
 300, 40 ),Point(10,80),this );
      root = control1;

      // Create first tier - pass parent with service object control
 1.
      ServiceContainerControl^ control2 = gcnew ServiceContainerControl( control1,System::Drawing::Size(
 200, 30 ),Point(50,160),this );
      ServiceContainerControl^ control3 = gcnew ServiceContainerControl( control1,System::Drawing::Size(
 200, 30 ),Point(50,240),this );

      // Create second tier A - pass parent with service object control
 2.
      ServiceContainerControl^ control4 = gcnew ServiceContainerControl( control2,System::Drawing::Size(
 180, 20 ),Point(300,145),this );
      ServiceContainerControl^ control5 = gcnew ServiceContainerControl( control2,System::Drawing::Size(
 180, 20 ),Point(300,185),this );

      // Create second tier B - pass parent with service object control
 3.
      ServiceContainerControl^ control6 = gcnew ServiceContainerControl( control3,System::Drawing::Size(
 180, 20 ),Point(300,225),this );
      ServiceContainerControl^ control7 = gcnew ServiceContainerControl( control3,System::Drawing::Size(
 180, 20 ),Point(300,265),this );

      // Add controls
      array<Control^>^temp0 = {control1,control2,control3,control4,control5
,control6,control7};
      this->Controls->AddRange( temp0 );
   }

internal:
   void ResetServiceTree( Object^ /*sender*/, EventArgs^ /*e*/
 )
   {
      // Remove the service from the service tree.
      if ( root->GetService( TextService::typeid ) != nullptr
 )
            root->RemoveService( TextService::typeid, true
 );

      // Set all controls to "not obtained" and clear their
 labels.
      for ( int i = 0; i < Controls->Count;
 i++ )
         if (  !Controls[ i ]->Equals( reset_button ) )
         {
            (dynamic_cast<ServiceContainerControl^>(Controls[ i ]))->state
 = TextServiceState::ServiceNotObtained;
            (dynamic_cast<ServiceContainerControl^>(Controls[ i ]))->label
 = String::Empty;
            (dynamic_cast<ServiceContainerControl^>(Controls[ i ]))->BackColor
 = Color::Beige;
         }
   }

public:
   void UpdateServiceCoverage()
   {
      // Have each control set state to reflect service availability.
      for ( int i = 0; i < Controls->Count;
 i++ )
         if (  !Controls[ i ]->Equals( reset_button ) )
                  (dynamic_cast<ServiceContainerControl^>(Controls[ i ]))->ReflectServiceVisibility();
   }

private:
   void InitializeComponent()
   {
      this->reset_button = gcnew System::Windows::Forms::Button;
      this->SuspendLayout();

      // 
      // reset_button
      // 
      this->reset_button->Location = System::Drawing::Point(
 392, 88 );
      this->reset_button->Name = "reset_button";
      this->reset_button->TabIndex = 0;
      this->reset_button->TabStop = false;
      this->reset_button->Text = "Reset";
      this->reset_button->Click += gcnew System::EventHandler(
 this, &ServiceForm::ResetServiceTree );

      // 
      // ServiceForm
      // 
      this->ClientSize = System::Drawing::Size( 512, 373 );
      array<System::Windows::Forms::Control^>^temp1 = {this->reset_button};
      this->Controls->AddRange( temp1 );
      this->MinimumSize = System::Drawing::Size( 520, 400 );
      this->Name = "ServiceForm";
      this->Text = "Service Container Architecture Example";
      this->ResumeLayout( false );
   }

protected:
   virtual void OnPaint( System::Windows::Forms::PaintEventArgs^
 e ) override
   {
      e->Graphics->DrawString( "The following tree diagram represents
 a "
      "hierarchy of linked service containers in controls.",
 gcnew System::Drawing::Font( "Arial",9 ), gcnew SolidBrush( Color::Black
 ), 4, 4 );
      e->Graphics->DrawString( "This example demonstrates the propagation
 "
      "behavior of services through a linked service object tree.", gcnew
 System::Drawing::Font( "Arial",8 ), gcnew SolidBrush( Color::Black ),
 4, 26 );
      e->Graphics->DrawString( "Right-click a component to add or replace
 a "
      "text service, or to remove it if the component provided
 it.", gcnew System::Drawing::Font( "Arial",8 ), gcnew SolidBrush(
 Color::Black ), 4, 38 );
      e->Graphics->DrawString( "Left-click a component to update text
 from "
      "the text service if available.", gcnew System::Drawing::Font(
 "Arial",8 ), gcnew SolidBrush( Color::Black ), 4, 50 );

      // Draw lines to represent tree branches.
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 20, 125, 20, 258 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 21, 175, 45, 175 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 21, 258, 45, 258 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 255, 175, 285, 175 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 255, 258, 285, 258 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 285, 155, 285, 195 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 285, 238, 285, 278 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 285, 155, 290, 155 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 285, 195, 290, 195 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 285, 238, 290, 238 );
      e->Graphics->DrawLine( gcnew Pen( gcnew SolidBrush( Color::Black ),1
 ), 285, 278, 290, 278 );

      // Draw color key.
      e->Graphics->DrawRectangle( gcnew Pen( gcnew SolidBrush( Color::Black
 ),1 ), 20, 305, 410, 60 );
      int y = 0;
      for ( int i = 0; i < 3; i++ )
      {
         e->Graphics->FillRectangle( gcnew SolidBrush( colorkeys[ y ] ), 25
 + (i * 140), 310, 20, 20 );
         e->Graphics->DrawRectangle( gcnew Pen( gcnew SolidBrush( Color::Black
 ),1 ), 25 + (i * 140), 310, 20, 20 );
         e->Graphics->DrawString( keystrings[ y ], gcnew System::Drawing::Font(
 "Arial",8 ), gcnew SolidBrush( Color::Black ), 50.0f + (i * 140), 315.0f
 );
         y++;
         e->Graphics->FillRectangle( gcnew SolidBrush( colorkeys[ y ] ), 25
 + (i * 140), 340, 20, 20 );
         e->Graphics->DrawRectangle( gcnew Pen( gcnew SolidBrush( Color::Black
 ),1 ), 25 + (i * 140), 340, 20, 20 );
         e->Graphics->DrawString( keystrings[ y ], gcnew System::Drawing::Font(
 "Arial",8 ), gcnew SolidBrush( Color::Black ), 50.0f + (i * 140), 345.0f
 );
         y++;

      }
   }
};

// Example Form for entering a string.
private ref class StringInputDialog: public
 System::Windows::Forms::Form
{
private:
   System::Windows::Forms::Button^ ok_button;
   System::Windows::Forms::Button^ cancel_button;

public:
   System::Windows::Forms::TextBox^ inputTextBox;
   StringInputDialog( String^ text )
   {
      InitializeComponent();
      inputTextBox->Text = text;
   }

private:
   void InitializeComponent()
   {
      this->ok_button = gcnew System::Windows::Forms::Button;
      this->cancel_button = gcnew System::Windows::Forms::Button;
      this->inputTextBox = gcnew System::Windows::Forms::TextBox;
      this->SuspendLayout();
      this->ok_button->Anchor = static_cast<System::Windows::Forms::AnchorStyles>(System::Windows::Forms::AnchorStyles::Bottom
 | System::Windows::Forms::AnchorStyles::Right);
      this->ok_button->Location = System::Drawing::Point(
 180, 43 );
      this->ok_button->Name = "ok_button";
      this->ok_button->TabIndex = 1;
      this->ok_button->Text = "OK";
      this->ok_button->DialogResult = System::Windows::Forms::DialogResult::OK;
      this->cancel_button->Anchor = static_cast<System::Windows::Forms::AnchorStyles>(System::Windows::Forms::AnchorStyles::Bottom
 | System::Windows::Forms::AnchorStyles::Right);
      this->cancel_button->Location = System::Drawing::Point(
 260, 43 );
      this->cancel_button->Name = "cancel_button";
      this->cancel_button->TabIndex = 2;
      this->cancel_button->Text = "Cancel";
      this->cancel_button->DialogResult = System::Windows::Forms::DialogResult::Cancel;
      this->inputTextBox->Location = System::Drawing::Point(
 6, 9 );
      this->inputTextBox->Name = "inputTextBox";
      this->inputTextBox->Size = System::Drawing::Size(
 327, 20 );
      this->inputTextBox->TabIndex = 0;
      this->inputTextBox->Text = "";
      this->inputTextBox->Anchor = static_cast<System::Windows::Forms::AnchorStyles>(System::Windows::Forms::AnchorStyles::Top
 | System::Windows::Forms::AnchorStyles::Left | System::Windows::Forms::AnchorStyles::Right);
      this->ClientSize = System::Drawing::Size( 342, 73 );
      array<System::Windows::Forms::Control^>^temp4 = {this->inputTextBox
,this->cancel_button,this->ok_button};
      this->Controls->AddRange( temp4 );
      this->MinimumSize = System::Drawing::Size( 350, 100 );
      this->Name = "StringInputDialog";
      this->Text = "Text Service Provide String Dialog";
      this->ResumeLayout( false );
   }
};

void ServiceContainerControl::OnMouseDown( System::Windows::Forms::MouseEventArgs^
 e )
{
   //  This example control responds to mouse clicks as follows:
   //
   //      Left click - control attempts to obtain a text service 
   //      and sets its label text to the text provided by the service
   //      Right click - if the control has already provided a text
 
   //      service, this control does nothing. Otherwise, the control
 
   //      shows a dialog box to specify text to provide as a new text
 
   //      service, after clearing the tree's services.
   if ( e->Button == ::MouseButtons::Left )
   {
      if ( state_ != TextServiceState::ServiceProvided )
      {
         // Attempt to update text from service, and set 
         // color state accordingly.
         TextService^ ts = dynamic_cast<TextService^>(GetService( TextService::typeid
 ));
         if ( ts != nullptr )
         {
            this->label = ts->text;
            state = TextServiceState::ServiceObtained;
         }
         else
         {
            this->label = "Service Not Found";
            state = TextServiceState::ServiceNotFound;
         }
      }
   }

   if ( e->Button == ::MouseButtons::Right )
   {
      if ( state_ == TextServiceState::ServiceProvided )
      {
         // Remove the service if the container provided it.
         if ( GetService( TextService::typeid ) != nullptr )
         {
            RemoveService( TextService::typeid, true );
            state = TextServiceState::ServiceNotObtained;
            this->label = "Service Removed";
         }
      }
      else
      {
         // Obtain string and provide text service.
         StringInputDialog^ form = gcnew StringInputDialog( "Test String"
 );
         form->StartPosition = FormStartPosition::CenterParent;
         if ( form->ShowDialog() == DialogResult::OK )
         {
            if ( GetService( TextService::typeid ) != nullptr
 )
                        RemoveService( TextService::typeid, true
 );
            parent->ResetServiceTree( this, gcnew EventArgs
 );
            AddService( TextService::typeid, gcnew TextService( form->inputTextBox->Text
 ), true );

            // The following commented method uses a service creator
 callback.
            // AddService(typeof(TextService), 
            //  new ServiceCreatorCallback(this.CreateTextService));
                                                
            state = TextServiceState::ServiceProvided;
            this->label = String::Format( "Provided Text:
 {0}", form->inputTextBox->Text );
         }
      }
   }

   parent->UpdateServiceCoverage();
}

[STAThread]
int main()
{
   Application::Run( gcnew ServiceForm );
}
package ServiceArchitectureExample;

import System.*;
import System.Drawing.*;
import System.Collections.*;
import System.ComponentModel.*;
import System.ComponentModel.Design.*;
import System.Windows.Forms.*;
import System.Windows.Forms.Design.*;
   
   // This sample contains a Form class that is configured to demonstrate
 
   // the behavior of a network of linked service containers.   
   // Notes regarding this IServiceContainer and IServiceProvider 
   // implementation:
   //
   // When implementing the IServiceContainer interface, you may want to
 
   // implement support for a linked service container system
   // which enables access to and sharing of services throughout a 
   // container tree or network.
   //
   // To effectively share a service, a GetService, AddService or 
   // RemoveService method must be able to locate a service 
   // that has been added to a shared service container tree or network.
   //        
   // One simple approach to sharing services, suitable for container networks
 
   // where each container has one parent and the tree has
   // one parentless container, is to store services only at the top node
 
   // (the root or grandparent) of a tree.
   //
   // To store services in the root node of a tree, two types of 
   // consistencies must be maintained in the implementation:      
  
   //
   //   >   The GetService, AddService and RemoveService implementations
 
   //       must access the root through some mechanism.
   //         The ServiceContainerControl's implementations of these
 
   //         standard IServiceContainer methods call 
   //         the same method of a parent container, if the container
 
   //         has been parented, to route methods to the root.  
   //
   //   >   The services must be maintained at the root of the tree;
 
   //       therefore, any new child's services should be copied to the
 root.                
   
   // ServiceContainerControl provides an example user control implmentation
 
   // of the IServiceContainer interface. This implementation of 
   // IServiceContainer supports a root-node linked service distribution,
 
   // access. and removal architecture.
public class ServiceContainerControl extends
  System.Windows.Forms.UserControl
    implements  IServiceContainer
{
    // List of service instances sorted by key of service type's full
 name.
    private SortedList localServices;

    // List that contains the Type for each service sorted by each 
    // service type's full name.
    private SortedList localServiceTypes;

    // The parent IServiceContainer, or null.
    private IServiceContainer parentServiceContainer;

    /** @property 
     */
    public IServiceContainer get_serviceParent()
    {
        return parentServiceContainer;
    } //get_serviceParent

    /** @property 
     */
    public void set_serviceParent(IServiceContainer
 value)
    {
        parentServiceContainer = value;

        // Move any services to parent.
        for (int i = 0; i < localServices.get_Count();
 i++) {
            parentServiceContainer.AddService(
                (Type)(localServiceTypes.GetByIndex(i)),
                localServices.GetByIndex(i));
        }
        localServices.Clear();
        localServiceTypes.Clear();
    } //set_serviceParent

    // The current state of the control reflecting whether it has 
    // obtained or provided a text service.
    private TextServiceState state_;

    /** @property 
     */
    public TextServiceState get_state()
    {
        return state_;
    } //get_state

    /** @property 
     */
    public void set_state(TextServiceState
 value)
    {
        if (value.member == TextServiceState.ServiceProvided){
                this.set_BackColor(Color.get_LightGreen());
        }
        else {
            if (value.member == TextServiceState.ServiceNotObtained)
 {
                this.set_BackColor(Color.get_White());
            }
            else {
                if (value.member == TextServiceState.ServiceObtained)
 {
                    this.set_BackColor(Color.get_LightBlue());
                }
                else {
                    if (value.member == TextServiceState.ServiceNotFound)
 {
                            this.set_BackColor(Color.get_SeaShell());
                    }
                }
            }
        }
        state_ = value;
    } //set_state

    // Parent form reference for main program function access.
    private ServiceForm parent;

    // String for label displayed on the control to indicate 
    // the control's current service-related configuration state.
    public String label;

    public ServiceContainerControl(Size size, Point location,
 
        ServiceForm parent)
    {
        this(null, size, location, parent);
    } //ServiceContainerControl

    public ServiceContainerControl(IServiceContainer ParentServiceContainer,
 
        Size size, Point location, ServiceForm parent)
    {
        this.set_state(new TextServiceState(
            TextServiceState.ServiceNotObtained));
        localServices = new SortedList();
        localServiceTypes = new SortedList();
        this.set_BackColor(Color.get_Beige());
        this.label = "";
        this.set_Size(size);
        this.set_Location(location);
        this.parent = parent;
        this.set_serviceParent(ParentServiceContainer);

        // If a parent is specified, set the parent property of this
 
        // linkable IServiceContainer implementation.
        if (ParentServiceContainer != null)
 {
            set_serviceParent(ParentServiceContainer);
        }
    } //ServiceContainerControl

    // IServiceProvider.GetService implementation for a linked 
    // service container architecture.
    public Object GetService(System.Type serviceType)
    {
        if (parentServiceContainer != null)
 {
            return parentServiceContainer.GetService(serviceType);
        }
        Object serviceInstance 
            = localServices.get_Item(serviceType.get_FullName());

        if (serviceInstance == null) {
            return null;
        }
        else {
            if (serviceInstance.GetType().
                Equals (ServiceCreatorCallback.class.ToType()))
 {
                // If service instance is a ServiceCreatorCallback,
 invoke 
                // it to create the service.
                return ((ServiceCreatorCallback)serviceInstance).
                    Invoke(this, serviceType);
            }
        }
        return serviceInstance;
    } //GetService

    // IServiceContainer.AddService implementation for a linked 
    // service container architecture.
    public void AddService(System.Type serviceType,
 
        System.ComponentModel.Design.ServiceCreatorCallback callback, 
        boolean promote)
    {
        if (promote && parentServiceContainer != null)
 {
            parentServiceContainer.AddService(serviceType, callback, true);
        }
        else {
            localServiceTypes.set_Item(serviceType.get_FullName(), serviceType);
            localServices.set_Item(serviceType.get_FullName(), callback);
        }
    } //AddService

    // IServiceContainer.AddService implementation for a linked 
    // service container architecture.
    public void AddService(System.Type serviceType,
 
        System.ComponentModel.Design.ServiceCreatorCallback callback)
    {
        AddService(serviceType, callback, true);
    } //AddService

    // IServiceContainer.AddService implementation for a linked 
    // service container architecture.
    public void AddService(System.Type serviceType,
 
        Object serviceInstance, boolean promote)
    {
        if (promote && parentServiceContainer != null)
 {
            parentServiceContainer.AddService(serviceType, 
                serviceInstance, true);
        }
        else {
            localServiceTypes.set_Item(serviceType.get_FullName(), serviceType);
            localServices.set_Item(serviceType.get_FullName(), serviceInstance);
        }
    } //AddService

    // IServiceContainer.AddService (defaults to promote service addition).
    public void AddService(System.Type serviceType,
 Object serviceInstance)
    {
        AddService(serviceType, serviceInstance, true);
    } //AddService

    // IServiceContainer.RemoveService implementation for a linked 
    // service container architecture.
    public void RemoveService(System.Type serviceType,
 boolean promote)
    {
        if (localServices.get_Item(serviceType.get_FullName())
 != null) {
            localServices.Remove(serviceType.get_FullName());
            localServiceTypes.Remove(serviceType.get_FullName());
        }
        if (promote) {
            if (parentServiceContainer != null)
 {
                parentServiceContainer.RemoveService(serviceType);
            }
        }
    } //RemoveService

    // IServiceContainer.RemoveService (defaults to promote 
    // service removal)
    public void RemoveService(System.Type serviceType)
    {
        RemoveService(serviceType, true);
    } //RemoveService

    // Paint method override draws the label string on the control.
    protected void OnPaint(System.Windows.Forms.PaintEventArgs
 e)
    {
        e.get_Graphics().DrawString(label, new Font("Arial",
 8), 
            new SolidBrush(Color.get_Black()), 5, 5);
    } //OnPaint

    // Process mouse-down behavior for click.
    protected void OnMouseDown(System.Windows.Forms.MouseEventArgs
 e)
    {
        //  This example control responds to mouse clicks as follows:
        //
        //      Left click - control attempts to obtain a text service
 
        //      and sets its label text to the text provided by the
 service
        //      Right click - if the control has already provided a text
 
        //      service, this control does nothing. Otherwise, the control
 
        //      shows a dialog box to specify text to provide as a new text
 
        //      service, after clearing the tree's services.
        if (e.get_Button().Equals (get_MouseButtons().Left)) {
            if (!(state_ .Equals (new TextServiceState(
                TextServiceState.ServiceProvided)))) {
                // Attempt to update text from service, and set 
                // color state accordingly.
                TextService ts 
                    = (TextService)(GetService(TextService.class.ToType()));
                if (ts != null) {
                    this.label = ts.text;
                    set_state(new TextServiceState(
                        TextServiceState.ServiceObtained));
                }
                else {
                    this.label = "Service Not Found";
                    set_state(new TextServiceState(
                        TextServiceState.ServiceNotFound));
                }
            }
        }
        if (e.get_Button().Equals (get_MouseButtons().Right))
 {
            if (state_.Equals (new TextServiceState(
                TextServiceState.ServiceProvided))) {
                // Remove the service if the container provided it.
                if (GetService(TextService.class.ToType())
 != null) {
                    RemoveService(TextService.class.ToType(),
 true);
                    set_state(new TextServiceState(
                        TextServiceState.ServiceNotObtained));
                    this.label = "Service Removed";
                }
            }
            else {
                // Obtain string and provide text service.
                StringInputDialog form = new StringInputDialog("Test
 String");
                form.set_StartPosition(FormStartPosition.CenterParent);
                if (form.ShowDialog().Equals(DialogResult.OK))
 {
                    if (GetService(TextService.class.ToType())
 != null) {
                        RemoveService(TextService.class.ToType(),
 true);
                    }
                    parent.ResetServiceTree(this, new
 EventArgs());
                    AddService(TextService.class.ToType(), 
                        new TextService(form.inputTextBox.get_Text()),
 true);

                    // The following commented method uses a 
                    // service creator callback.
                    // AddService(typeof(TextService), 
                    //  new ServiceCreatorCallback(this.CreateTextService));
                                                
                    set_state(
                        new TextServiceState(TextServiceState.ServiceProvided));
                    this.label = "Provided Text: " 
                        + form.inputTextBox.get_Text();
                }
            }
        }
        parent.UpdateServiceCoverage();
    } //OnMouseDown

    // Method accesses the TextService to test the visibility of the
 
    // service from the control, and sets the UI state accordingly.
    public void ReflectServiceVisibility()
    {
        if (state_.Equals(new TextServiceState(
            TextServiceState.ServiceObtained))) {
            if (GetService(TextService.class.ToType())
 == null) {
                this.set_BackColor(Color.get_CadetBlue());
            }
        }
        else {
            if (!(state_.Equals(new TextServiceState(
                TextServiceState.ServiceProvided)))) {
                if (GetService(TextService.class.ToType())
 == null) {
                    this.set_BackColor(Color.get_White());
                    return;
                }

                // Service available.        
                if (state_.Equals(new TextServiceState(
                    TextServiceState.ServiceNotFound))) {
                    this.set_BackColor(Color.get_Khaki());
                }
                else {
                    if (state_.Equals(new TextServiceState(
                        TextServiceState.ServiceNotObtained)) 
                        && !(label.Equals("Service Removed")))
 {
                        this.set_BackColor(Color.get_Khaki());
                    }
                }
            }
        }
    } //ReflectServiceVisibility

    // ServiceCreatorCallback method creates a text service.
    private Object CreateTextService(
        IServiceContainer container, System.Type serviceType)
    {
        return new TextService("Test Callback");
    } //CreateTextService
} //ServiceContainerControl
      
   // Example form provides UI for demonstrating service sharing behavior
 
   // of a network of IServiceContainer/IServiceProvider controls.
public class ServiceForm extends System.Windows.Forms.Form
{
    // Root service container control for tree.
    private ServiceContainerControl root;

    // Button for clearing any provided services and resetting tree
 states.
    private System.Windows.Forms.Button reset_button;

    // Color list used to color code controls.
    private Color colorkeys[];

    // Strings used to reflect text service.
    private String keystrings[];

    public ServiceForm()
    {
        InitializeComponent();
        colorkeys = new Color[] { Color.get_Beige(), Color.get_SeaShell(),
 
            Color.get_LightGreen(), Color.get_LightBlue(), Color.get_Khaki(), 
            Color.get_CadetBlue() };
        keystrings = new String[] { "No service use",
 "Service not accessible", 
            "Service provided", "Service obtained", "Service
 accessible", 
            "No further access" };
        CreateServiceControlTree();
    } //ServiceForm

    private void CreateServiceControlTree()
    {
        // Create root service control
        ServiceContainerControl control1 = new ServiceContainerControl(null,
 
            new Size(300, 40), new Point(10,
 80), this);
        root = control1;

        // Create first tier - pass parent with service object control
 1.
        ServiceContainerControl control2 = new ServiceContainerControl(control1,
 
            new Size(200, 30), new Point(50,
 160), this);
        ServiceContainerControl control3 = new ServiceContainerControl(control1,
 
            new Size(200, 30), new Point(50,
 240), this);

        // Create second tier A - pass parent with service object control
 2.
        ServiceContainerControl control4 = new ServiceContainerControl(control2,
 
            new Size(180, 20), new Point(300,
 145), this);
        ServiceContainerControl control5 = new ServiceContainerControl(control2,
 
            new Size(180, 20), new Point(300,
 185), this);

        // Create second tier B - pass parent with service object control
 3.
        ServiceContainerControl control6 = new ServiceContainerControl(control3,
 
            new Size(180, 20), new Point(300,
 225), this);
        ServiceContainerControl control7 = new ServiceContainerControl(control3,
 
            new Size(180, 20), new Point(300,
 265), this);

        // Add controls
        this.get_Controls().AddRange(new Control[]
 { control1, control2, 
            control3, control4, control5, control6, control7 });
    } //CreateServiceControlTree

    public void ResetServiceTree(Object sender,
 EventArgs e)
    {
        // Remove the service from the service tree.
        if (root.GetService(TextService.class.ToType())
 != null) {
            root.RemoveService(TextService.class.ToType(), true);
        }

        // Set all controls to "not obtained" and clear their
 labels.
        for (int i = 0; i < get_Controls().get_Count();
 i++) {
            if (!(get_Controls().get_Item(i).Equals(reset_button)))
 {
                ((ServiceContainerControl)(get_Controls().get_Item(i))).
                    set_state(new TextServiceState(
                    TextServiceState.ServiceNotObtained));
                ((ServiceContainerControl)(
                    get_Controls().get_Item(i))).label ="" ;
                ((ServiceContainerControl)(get_Controls().get_Item(i))).
                    set_BackColor(Color.get_Beige());
            }
        }
    } //ResetServiceTree

    public void UpdateServiceCoverage()
    {
        // Have each control set state to reflect service availability.
        for (int i = 0; i < get_Controls().get_Count();
 i++) {
            if (!(get_Controls().get_Item(i).Equals(reset_button)))
 {
                ((ServiceContainerControl)(get_Controls().get_Item(i))).
                    ReflectServiceVisibility();
            }
        }
    } //UpdateServiceCoverage

    private void InitializeComponent()
    {
        this.reset_button = new System.Windows.Forms.Button();
        this.SuspendLayout();

        // 
        // reset_button
        // 
        this.reset_button.set_Location(new
 System.Drawing.Point(392, 88));
        this.reset_button.set_Name("reset_button");
        this.reset_button.set_TabIndex(0);
        this.reset_button.set_TabStop(false);
        this.reset_button.set_Text("Reset");
        this.reset_button.add_Click(new System.EventHandler(
            this.ResetServiceTree));

        // 
        // ServiceForm
        // 
        this.set_ClientSize(new System.Drawing.Size(512,
 373));
        this.get_Controls().AddRange(new System.Windows.Forms.Control[]
 
            { this.reset_button });
        this.set_MinimumSize(new System.Drawing.Size(520,
 400));
        this.set_Name("ServiceForm");
        this.set_Text("Service Container Architecture Example");
        this.ResumeLayout(false);
    } //InitializeComponent

    /** @attribute STAThread()
     */
    public static void main(String[]
 args)
    {
        Application.Run(new ServiceForm());
    } //main

    protected void OnPaint(System.Windows.Forms.PaintEventArgs
 e)
    {
        e.get_Graphics().DrawString("The following tree diagram represents a
 " 
            + "hierarchy of linked service containers in
 controls.", 
            new Font("Arial", 9), new
 SolidBrush(Color.get_Black()), 4, 4);
        e.get_Graphics().DrawString("This example demonstrates the propagation
 " 
            + "behavior of services through a linked service object tree.",
 
            new Font("Arial", 8), new
 SolidBrush(Color.get_Black()), 4, 26);
        e.get_Graphics().DrawString("Right-click a component to add or "
            +"replace a " + "text service, or to remove it if
 the component"
            +" provided it.", new Font("Arial",
 8), 
            new SolidBrush(Color.get_Black()), 4, 38);
        e.get_Graphics().DrawString("Left-click a component to update text from
 "
            + "the text service if available.", new
 Font("Arial", 8), 
            new SolidBrush(Color.get_Black()), 4, 50);

        // Draw lines to represent tree branches.
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            20, 125, 20, 258);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            21, 175, 45, 175);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1),
            21, 258, 45, 258);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            255, 175, 285, 175);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            255, 258, 285, 258);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            285, 155, 285, 195);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            285, 238, 285, 278);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            285, 155, 290, 155);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            285, 195, 290, 195);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            285, 238, 290, 238);
        e.get_Graphics().DrawLine(new Pen(new
 SolidBrush(Color.get_Black()), 1), 
            285, 278, 290, 278);

        // Draw color key.
        e.get_Graphics().DrawRectangle(new Pen(new
 SolidBrush(Color.get_Black()),
            1), 20, 305, 410, 60);
        int y = 0;
        for (int i = 0; i < 3; i++) {
            e.get_Graphics().FillRectangle(new SolidBrush(colorkeys[y]),
 
                25 + i * 140, 310, 20, 20);
            e.get_Graphics().DrawRectangle(new Pen(new
 SolidBrush(
                Color.get_Black()), 1), 25 + i * 140, 310, 20, 20);
            e.get_Graphics().DrawString(keystrings[y], new Font("Arial",
 8), 
                new SolidBrush(Color.get_Black()), 50 + i * 140,
 315);
            y++;
            e.get_Graphics().FillRectangle(new SolidBrush(colorkeys[y]),
 
                25 + i * 140, 340, 20, 20);
            e.get_Graphics().DrawRectangle(new Pen(new
 SolidBrush(Color.get_Black()), 
                1), 25 + i * 140, 340, 20, 20);
            e.get_Graphics().DrawString(keystrings[y], new Font("Arial",
 8), 
                new SolidBrush(Color.get_Black()), (50 + i * 140),
 345);
            y++;
        }
    } //OnPaint
} //ServiceForm
      
   // Example service type contains a text string, sufficient to 
   // demonstrate service sharing.
public class TextService
{
    public String text;

    public TextService()
    {
        this("");
    } //TextService

    public TextService(String text)
    {
        this.text = text;
    } //TextService
} //TextService
   
public class TextServiceState
{
    public int member;
    TextServiceState()
    { 
        member = 1;
    }
    TextServiceState(int n)
    {
        member = n;
    }
    public static int ServiceNotObtained
 = 1;
    public static int ServiceObtained
 = 2;
    public static int ServiceProvided
 = 3;
    public static int ServiceNotFound
 = 4;
} //TextServiceState
   
   // Example Form for entering a string.
class StringInputDialog extends System.Windows.Forms.Form
{
    private System.Windows.Forms.Button ok_button;
    private System.Windows.Forms.Button cancel_button;
    public System.Windows.Forms.TextBox inputTextBox;

    public StringInputDialog(String text)
    {
        InitializeComponent();
        inputTextBox.set_Text(text);
    } //StringInputDialog

    private void InitializeComponent()
    {
        this.ok_button = new System.Windows.Forms.Button();
        this.cancel_button = new System.Windows.Forms.Button();
        this.inputTextBox = new System.Windows.Forms.TextBox();
        this.SuspendLayout();
        this.ok_button.set_Anchor(System.Windows.Forms.AnchorStyles.Bottom
 
            | System.Windows.Forms.AnchorStyles.Right);
        this.ok_button.set_Location(new System.Drawing.Point(180,
 43));
        this.ok_button.set_Name("ok_button");
        this.ok_button.set_TabIndex(1);
        this.ok_button.set_Text("OK");
        this.ok_button.set_DialogResult(System.Windows.Forms.DialogResult.OK);
        this.cancel_button.set_Anchor(System.Windows.Forms.AnchorStyles.Bottom
 
            | System.Windows.Forms.AnchorStyles.Right);
        this.cancel_button.set_Location(new
 System.Drawing.Point(260, 43));
        this.cancel_button.set_Name("cancel_button");
        this.cancel_button.set_TabIndex(2);
        this.cancel_button.set_Text("Cancel");
        this.cancel_button.set_DialogResult(
            System.Windows.Forms.DialogResult.Cancel);
        this.inputTextBox.set_Location(new
 System.Drawing.Point(6, 9));
        this.inputTextBox.set_Name("inputTextBox");
        this.inputTextBox.set_Size(new System.Drawing.Size(327,
 20));
        this.inputTextBox.set_TabIndex(0);
        this.inputTextBox.set_Text("");
        this.inputTextBox.set_Anchor(System.Windows.Forms.AnchorStyles.Top
 
            | System.Windows.Forms.AnchorStyles.Left 
            | System.Windows.Forms.AnchorStyles.Right);
        this.set_ClientSize(new System.Drawing.Size(342,
 73));
        this.get_Controls().AddRange(new System.Windows.Forms.Control[]
 
            { this.inputTextBox, this.cancel_button,
 this.ok_button });
        this.set_MinimumSize(new System.Drawing.Size(350,
 100));
        this.set_Name("StringInputDialog");
        this.set_Text("Text Service Provide String Dialog");
        this.ResumeLayout(false);
    } //InitializeComponent
} //StringInputDialog
プラットフォームプラットフォーム
バージョン情報バージョン情報
参照参照
関連項目
IServiceContainer メンバ
System.ComponentModel.Design 名前空間
IDesignerHost インターフェイス
IServiceProvider

IServiceContainer メソッド


IServiceContainer メンバ




英和和英テキスト翻訳>> Weblio翻訳
英語⇒日本語日本語⇒英語
  

辞書ショートカット

すべての辞書の索引

「IServiceContainer」の関連用語

IServiceContainerのお隣キーワード
検索ランキング

   

英語⇒日本語
日本語⇒英語
   



IServiceContainerのページの著作権
Weblio 辞書 情報提供元は 参加元一覧 にて確認できます。

   
日本マイクロソフト株式会社日本マイクロソフト株式会社
© 2025 Microsoft.All rights reserved.

©2025 GRAS Group, Inc.RSS