C#设计模式:通用方法?

时间:2009-11-28 18:48:02

标签: .net design-patterns

并感谢您的帮助

对于:

public abstract class EntityBase
{    
 protected void Create(EntityBase c)    
 {        
    Log.Audit(c);
 }
}

public class Customer : EntityBase
{    
 public void CreateCustomer(Customer c)    
 {        
  Create(c);    
 }    
 }
}

public class Car : EntityBase
{    
 public void CreateCar(Car c)    
 {        
  Create(c);    
 }    
 }
}

对于上面的例子 1)您将如何实现方法签名:     Log.Audit(C);

2)在方法Audit(c)中,我们需要将c转换为适当的类型,并遍历整个对象的属性以进行审计。如何实现这一目标。我在想像......

public Audit(T t)
{
 switch (t.GetType())
 {
 case Customer:
    //Audit Customer
    Audit(<Customer> t); 
    break;
 case Car:
    //Audit Car
    Audit(<Car> t); 
 }
}

只是一个猜测,任何帮助都会很棒。

注意:如果您能想出更好的方法来构建此方法,请告诉我。

再次感谢。 史蒂芬

3 个答案:

答案 0 :(得分:5)

在一个方法中,当你有switch或if / else构造来决定如何分派方法时,这是一个告诉你不使用多态的迹象。

一种解决方案是使Audit()成为EntityBase的虚方法,并让Audit在实例上调用它(因此您可以覆盖Customer或Car中的Audit)

您可以作为奖励提供使用反射的默认实现,该反射遍历继承类的每个属性以转储它。

public abstract class EntityBase
{    
     protected void Create(EntityBase c)    
     {        
       Audit(c);
     }

     public virtual void Audit()
    {
    //Default audit code here, using reflection for instance
    }     
}

public class Car : EntityBase
{
    //Does not override, uses default Audit Code
}

public class Hamster : EntityBase
{
    public override void Audit()
    {
        //Specific code here..
    }
}

如果您不希望在Entity类或其中一个继承者中拥有Audit责任,则必须采用反射方式。

答案 1 :(得分:3)

我在审计时几乎总是使用反射。如果您具有可以区分它们的属性(比如ColumnAttribute),则可以使用这些属性来查找要审核的属性。您始终可以创建要使用的属性,并在需要时应用它。然而,最简单的方法就是审计类的公共属性。

public void Audit( T t )
{
     foreach (var property in t.GetType().GetProperties())
     {
         var value = property.GetValue(t,null);
         ...do something with property.Name and value...
     }
}

您可以在http://farm-fresh-code.blogspot.com/2009/05/auditing-inserts-and-updates-using-linq.html了解我如何在LINQ to SQL中使用它。

答案 2 :(得分:0)

我建议基类永远不要知道关于这些类的任何东西。在这种情况下:如果添加另一个来自的类,则还需要每次都更改基类。因此,Yann Schwartz的建议比您的方法更好。

问题可能是Customer / Car / ...逻辑与autdit功能的紧密联系(参见single responsiblity principle)。这可能是反射的一个优点(如上所述,即使它可能更慢)但如果你想为所有目的实现一个共同的方法,这可能会变得非常复杂。将问题委托给您可以使用的单独部分(例如可以附加的插件aspect oriented programming)是一种更好的做法。一些框架已经支持这种方法。

如果您想“外包”您的开关案例问题,可以使用strategy pattern。 您可以在没有特殊框架here的情况下找到我在c#中经常使用的示例。