Можно ли контролировать, как IExtenderProvider форматирует выходные данные в коде конструктора Windows Forms?

У меня есть класс, который реализует IExtenderProvider

Вот отличная статья об этом интерфейсе http://www.codeproject.com/Articles/4683/Getting-to-know-IExtenderProvider

Основная идея состоит в том, чтобы выбрать элемент управления в окнах форм desinger и иметь "виртуальное" свойство MyProperty on MyExtender

Подсказка делает то же самое.

Это работает, как и ожидалось, и дизайнерский код выглядит так

this.label1.AutoSize = true;
...
this.myExtender1.SetMyProperty(this.label1, "MyValue");
...
this.label1.Name = "label1";
this.label1.Text = "label1";

Разрешается вводить строки ресурсов из определенного файла ресурсов только через раскрывающееся меню в сетке свойств. Теперь то, что я хочу достичь, это

this.label1.AutoSize = true;
....
this.myExtender1.SetMyProperty(this.label1, 
                 My.Namespace.Properties.Resources.MyValue);
...
this.label1.Name = "label1";
this.label1.Text = "label1";

которая является ссылкой на строковую переменную в моем классе ресурсов. Идея состоит в том, что я хочу извлечь выгоду из статической типизации (если я переименую ресурс, я получаю ошибки времени разработки, а не ошибки времени выполнения).

Есть ли способ достичь этого?

1 ответ

Решение

Эта статья Тима Ван Вассенхова под названием " Сгибание генерации кода IExtenderProvider к вашей воле " может решить вашу проблему.

Говорится:

В " Изучении CodeDomSerializer" я уже объяснил, как мы можем изменить код, который сгенерирует для нас дизайнер Visual Studio. С типичным IExtenderProvider конструктор генерирует инициализатор, методы SetXXX и объявление переменной...

Теперь, что если мы не довольны этими сгенерированными методами SetXXX для каждого компонента? Проблема заключается в том, что этот код генерируется не сериализатором для ConstantsExtenderProvider, а сериализаторами для компонентов. Простым решением этой проблемы является установка атрибута DesignerSerializationVisibilityAttribute для метода GetXXX в нашем IExtenderProvider на Hidden.

С этими уродливыми методами SetXXX мы можем сделать это лучше. Мы делаем это путем реализации собственного сериализатора для нашего ConstantsExtenderProvider:

class ConstantsSerializer<t> : CodeDomSerializer
{
 public override object Serialize(IDesignerSerializationManager manager, object value)
 {
  ConstantsExtenderProvider provider = value as ConstantsExtenderProvider;
 
  CodeDomSerializer baseClassSerializer = manager.GetSerializer(typeof(ConstantsExtenderProvider).BaseType, typeof(CodeDomSerializer)) as CodeDomSerializer;
  CodeStatementCollection statements = baseClassSerializer.Serialize(manager, value) as CodeStatementCollection;
 
  IDesignerHost host = (IDesignerHost)manager.GetService(typeof(IDesignerHost));
  ComponentCollection components = host.Container.Components;
  this.SerializeExtender(manager, provider, components, statements);
 
  return statements;
 }
 
 private void SerializeExtender(IDesignerSerializationManager manager, ConstantsExtenderProvider provider, ComponentCollection components, CodeStatementCollection statements)
 {
  foreach (IComponent component in components)
  {
   Control control = component as Control;
   if (control != null && (control as Form == null))
   {
    CodeMethodInvokeExpression methodcall = new CodeMethodInvokeExpression(base.SerializeToExpression(manager, provider), "SetConstants");
    methodcall.Parameters.Add(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), control.Name));
 
    string[] constants = provider.GetConstants(control);
    if (constants != null)
    {
     StringBuilder sb = new StringBuilder();
     sb.Append("new string[] { ");
 
     foreach (string constant in constants)
     {
      sb.Append(typeof(T).FullName);
      sb.Append(".");
      sb.Append(constant);
      sb.Append(", ");
     }
 
     sb.Remove(sb.Length - 2, 2);
     sb.Append(" }");
 
     methodcall.Parameters.Add(new CodeSnippetExpression(sb.ToString()));
    }
    else
    {
     methodcall.Parameters.Add(new CodePrimitiveExpression(null));
    }
 
    statements.Add(methodcall);
   }
  }
 }
}

И теперь сгенерированный код выглядит так:

this.constantsExtenderProvider1.SetConstants(this.button1, new string[] {
    WindowsApplication1.Constants.Operation1,
    WindowsApplication1.Constants.Operation5
});
Другие вопросы по тегам