返回接口正确实现的扩展方法?

时间:2011-10-27 13:54:03

标签: c# extension-methods

我不确定这是否可行,我可能需要为每个实现编写扩展方法。以下是一些示例代码:

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")

2 个答案:

答案 0 :(得分:3)

你可以这样做:

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

答案 1 :(得分:2)

好的,这可能适用于您的设计,也可能不适用,但它建立在Felix的答案(他应该得到赞誉)的基础上,并使其可推断。

由于您的UnitOfWork类不依赖于类型T,因此您可以创建一个非{0}包含IBaseService成员的UnitOfWork,然后生成{{1}像这样扩展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>,因此我们无需指定导致推理有问题的第二个类型参数UnitOfWork。现在我们可以完全按照您的意愿编写代码,因为它现在可以推断TS而无需了解类型UserServiceT):

User

当然,正如我所说,这假设userService.EnableLazyLoading(false).FindByUsernameAndPassword("ddivita","123456"); 不需要UnitOfWork类型的任何内容。

正如我所说的那样,@ Felix应该得到答案,但只是想扩展一下如何能够推断它能够避免传递泛型类型参数。不过,赞成票: - )