2013-04-23 51 views
1

我想重構一些基本上有對象類型的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); 

回答

3

簡單!我會假設你不需要施放(你實際上有強類型的類型)。

在這種情況下,你只需要一個通用的IDoSomethingService

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}); 
} 
+0

我認爲這是正確的軌道。對於ServiceResolver.Current.Resolve >()有沒有辦法解決而不通過T?我沒有定義T泛型,只是對象類型。 – NullReference 2013-04-23 19:44:43

+0

Gahh ...不是我想聽的.... – Aron 2013-04-24 01:15:23

0

我的想法是:

public interface IUserDoSomethingService { 
    void DoSomething(Employee user); 
    void DoSomething(Manager user); 
    void DoSomething(Executive user); 
} 
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語句或策略模式按對象類型來解決。

如果其他例子(內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); 
    } 
} 

聽起來很複雜,但在你理解後很簡單。