2011-10-27 74 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