我正在尝试重构一些基本上在对象类型上有switch语句的代码,并根据该类型调用特定的服务方法。我尽量保持基本相同的代码。
if (user is Employee)
{
_userService.DoSomething(user);
}
else if (user is Manager)
{
_managerService.DoSomething(user);
}
else if (user is Executive)
{
_executiveService.DoSomething(user);
}
我想将服务调用抽象到接口并减少代码行数。我的问题在于ServiceResolver部分,是否存在与此类问题相关的特定设计模式?我可以轻松地创建一个具有switch语句的类,该语句返回实现接口的正确服务但是看起来并不像我想要的那样干净。有什么建议?我已经在使用结构图构造函数注入,是否可以与条件或其他东西一起使用?
public interface IUserDoSomethingService
{
void DoSomething(User user)
}
var userDoSomethingService = _userDoSomethingServiceResolver(user);
userDoSomethingService.DoSomething(user);
答案 0 :(得分:3)
Simples!我假设你不需要演员(你实际上有强类型的类型)。
在这种情况下,你只需要在IDoSomethingService上使用Generic
public interface IServiceDoSomethingOn<in T>
{
void DoSomethingOn(T thing);
}
现在在服务电话上你只需要打电话......
public void DoSomethingOnSomethingElse<T>(T thatSomething)
{
var service = ServiceResolver.Current.Resolve<IServiceDoSomethingOn<T>>();
service.DoSomethingOn(thatSomething);
}
编辑:半通用解决方案。警告我不知道结构图将如何处理协方差和反演。所以继承可能不起作用。
public void DoSomethingOnSomethingElse(object thatSomething, Type type)
{
var genericMethod = this.GetType().GetMethods()
.Single(x => x.IsGeneric && x.Name == "DoSomethingOnSomethingElse");
var method = genericMethod.MakeGenericMethod(type);
method.Invoke(this, new object[]{thatSomething});
}
答案 1 :(得分:2)
从我的观点来看,适合您情况的设计模式是战略模式。你可以在这里参考: http://blogs.microsoft.co.il/blogs/gilf/archive/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements.aspx
您可以将每个类型名称作为键注册到结构图中,以解析相应的具体类。
希望得到这个帮助。
答案 2 :(得分:1)
为什么不抽象工厂模式?
public class UserServiceFactory : IUserServiceFactory {
public EmployeeServiceFactory(IUserService employeeService
, IUserService managerService
, IUserService executiveService) {
//null guards
this.employeeService = employeeService;
this.managerService = managerService;
this.executiveService = executiveService;
}
}
从这里开始,您有两个选项,使用传统的if-else语句或策略模式来按对象类型解析。
If-else示例(UserServiceFactory中的方法):
public void DoSomething(User user) {
if (user is Employee) {
employeeService.DoSomething(user);
}
else if (user is Manager) {
managerService.DoSomething(user);
}
else if (user is Executive) {
executiveService.DoSomething(user);
}
}
按对象类型解析:
public void DoSomething(Employee user) {
employeeService.DoSomething(user);
}
public void DoSomething(Manager user) {
managerService.DoSomething(user);
}
public void DoSomething(Executive user) {
executiveService.DoSomething(user);
}
应该有另一种方法,通过使用命名而不是配置,但我仍然无法做到。
直接通话中的用法:
public void CallUser() {
// declare the services and user here
UserServiceFactory userServiceFactory = new UserServiceFactory(employeeService
, managerService
, executiveService);
userServiceFactory.DoSomething(user);
}
在其他服务中使用,注入工厂而不是服务集合。
public class UserServiceConsumer:IUserServiceConsumer {
public UserServiceConsumer(IUserServiceFactory userServiceFactory) {
this.userServiceFactory = userServiceFactory;
}
IUserServiceFactory userServiceFactory;
public void ConsumeFactory(User user) {
//do some validation maybe
userServiceFactory.DoSomething(user);
}
}
这可能听起来很复杂,但在你理解之后就足够简单了。
答案 3 :(得分:0)
我的想法是:
public interface IUserDoSomethingService {
void DoSomething(Employee user);
void DoSomething(Manager user);
void DoSomething(Executive user);
}
答案 4 :(得分:0)
您还可以使用托管扩展性框架(MEF),它是.Net中System.ComponentModel.Composition
命名空间的一部分,可以与ServiceLocator
模式结合使用。
以下是MEF上的一些articles
:
http://msdn.microsoft.com/en-IN/library/dd460648(v=vs.100).aspx