修复通用UserControl的嵌入资源

时间:2009-10-26 21:28:39

标签: c# .net winforms generics designer

在重构过程中,我向MyControl添加了一个泛型类型参数,这是一个派生自UserControl的类。所以我的班级现在是MyControl<T>

现在我在运行时遇到错误,指出无法找到嵌入式资源文件 MyControl`1.resources 。快速查看.NET Reflector表示资源文件实际上名为 MyControl.resources ,没有`1

MyControl<T>.InitializeComponent方法开始时,这条线可能是造成问题的线:

 System.ComponentModel.ComponentResourceManager resources =
    new System.ComponentModel.ComponentResourceManager(
       typeof(MyControl<>));

如何强制ComponentResourceManager使用嵌入资源文件MyControl.resources?其他解决此问题的方法也很受欢迎。

4 个答案:

答案 0 :(得分:18)

事实证明,您可以通过继承ComponentResourceManager来覆盖要加载的资源文件名:

   using System;
   using System.ComponentModel;

   internal class CustomComponentResourceManager : ComponentResourceManager
   {
      public CustomComponentResourceManager(Type type, string resourceName)
         : base(type)
      {
         this.BaseNameField = resourceName;
      }
   }

现在我可以确保资源管理器像这样加载MyControl.resources

 System.ComponentModel.ComponentResourceManager resources =
    new CustomComponentResourceManager(typeof(MyControl<>), "MyControl");

这似乎有效。

编辑:如果您使用设计器,则会覆盖上面的行,因为它位于 生成代码区域。我避开设计师并使用版本控制工具来恢复任何不需要的更改,但解决方案并不理想。

答案 1 :(得分:16)

除了Wim的技术之外,您还可以声明一个与泛型类同名的非泛型基本控件,并使您的泛型控件/表单派生自该非泛型基类。

通过这种方式,您可以欺骗设计人员和编译器使用泛型类中的资源文件,并且一旦设置了基类,您就可以获得永久的设计器支持,而无需在每次重建时都放入.designer文件: / p>

// Empty stub class, must be in a different file (added as a new class, not UserControl 
// or Form template)
public class MyControl : UserControl
{
}

// Generic class
public class MyControl<T> : MyControl
{
     // ...
}

唯一的要求是为您的泛型类及其基类提供完全相同的名称,并且基类必须位于另一个类文件中,否则设计者会抱怨找不到其中一个两个班。

PS。我用表单测试了这个,但它应该与控件一样。

答案 2 :(得分:4)

Visual Studio 2008我有这个错误:

  

System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MyControl));

使用泛型类型'WindowsFormsApplication1.UserControl1'需要'1'类型参数。

请注意,在我的案例中,代码是在类名后面生成没有括号<>的。

它变得有趣,请参阅 ImageList autogenerates non-compiling code in a Generic User Control

他们说了什么:

  

Microsoft于2005年7月6日下午2:49发布

     

这是一个有趣的错误。您已经遇到了我们在Windows窗体设计器中不支持的通用scneario。我们将无法在Whidbey(我的注释:Visual Studio 2008?)版本中添加对此的支持。我们将在未来的版本中考虑这一点。作为一种变通方法,您可以使用设计器创建一个具有公共Type属性的非泛型UserControl,然后创建一个继承自它的泛型类,并将T传递给基类Type属性。

我认为无法在Visual Studio窗体设计器中设计此控件。

答案 3 :(得分:3)

最简单,最简单的解决方法是为自动生成的typeof()创建一个虚拟类。您不需要继承它,甚至不需要将它暴露给外部:

// Non-generic name so that autogenerated resource loading code is happy
internal sealed class GridEditorForm
{
}

(根据我的经验,让设计师围绕仿制药工作所需的时间并不值得理想的冷却仿制品所能提供的。我不会再使用通用的Windows窗体或控件。)