我有一个实现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";
是我资源类中字符串变量的引用。 我的想法是希望从静态类型中获益(如果我重命名资源,我会得到设计时错误而不是运行时错误)。
有没有办法实现这个目标?
答案 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
});