假设以下域实体:
public enum Role
{
User = 0,
Moderator = 1,
Administrator = 2
}
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Role Role { get; set; }
}
我需要知道用户是否可以执行“编辑”操作。所以我有2个解决方案:
在用户实体
中创建CanEdit方法public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public Role Role { get; set; }
public bool CanEdit()
{
return Role == Role.Moderator || Role == Role.Administrator;
}
}
为用户类型创建CanEdit扩展方法:
public static class UserExtensions
{
public static bool CanEdit(this User user)
{
return user.Role == Role.Moderator || user.Role == Role.Administrator;
}
}
两种解决方案都有效,但问题是何时使用标准方法与使用扩展方法?
答案 0 :(得分:11)
扩展方法只是普通静态方法的语法糖。
如果您控制类结构,则应在类中实现所需的所有功能。扩展方法真正有用/必要的地方是你不拥有你想要“扩展”的类。
对于这个例子,我认为你应该将逻辑放在User
类中。它是用户自身的逻辑功能;消费者应该能够使用CanEdit()
方法,而无需使用甚至不了解UserExtensions
类。
答案 1 :(得分:2)
我大多同意Aaronaught的回答,但请考虑一下:
也许您的CanEdit()
方法或其他类似方法(业务规则)可能会或多或少地发生变化,或者取决于某些外部因素。或者随着时间的推移,您将拥有越来越多的此类规则(针对不同的问题)。在这种情况下,您可能希望将它们保存在与域模型分离的不同位置,以确保域模型不具有太多不同的职责,并且不需要经常更改。
然后,一种方法是将它们作为扩展方法实现,因为这允许您将这些业务规则与您的域模型(例如User类)分开,但该方法仍然可以被User类的用户轻松发现。
实现此类业务规则的另一种方法是specification pattern,您可以将每个规则实现为单独的(规范)类,例如:在this blog post中展示。
答案 2 :(得分:1)
使用Extension方法为了使用它们没有什么意义。如果该方法属于该类,请在那里使用它。扩展方法用于扩展,在无法控制类时使用它们,或者为功能应该应用于从该接口派生的所有类的接口提供功能。
答案 3 :(得分:1)
如果你没有直接访问类的源代码,你应该使用Extensions方法,如果你有权访问源代码,我认为没有理由不使用标准方法......
答案 4 :(得分:1)
我同意Aaronaught的观点:用老式的方式实现自己的逻辑。静态方法可能导致问题(缺少使用语句,方法似乎“缺失”)。
您的模型固有的东西应该是您课程的一部分。