Безопасно ли вызывать MemberwiseClone() для пользовательских серверных элементов управления?

Я написал собственный серверный элемент управления, который (псевдокод) выглядит так:

public class MyCustomCtrl : WebControl
{
   private Button innerCtrl; //some arbitrary object, doesn't matter

   ...

   protected override void CreateChildControls()
   {
      //initialization etc, as standard...

   }

}

Теперь у меня есть случай, когда мне нужно скопировать этот настраиваемый серверный элемент управления. В основном он добавляется программистом декларативно в коде aspx или ascx. Во время выполнения необходимо создать несколько экземпляров этого элемента управления, которые затем добавляются к некоторому родительскому элементу управления. Однако это обрабатывается в контексте этого родительского элемента управления.

В любом случае, немного сложно объяснить контекст использования. Однако мой главный вопрос заключается в том, безопасно ли использовать «клонирование», особенно для вызова MemberwiseClone() в веб-элементах управления? Что я сделал до сих пор, так это добавил такой метод, как

public class MyCustomCtrl : WebControl
{
   ...

   public object Clone(){
      MyCustomCtrl clone = MemberwiseClone() as MyCustomCtrl;
      clone.InnerCtrl = this.innerCtrl.Clone() as Button; //or whatever type

      return clone;
   }
}

Я имею в виду, что иерархия элементов управления ASP.net представляет собой довольно сложную модель. Поэтому я хотел услышать, знает ли кто-нибудь из вас какие-либо недостатки, которые могут возникнуть при использовании такого решения.


person Juri    schedule 04.09.2009    source источник


Ответы (1)


Нет, это небезопасная операция по очень общей причине: MemberwiseClone — это поверхностная, а не глубокая копия.

Таким образом, такие вещи, как ViewState, совместно используются вашим исходным элементом управления и клоном. Но коллекция Controls также является общей, поэтому любые изменения в исходной коллекции Controls распространяются на клон. Элементы управления используют намного больше скрытых ссылок для поддержания состояния (таких как стиль, события и т. д.), поэтому MemberwiseClone — очень опасная вещь.

Единственный способ повторно использовать элементы управления в качестве своего рода шаблона — использовать шаблоны (ITemplate), которые имеют метод InstantiateIn, создающий новую иерархию элементов управления. Я предлагаю вам взглянуть на такие элементы управления, как Repeater, которые делают это.

person Ruben    schedule 04.09.2009
comment
хм.. этого я и ожидал. Я уже разработал элементы управления с использованием шаблонов, и на самом деле тот, что выше, используется в контексте элемента управления, который обертывает элемент управления повторителем. Проще говоря, пользователь один раз определяет элемент управления MyCustomCtrl в ParentControl, который внутренне обертывает повторитель. Поэтому при обработке ItemTemplate повторителя я должен скопировать MyCustomCtrl и прикрепить его к каждому RepeaterItem (в основном к строке). Вот почему мне нужна функция копирования. - person Juri; 05.09.2009