다음을 통해 공유


확장 가능한 개체

확장 가능한 개체 패턴은 기존 런타임 클래스를 새 기능으로 확장하거나 개체에 새 상태를 추가하는 데 사용됩니다. 처리의 매우 다른 단계에서 동작을 사용할 수 있게 하는 확장은 확장 가능한 개체 중 하나에 연결되며, 이로 인해 사용자는 공통 확장 가능한 개체에 연결된 공유 상태 및 기능에 접근할 수 있습니다.

IExtensibleObject<T> 패턴

확장 가능한 개체 패턴에는 IExtensibleObject<T>, IExtension<T>IExtensionCollection<T>세 가지 인터페이스가 있습니다.

IExtensibleObject<T> 인터페이스는 IExtension<T> 개체가 해당 기능을 사용자 지정할 수 있도록 하는 형식에 의해 구현됩니다.

확장 가능한 개체는 IExtension<T> 개체의 동적 집계를 허용합니다. IExtension<T> 개체는 다음 인터페이스로 특징지어집니다.

public interface IExtension<T>
where T : IExtensibleObject<T>
{
    void Attach(T owner);
    void Detach(T owner);
}

형식 제한은 IExtensibleObject<T>클래스에 대해서만 확장을 정의할 수 있도록 합니다. AttachDetach이 집계 또는 해제에 대한 알림을 제공합니다.

구현이 소유자에서 추가 및 제거될 수 있는 시기를 제한하는 것이 유효합니다. 예를 들어 소유자 또는 확장이 특정 상태에 있을 때 확장을 추가 또는 제거하는 것을 허용하지 않거나, 여러 소유자에 동시에 추가할 수 없도록 하거나, 단 한 번의 추가와 단일 제거만 허용하여 제거를 완전히 허용하지 않도록 할 수 있습니다.

IExtension<T> 다른 표준 관리 인터페이스와의 상호 작용을 의미하지는 않습니다. 특히 소유자 개체의 IDisposable.Dispose 메서드는 일반적으로 해당 확장을 분리하지 않습니다.

확장이 컬렉션에 추가되면 컬렉션에 들어가기 전에 Attach 호출됩니다. 확장이 컬렉션에서 제거되면 제거된 후 Detach 호출됩니다. 즉,(적절한 동기화를 가정) 확장은 AttachDetach사이에 있는 동안 컬렉션에서만 찾을 수 있습니다.

FindAll 또는 Find에 전달되는 개체는 반드시 IExtension<T>일 필요는 없으며(예를 들어, 어떤 개체라도 전달할 수 있음), 반환된 확장명은 IExtension<T>입니다.

컬렉션에 IExtension<T>확장이 없으면 Find null을 반환하고 FindAll 빈 컬렉션을 반환합니다. 여러 확장이 IExtension<T>구현하는 경우 Find 그 중 하나를 반환합니다. FindAll 반환된 값은 스냅샷입니다.

두 가지 주요 시나리오가 있습니다. 첫 번째 시나리오에서는 Extensions 속성을 형식 기반 사전으로 사용하여 개체에 상태를 삽입하여 다른 구성 요소가 형식을 사용하여 검색할 수 있도록 합니다.

두 번째 시나리오에서는 AttachDetach 속성을 사용하여 이벤트 등록, 상태 전환 감시 등과 같은 사용자 지정 동작에 개체가 참여할 수 있도록 합니다.

IExtensionCollection<T> 인터페이스는 형식별로 IExtension<T> 검색할 수 있는 IExtension<T> 개체의 컬렉션입니다. IExtensionCollection<T>.Find 가장 최근에 추가된 해당 형식의 IExtension<T> 개체를 반환합니다.

Windows Communication Foundation의 확장 가능한 개체

WCF(Windows Communication Foundation)에는 4개의 확장 가능한 개체가 있습니다.

  • ServiceHostBase – 서비스 호스트의 기본 클래스입니다. 이 클래스의 확장은 ServiceHostBase 자체의 동작을 확장하거나 각 서비스에 대한 상태를 저장하는 데 사용할 수 있습니다.

  • InstanceContext – 이 클래스는 서비스 유형의 인스턴스를 서비스 런타임에 연결합니다. 인스턴스에 대한 정보와 InstanceContext가 포함하고 있는 ServiceHostBase에 대한 참조가 포함되어 있습니다. 이 클래스의 확장은 InstanceContext 동작을 확장하거나 각 서비스의 상태를 저장하는 데 사용할 수 있습니다.

  • OperationContext – 이 클래스는 런타임이 각 작업에 대해 수집하는 작업 정보를 나타냅니다. 여기에는 들어오는 메시지 헤더, 들어오는 메시지 속성, 들어오는 보안 ID 및 기타 정보와 같은 정보가 포함됩니다. 이 클래스의 확장은 OperationContext 동작을 확장하거나 각 작업에 대한 상태를 저장할 수 있습니다.

  • IContextChannel – 이 인터페이스를 사용하면 WCF 런타임에서 빌드한 채널 및 프록시에 대한 각 상태를 검사할 수 있습니다. 이 클래스의 확장은 IClientChannel 동작을 확장하거나 각 채널의 상태를 저장하는 데 사용할 수 있습니다.

다음 코드 예제에서는 간단한 확장을 사용하여 InstanceContext 개체를 추적하는 방법을 보여줍니다.

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace Microsoft.WCF.Documentation
{
    public class MyInstanceContextInitializer : IInstanceContextInitializer
    {
        public void Initialize(InstanceContext instanceContext, Message message)
        {
            MyInstanceContextExtension extension = new MyInstanceContextExtension();

            //Add your custom InstanceContext extension that will let you associate state with this instancecontext
            instanceContext.Extensions.Add(extension);
        }
    }

    //Create an Extension that will attach to each InstanceContext and let it retrieve the Id or whatever state you want to associate
    public class MyInstanceContextExtension : IExtension<InstanceContext>
    {

        //Associate an Id with each Instance Created.
        string _instanceId;

        public MyInstanceContextExtension()
        { _instanceId = Guid.NewGuid().ToString(); }

        public string InstanceId => _instanceId;

        public void Attach(InstanceContext owner)
        {
            Console.WriteLine("Attached to new InstanceContext.");
        }

        public void Detach(InstanceContext owner)
        {
            Console.WriteLine("Detached from InstanceContext.");
        }
    }

    public class InstanceInitializerBehavior : IEndpointBehavior
    {

        public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters)
        { }

        //Apply the custom IInstanceContextProvider to the EndpointDispatcher.DispatchRuntime
        public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
        {
            MyInstanceContextInitializer extension = new MyInstanceContextInitializer();
            endpointDispatcher.DispatchRuntime.InstanceContextInitializers.Add(extension);
        }

        public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
        { }

        public void Validate(ServiceEndpoint endpoint)
        { }
    }

    public class InstanceInitializerBehaviorExtensionElement : BehaviorExtensionElement
    {

        public override Type BehaviorType
        {
            get { return typeof(InstanceInitializerBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new InstanceInitializerBehavior();
        }
    }
}

참고하십시오