C#在类之间共享代码

时间:2009-12-10 03:13:51

标签: c# share

在使用C#的Visual Studio 2008中,跨多个类和源文件共享代码的最佳方法是什么?

继承不是解决方案,因为类已经具有有意义的层次结构。

是否有一些简洁的功能,就像一个C包含文件,让你在其他类中的任何地方插入代码?

编辑:

好吧,我想我们需要一个具体的例子......

域中有几百个类,经过深思熟虑的类层次结构。现在,许多这些类需要打印。有一个实用程序打印机类来处理打印。假设有3种不同的打印方法依赖于正在打印的类。调用print方法的代码(6行)是我试图避免在所有不同的客户端类页面上复制和粘贴的代码。

如果人们不会认为他们对该领域有更多了解,那会很好 - 特别是当他们特别提到不合适的技术时......

10 个答案:

答案 0 :(得分:7)

如果您在代表非常不同的事物的课程中经常使用的功能,根据我的经验,它应该只属于几个类别:

  • 实用程序(例如字符串格式化,解析,......)
  • 横切关注点(日志记录,安全执法......)

对于实用程序类型的功能,您应该考虑创建单独的类,并在业务类中需要的地方引用实用程序类。

public class Validator
{
  public bool IsValidName(string name);
}

class Patient
{
  private Validator validator = new Validator();
  public string FirstName
  {
     set
     {
         if (validator.IsValidName(value)) ... else ...
     }
  }
}

对于日志记录或安全性等跨领域问题,建议您调查Aspect-Oriented Programming

关于其他评论中讨论的PrintA与PrintB示例,它听起来像是工厂模式的一个很好的例子。你定义一个接口,例如IPrint,类PrintA和PrintB都实现IPrint,并根据特定页面的需要分配IPrint实例。

// Simplified example to explain:

public interface IPrint 
{ 
   public void Print(string); 
}

public class PrintA : IPrint
{
   public void Print(string input)
   { ... format as desired for A ... }
}

public class PrintB : IPrint
{
   public void Print(string input)
   { ... format as desired for B ... }
}

class MyPage
{
   IPrint printer;

   public class MyPage(bool usePrintA)
   {
      if (usePrintA) printer = new PrintA(); else printer = new PrintB();
   }

   public PrintThePage()
   {
      printer.Print(thePageText);
   }
}

答案 1 :(得分:4)

您不能像在C中那样通过预处理程序指令加载您希望添加到C#类中的代码。

但是,您可以定义一个接口并为该接口声明扩展方法。然后可以通过类实现接口,并且可以在这些类上调用扩展方法。 E.g。

public interface IShareFunctionality { }

public static class Extensions
{
    public static bool DoSomething(this IShareFunctionality input)
    {
        return input == null;
    }
}

public class MyClass : Object, IShareFunctionality
{
    public void SomeMethod()
    {
        if(this.DoSomething())
            throw new Exception("Impossible!");
    }
}

这将允许您重用功能,但是如果您可以,例如,哈希包含文件,则无法访问类的私有成员。

我们可能需要一些更具体的例子来说明你想做什么?

答案 2 :(得分:3)

C#实用程序类将起作用。它就像公共代码的中央注册表(或者像VB.NET模块构造一样) - 它应该包含不特定于任何类的代码,否则它应该被附加到相关类。

想要开始复制源代码,如果您不需要,因为考虑到重复会导致代码更新问题。

只要源不需要保留状态,就可以使用带静态方法的静态类。

static public class MySharedMembers {
    static public string ConvertToInvariantCase(string str)  {
        //...logic
    }
    // .... other members
}

答案 3 :(得分:2)

如果类在同一名称空间中,则不需要包含模拟。只需调用另一个函数中定义的类的成员即可。

如果它们不在同一名称空间中,请在usings指令中添加要使用的类的名称空间,它应该与上面的相同。

我对这个问题感到困惑:似乎你需要处理你的基本OO理解。

答案 4 :(得分:2)

答案 5 :(得分:2)

我不知道如何包含部分文件,但我们经常做的一件事是添加现有文件并从当前位置“链接”它。例如,我们有一个assemblyInfo.cs文件,每个项目都是从解决方案目录引用的。我们更改它一次,所有项目都有相同的信息,因为它们指的是同一个文件。

否则,关于在common.dll中重构“常见”例程的建议是我在.Net中提出的最好的事情。

答案 6 :(得分:1)

我不确定你的“有意义”结构究竟是什么意思,但这听起来像是一个可以使用基类实现的地方。虽然不像C ++多重继承那样“冗长”,但是使用链式基类实现来重用常用函数可能会带来一些好处。

您可以保留类层次结构,至少可视化并根据需要覆盖行为。

答案 7 :(得分:1)

将重复代码拉出到服务中。重复代码是一个线索,可能有一些重构的空间。

例如,创建一个“PrintingService”,其中包含打印所需的逻辑。然后,您可以让需要打印的类依赖于此服务(通过构造函数或需要服务的方法中的参数)。

我在这些方面的另一个技巧是为基本功能创建接口,然后使用接口进行编码。例如,我有一堆报告类,用户可以通过传真,电子邮件或打印。我没有为每个创建方法,而是为每个创建了一个服务,让他们实现一个具有Output()方法的接口。然后,我可以根据用户想要的输出类型将每个服务传递给相同的方法。当客户想要使用eFax而不是通过调制解调器传真时,只需编写实现此相同界面的新服务即可。

答案 8 :(得分:0)

说实话,我想不出像Visual C#中包含的东西,也不会想到为什么你会想要这个功能。也就是说,部分类可以做类似于你想要的事情,但使用它们可能会对你的“类已经有一个有意义的层次结构”要求发生冲突。

答案 9 :(得分:0)

您有很多选项,TT,扩展方法,委托和lambda