是否可以控制IExtenderProvider如何格式化Windows窗体设计器代码中的输出?

时间:2013-12-06 07:34:42

标签: c# .net winforms windows-forms-designer

我有一个实现IExtenderProvider

的类

以下是关于该界面http://www.codeproject.com/Articles/4683/Getting-to-know-IExtenderProvider

的精彩文章

基本思路是在windows窗体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 个答案:

答案 0 :(得分:2)

Tim Van Wassenhove的这篇题为“Bending the code generation of IExtenderProvider to your will”的文章可能会解决您的问题。

它声明:

  

Exploring CodeDomSerializer中,我已经解释了如何修改Visual Studio设计器为我们生成的代码。使用典型的IExtenderProvider,设计器会生成初始化程序,SetXXX方法和变量声明......

     

现在,如果我们对每个组件上生成的SetXXX方法不满意怎么办?问题是此代码不是由ConstantsExtenderProvider的序列化程序生成的,而是由组件的序列化程序生成的。解决此问题的一个简单方法是将IExtenderProvider中GetXXX方法的DesignerSerializationVisibilityAttribute设置为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
});