并感谢您的帮助
对于:
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);
}
}
只是一个猜测,任何帮助都会很棒。
注意:如果您能想出更好的方法来构建此方法,请告诉我。
再次感谢。 史蒂芬
答案 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#中经常使用的示例。