2

我正在尝试重构一些基本上具有对象类型的 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);
4

5 回答 5

3

简单!我将假设您不需要强制转换(您实际上具有强类型的类型)。

在这种情况下,您只需要 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});
}
于 2013-04-23T18:49:07.557 回答
2

从我的角度来看,适合您情况的设计模式是策略模式。您可以在这里参考:http: //blogs.microsoft.co.il/blogs/gilf/archive/2009/11/22/applying-strategy-pattern-instead-of-using-switch-statements.aspx

您可以将每个类型名称注册为结构映射的键,以解析适当的具体类。

希望这有帮助。

于 2013-04-23T18:45:38.453 回答
1

为什么不抽象工厂模式

public class UserServiceFactory : IUserServiceFactory {
  public EmployeeServiceFactory(IUserService employeeService
    , IUserService managerService
    , IUserService executiveService) {

    //null guards
    this.employeeService = employeeService;
    this.managerService = managerService;
    this.executiveService = executiveService;
  }
}

从这里,您有 2 个选项,或者使用传统的 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);
  }
}

这听起来可能很复杂,但在你理解之后就足够简单了。

于 2013-04-24T09:21:45.840 回答
0

您还可以使用 Managed Extensibility Framework (MEF),它是System.ComponentModel.Composition.Net 中命名空间的一部分,可以与ServiceLocator模式结合使用。以下是articlesMEF 上的一些内容:

http://fernandomachadopirizen.wordpress.com/2010/04/19/a-simple-introduction-to-the-microsoft-extensibility-framework/

http://msdn.microsoft.com/en-IN/library/dd460648(v=vs.100).aspx

于 2013-04-24T08:24:16.037 回答
0

我的想法是:

public interface IUserDoSomethingService {
    void DoSomething(Employee user);
    void DoSomething(Manager user);
    void DoSomething(Executive user);
}
于 2013-04-23T18:52:59.323 回答