使用Visual Studio时重用代码的最佳方法?

时间:2008-08-29 16:58:02

标签: .net visual-studio

我尝试了两种不同的重用代码方法。我有一个完整的类库项目的解决方案,通用代码我几乎在我工作的每个项目中重用。当我开始研究一个新项目时,我将以两种方式之一重用此代码库中的代码。我已经尝试将我需要的项目从这个代码库带入我的项目中。我还尝试编译为.dll并从当前解决方案的根目录中的文件夹引用.dll。虽然第二种方法似乎更容易实现,但我总是发现自己对原始代码做了一些小调整,以使其适合我当前项目的上下文。我知道这是一个模糊的问题,但有没有人在其他方法上重新使用类库来解决新的解决方案?

8 个答案:

答案 0 :(得分:8)

简而言之,您所做的是对的,您希望将公共代码移动到类库(DLL)中,然后在任何需要其逻辑的项目中引用它。

你出错的地方是你不是维护它。如果您需要对现有代码进行少量“调整” [子类](http://en.wikipedia.org/wiki/Subclass (computer_science)_并对其进行扩展,请不要更改它。如果需要进行重大更改,那么重新思考设计。

答案 1 :(得分:1)

我已经完成了你提到的两种方式。我喜欢第二个,但就像你说的那样,当你对该库进行更新时,这有点乏味。

我使用的另一种方法是选择一个中心位置来保存您的库。然后添加一个带有字符串值的注册表项以指向该目录。添加引用时,所有库都将显示在.net选项卡下,就像库位于GAC中一样。然后,您可以创建一个post build命令来将库构建到该中心位置。

这是注册表项,更改CompanyName和目录:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders\ComapnyName]
@="C:\\CentralLocation"

答案 2 :(得分:0)

我喜欢将所有泛型类编写为:泛型。我让它们尽可能独立于应用程序,并尝试让它们保持不知不觉。如果我制作一个花哨的Tree类,我将使用泛型将其创建为Tree< T>所以我可以使用我想要的任何类型的类。如果我需要使用Tree来保存GameCharacter对象,我可以实例化Tree< GameCharacter>但如果我正在编写业务应用程序,我可以将其用作Tree< Spreadsheet&gt ;.

如果您发现自己更改了Reuse Libary以匹配您的项目,请尝试使它们不那么具体,而是从实际项目中的Library基类派生。将所有通用逻辑放在库类中,对于特定于应用程序的部分,创建派生类并在该派生类中实现它们的逻辑。

就解决方案组织而言,我将重用库作为一个单独的项目保存在一个公共文件夹中,并将项目包含在我创建的任何解决方案中,这使我可以轻松地引用它,但也可以对任何解决方案进行任何更改。我的应用程序的解决方案。

答案 3 :(得分:0)

我不使用Visual Studio或.NET,但它认为这个问题在所有程序员中都很常见,所以我想我会对它进行修改。

当我们尝试将公共代码提取到单独的库中时,我们遇到了类似的问题。一开始可能没问题,但最终1个客户端需要一些新功能并需要更改库。这总会导致一些其他客户的问题,造成巨大的混乱。除非你有一个很好的方法来版本化你的库文件,否则这是一个难以解决的问题。

最后,您可能最好只将源文件复制并粘贴到新项目中。是的,这违反了DRY(不要重复自己)原则,但是你避免了很多与公共库创建的依赖关系相关的问题。

答案 4 :(得分:0)

您真正需要做的是使用某种源控制软件,以便:

  • 您在一个项目中所做的任何更改都将反映在所有项目中,而不会损失参照完整性
  • 您可以选择保留您所拥有的库的多个版本并引用特定版本,而不是拉动毛发确定哪个版本由哪个项目使用

只需确保您手头有单元测试,以确保您以前的项目不会受到您在图书馆所做的任何更改的影响或受到轻微影响。

古德勒克!

答案 5 :(得分:0)

@Outlaw
如果您需要复制代码并进行特定于应用程序的更改,那么该代码不是通用的。它应该被重构,以便公共功能保留在公共库中,并且应用程序特定的功能应该添加到该应用程序的代码库中的子类中。

对每个特定于应用程序的版本使用带分支的版本控制可以帮助解决集成问题 - 在分支中进行更改,然后在将它们合并回主干之前使用其他应用程序对其进行测试。如果您不想设置自己的免费在线源代码控制主机,本网站上有几个问题。

答案 6 :(得分:0)

一些非常好的可重复使用的代码位于Ayende Rahien的Rhino Tools。不仅要了解他如何实现各种常见代码,还要了解它是如何组织的。

答案 7 :(得分:0)

这个想法很好 - 把你的代码放在一个普通的dll中并引用它。我们广泛使用这种方法,它的工作原理。显然有些项目最终会失去同步,所以我们这样做是这样的:

  • 至少具体,如果您可以使用泛型类型,那么这样做。例如,如果您想要一个处理空值或没有值的函数和

返回一些东西,实现NullConvert(o作为对象,作为对象),因为对象优于NullConvert(o作为对象,String)为

的字符串。然后,您可以添加其他类型,使签名保持不变。但是,如果未处理类型,则在方法中具体说明并为未处理的类型引发异常 - 不要让它失去工作机会。在上面的示例中,检查返回值的类型,并检查您的实现是否处理该类型。

  • 按命名空间中的类型分组函数; MyGeneric.DateFns,MyGeneric.StringFns,MyGeneric.Comms等。

  • 使用类或方法后,请勿更改功能,这样做可能不安全。将它们标记为已弃用并包含注释以指示更新/更好的课程的位置。

  • 您可以考虑两个或更多库,例如,基础库中的公共方法和类,以及特定于域的类和

在另一个库(更高级别)中使用常用方法(来自基础库)的函数。这样,基础库就不需要一直改变。

  • 考虑使用“实现”而不是类。例如,如果您有一个处理ArrayList的函数,请设置

取代iList的方法的参数。然后您也可以使用其他列表类型,只要它们在其中实现iList。

  • 避免引入细节,例如,显式驱动程序(Oracle 8.x)。将其包裹在其他内容中,如果更改,请更改

包装器对象的内部,而不是对象本身。

  • 了解如何使用反射。假设您需要一个函数来从对象数组中获取Distinct值。您可以使用反射和

然后传递你需要得到的属性名称; GetDistinct(MyList as iList,“Name”)作为List(of String)。您的代码可以查看

通过反射调用“名称”的参数(涉及的性能损失很小)。

  • 了解如何编写扩展程序(组件模型)。例如,如果您正在编写一个函数来始终返回一个单独格式化的

日期,将该功能转换为扩展功能。明智地说,如果您公司的名称是ABC,那么请使用ABCDateFormat,例如,区分您的和MS功能。

这里应该列出太多的东西。你的朝着正确的方向迈出了一步。