Visual Studio 为什么C#设计器生成的代码(如Form1.designer.cs)会对Subversion造成严重破坏?

axkjgtzd  于 2022-12-23  发布在  C#
关注(0)|答案(6)|浏览(250)

我的工作室最近从SourceSafe切换到了Subversion,使我们从自动锁定中解放出来。这导致了表单的并发编辑,这很棒。但是当多个开发人员提交他们的更改时,由设计者创建的代码文件(所有名为TheFormName.designer.cs的文件)会导致冲突,这是非常难以解决的。
据我所知,这是因为无论用户何时修改设计器生成的代码,不管实际的更改有多小,它都会被大量地重新排列。

  • 如何使这些冲突更容易解决?
  • 有没有什么方法可以告诉设计师少修改代码?
  • 作为经验丰富的C#团队,您如何处理表单的并发修改?
3hvapo4f

3hvapo4f1#

下面是一些可以尝试的方法:

  • 让事情更模块化。使用用户控件等组件将表单拆分成多个更小的物理文件。
  • 使用表示层设计模式(如MVP)将代码移出视图并移入标准POCO类。
  • SVN的最新版本允许您使用硬锁-使用此功能可以避免复杂的合并场景。

希望能有所帮助。

5m1hhzi4

5m1hhzi42#

我敢肯定,没有银解决这个问题,因为设计师踩在所有的设计师。
我所能建议的就是尽量少用设计器。我个人只在代码中挂钩事件,只在初始化和定位时使用设计器。因此,不难理解变更集中的差异(“哦,有人添加了一个按钮”,“哦,有人稍微改变了它的外观”)。

ff29svar

ff29svar3#

是的,设计师的随机重新安排确实令人恼火。微软使用他们自己的工具吗?微软看他们签入版本控制吗?这让人难以置信。
我们团队的“解决方案”是在编辑完Designer文件后手动编辑它们,将内容放回原来的位置,这样基于文本的diff是可读的,并且并发的更改可以被合理地合并。幸运的是,Visual Studio的大多数重新排列都是头脑简单的,所以这是可行的。
遗憾的是,我们发现这一步对于验证正确性是必要的--我们发现设计器悄悄地删除了需要的东西,导致了代码损坏。所以必须完成这一步,以便解决隐藏在其中的任何数据破坏错误。
由于微软在修复bug方面的记录很差,唯一的解决方案可能是改进Mono's WinForms Designer,以便为黄金时期做好准备。

lnxxn5zx

lnxxn5zx4#

我不熟悉C#或Windows窗体设计器,但看看我可以在网上找到的一些designer.cs文件,它们没有特别复杂的结构。
它的哪些部分被重新安排了?我猜主要是InitializeComponent()方法中属性的顺序被打乱了?
如果是这样的话,你可以写一个简单的脚本,把这些行按字母顺序重新排序(特别是如果你从来没有手动编辑过这些文件),并把它作为Subversion中的pre-commit钩子脚本.
嗯,好吧......把它划掉。那部分底部的大红框说你不应该修改钩子脚本中的事务。但是你也许可以找到另一种方法在designer.cs文件被修改和被提交之间的某个地方运行那个脚本。

编辑:

实际上,根据scraimer的评论:
总黑客,但在最坏的情况下,就在合并之前,我可以排序两个文件,并使合并简单地一行一行的事情...
难道不能让Subversion设置一个外部合并程序吗?我一直在使用KDiff3,它可以run a preprocessor command before doing diffs or merges,所以可以自动化这个过程.

luaexgnf

luaexgnf5#

的确,设计者有时会把代码中控件的顺序搞得一团糟,这会导致文件看起来与以前的版本大不相同,如果文件受版本控制,这确实是个问题。
但是,我发现如果遵循某些规则,即使在非常大的窗体和用户控件中,设计器也能相当可靠地工作,而在极少数情况下,如果不遵循这些规则,我有一种简单的方法来强制设计器重新按“正确”的顺序排列控件。
我的规则:
1.每个.designer.csInitializeComponent()顶部的注解都说:* 不要用代码编辑器修改这个方法的内容 *.好吧,如果你知道你在做什么,那么手工编辑这个文件绝对没有问题,因为这是你需要做的。只要确保你有备份。
1.通常,当你创建一个表单或UC时,你会在这里或那里添加一些控件,然后移动它们,直到你找到一个好的排列方式。但是在.designer.cs文件中,控件是按照它们创建的顺序排序的,而不是按照你的逻辑如何把它们放在一起。
在完成窗体或UC的创建之后,我对这两个声明进行了重新排序(在文件的底部)和控件的示例化(在InitializeComponent()中),直到它们按照我希望的顺序排列。如果你必须在代码中更改控件的属性,这使得找到它们变得容易得多。而且这也使得版本控制变得容易,因为你可以很容易地看到你的表格或UC的哪一部分被更改了,只要在文件比较视图中看到更改的位置(更确切地说是靠近文件的顶部还是底部?)
但是改变这两个部分的顺序并不会自动改变InitializeComponent()中示例化部分之后的所有参数化代码的顺序,这将在你执行OP问题的解决方案时完成,这将在下面描述。
如果您使用规则#2,那么您需要做的收尾工作与遇到OP描述的问题时需要做的工作相同:

必须强制设计器按照控件在声明和示例化中的顺序排列控件。

这可以用一种非常简单的方式来完成(到目前为止,我在99%的情况下都是这样):
1.保存表格或UC的所有文件
1.打开设计器视图
1.移动其中一个控件(例如,通过选择它并按1次左箭头键)
1.可选:查看.designer.cs文件和/或保存表格或UC
1.将控件移回您想要的设计(例如,按1x右箭头键)
1.保存表单或UC
设计器将重写整个.designer.cs文件,您的控件现在应该处于“正确”的顺序。
在极少数情况下,这并没有什么帮助,包括嵌入式DataGridView和嵌入式UserControl中的DataGridViewRow。在这些情况下,我会额外做一些类似的收尾工作,包括添加和删除一个按钮:
1.保存表格或UC的所有文件
1.打开设计器视图
1.在窗体或UC中的任意位置添加按钮
1.可选:查看.designer.cs文件和/或保存表格或UC
1.再次删除此按钮
1.保存表单或UC

kdfy810k

kdfy810k6#

在使用合并风格的源代码管理系统(如subversion)时,我所知道的唯一真正避免这个问题的方法是手工编写表单,而不使用设计器。显然,这并不好,因为手工编写这些表单可能需要一段时间。
发生这种情况的原因是,设计器按照控件属性在窗体上的放置顺序序列化控件属性。剪切和粘贴以及移动控件使其具有新的父级(例如,将以前直接位于窗体上的控件移动到面板上)都会影响此顺序。
我在一个大型项目中遇到过这个问题,不得不使用一种相当丑陋的方法--将designer.cs文件与签入的目标版本进行比较,然后使用合并工具手动合并它们.这并不理想,但这是我看到svn或其他合并风格的源代码管理工具能够一致工作的唯一方法.
另一种选择是使用锁方法进行源代码控制,正如其他人所指出的,但这也会带来令人不快的副作用。

相关问题