디자인 타임 컬렉션을 관리하는 데에 어려움이 있으십니까?

Windows Forms, ASP .NET Web Form 디자이너의 경우, 디자인 타임에 대한 의존도가 상당히 높은 편입니다. 그리고 이러한 디자인 타임 상의 구현을 완료하는데에 있어서 흔히 겪게 되는 문제가 있는데, 바로 컬렉션에 대한 처리입니다.


디자인 타임을 위한 컬렉션의 초기화 방법은 달라야 합니다.


디자인 타임을 위한 컬렉션의 초기화 방법은 런타임때와는 달라야 합니다. 객체를 생성하고 호출하는 방법이 우리가 이해하는 런타임 때와는 다르며, 컬렉션은 이를 준수하기 위해서 지연된 초기화 과정을 거쳐야 합니다. 다음은 디자인 타임용 컬렉션을 초기화하는 프로퍼티의 한 예시입니다.


internal ArrayList internalObjCollection = new ArrayList(); // 나중에 설명할 부분입니다.
private ObjectCollection objCollection = null; // 생성자나 인라인 식에서 초기화하지 않습니다. 대신…


[Browsable(true)]
[Category(ForexRuntime.ForexCategoryName)]
[Editor(typeof(CollectionEditor), typeof(UITypeEditor))]
[Description(“속성에 대한 설명을 여기에 지정합니다.”)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ObjectCollection Collection {
    get {
        if (objCollection == null) objCollection = new ObjectCollection(this);
        return objCollection;
    }
}


위의 예시에서처럼 지연된 초기화를 사용한다는 점을 기억해야 합니다. 또한, 디자인 타임 컬렉션이 갖추어야 할 추가적인 조건이 한 가지 더 있는데, 디자인 타임 컬렉션은 철저히 프록시 역할을 수행해야 한다는 점입니다. 위에서 언급한 ObjectCollection의 생성자 호출 시 부모 객체의 참조를 넘겨받는 다는 점을 유심히 살펴보아야 합니다. 그리고 ObjectCollection은 컬렉션으로서 준수해야 할 기본적인 인터페이스 구현만을 포함해야 하며 실제로 모든 객체 관리는 다시 internalObjCollection 이라는 별도의 컬렉션에서 관리가 이루어지게 된다는 점입니다.


[Serializable]
[DesignTimeVisible(true)]
public class OutputFieldDefineCollection : IList { … }


컬렉션 클래스 자체에는, 디자인 타임과의 원활한 상호 작용을 위하여 DesignTimeVisibleAttribute 속성이 추가된 것을 확인해 둡니다. 그리고 이 컬렉션의 생성자 형식에서 수용하기로 한 원본 객체의 참조는, 원본 객체 내부의 ArrayList에 접근하기 위한 목적으로 사용되고, 이 클래스가 구현하기로 한 IList 및 다른 인터페이스는 원본 객체 내부의 ArrayList를 기준으로 컬렉션의 기능을 제공하도록 코드를 작성합니다.


생성자와 IContainer 인터페이스의 역할은 매우 중요합니다.


추가하기로 한 컴포넌트에서 각별히 신경써야 할 것은, 바로 컨테이너의 기본 생성자와 더불어서 IContainer 객체의 참조를 받는 생성자로 적어도 2가지 생성자가 항상 제공되어야 합니다. 예를 들어, BookComponent가 있다고 가정해 보겠습니다.


public class BookComponent : Component {
    public BookComponent() : this(null) { }
    public BookComponent(IContainer container) : base() {
        if (container != null) { container.Add(this); }
        // 이곳에 생성자 코드를 지정하거나, this.InitializeComponent() 메서드를 호출합니다.
    }
}


위와 같은 코드가 있다고 하였을 때, 보통 container의 Add 메서드를 별 다른 생각없이 부릅니다. 하지만 여기에 숨겨진 기능이 하나 더 있는데, Add 메서드에는 디자인 타임에서 사용할 변수의 이름을 지정할 수 있는 인자가 제공된다는 점입니다. Add 메서드의 두 번째 오버로드를 사용하면 쉽게 변수의 이름을 다시 정의할 수 있는 것입니다. 단, 중복되는 변수 이름이 발생하지 않도록 정교한 명명 규칙이 필요함을 유의해야합니다.


또한, 별도의 디자이너가 존재하는 경우, 가능하면 컴포넌트의 생성자 메서드의 실행이 끝나기 전에 필요한 모든 초기화 작업을 수행하는 것이 좋으며 여기에는 앞서 설명한 Add 메서드의 활용은 물론 컴포넌트 자체의 설정에 관한 부분들도 포함됩니다.

댓글 남기기