2011-10-27 70 views
4

我不確定這是否可能,我可能需要爲每個實現編寫擴展方法。下面是一些示例代碼:擴展方法返回接口的正確實現嗎?

public interface IBaseService<T> 
{ 
    IUnitOfwork UnitOfWork {get;} 
} 

public interface IService<T>: IBaseService<T> 
{ 
    IEnumerable<T> GetAll(); 
    T GetById(Guid id); 
} 

public interface IUserService: IService<User> 
{ 
    User FindByUsernameAndPassword(string username, string password) 
} 

public class BaseService<T>: IService<T> 
{ 

    public BaseService(IRepository<T> repository) 
    { 
     _repository = repository 
    } 
    public virtual IEnumerable<T> GetAll(){....}; 
    public virtual T GetById(Guid id){....}; 
    IUnitOfWork UnitOfWork {get {return _repository.UnitOfWork;}} 
} 

public class UserService: BaseService<User>, IUserService 
{ 
    ... 
} 

public static class ServiceExtensions 
{ 
    public static IBaseService<T> EnableLazyLoading<T>(this IBaseService<T> service, bool lazyLoad = True) 
    { 
      service.UnitOfWork.EnableLazyLoad(lazyLoad); 
      return service; 
    } 
} 

因此,假設我正在使用UserService。當我打電話的擴展方法上UserService,是有可能有它返回IBaseService的正確執行或做我需要爲每個執行?:

實例創建和擴展方法:

userService.EnableLazyLoading(false).FindByUsernameAndPassword("ddivita","123456") 
+0

所以,澄清,你是說你想要它創建一個新的版本,無論它被稱爲? –

+0

我只想編寫一個擴展方法供IBaseServcie 的所有實現使用,以便返回正確的實現。在我的例子中,我想找出一種方法來在我調用EnableLazyLoading擴展時返回IUserService。 – DDiVita

+0

哦!我明白了,所以你希望它返回被調用的特定類型,而不是創建它的新實例。 –

回答

3

你可以這樣來做:

public static S EnableLazyLoading<T, S>(this S service, bool lazyLoad = true) 
    where S : IBaseService<T> 
{ 
    service.UnitOfWork.EnableLazyLoad(lazyLoad); 
    return service; 
} 
+0

我想出了相同的答案,唯一的問題是它不能推斷出類型(OP可能會或可能不會),所以你必須明確地調用它,像這樣:'userService.EnableLazyLoading (false)...' –

+0

是的,這是真的,但我更喜歡這種方式n次創建擴展方法。如果你有多個擴展方法,你可以做的唯一事情就是從一個接口變成一個抽象類。 –

+0

哦,我完全同意。只是指出了不利的一面。 –

2

好吧,這可能會或可能不會與您的設計工作,但它建立在Felix的答案(這是他應該得到的功勞),並使其推斷 - 能。

因爲你UnitOfWork類不依賴於T類型,你可以創建一個IBaseService即非通用包含UnitOfWork成員,然後進行IBaseService<T>延長IBaseService像這樣:

public interface IBaseService 
{ 
    // all non-type-T related stuff 
    IUnitOfwork UnitOfWork {get;} 
} 

public interface IBaseService<T> : IBaseService 
{ 
    // .. all type T releated stuff 
} 

然後,保持休息你的類設計爲正常,寫擴展方法爲:

public static S EnableLazyLoading<S>(this S service, bool lazyLoad = true) 
    where S : IBaseService 
{ 
    service.UnitOfWork.EnableLazyLoad(lazyLoad); 
    return service; 
} 

因爲我們不需要IBaseService<T>通用電氣現在,我們不需要指定第二類型參數T,它正在推斷問題。所以,現在我們可以編寫代碼完全按照你想要的,因爲它現在可以推斷SUserService,而不需要知道有關類型TUser):

userService.EnableLazyLoading(false).FindByUsernameAndPassword("ddivita","123456"); 

當然,這是假設,正如我所說,這UnitOfWork不需要任何類型T

正如我所說,@Felix應該得到答案,但只是想擴大如何可以推斷,以避免必須傳遞泛型類型參數。雖然贊成票增加:-)

+0

哦,那太棒了! – DDiVita

+0

@DDiVita:謝謝,雖然我說費利克斯應該得到答案,但我只是在構建他的工作。 –

+1

這很好,順便說一句。我的UoW沒有輸入,所以這是一個完美的解決方案。感謝你和Felix – DDiVita