2015-02-21 4 views
2

У меня есть метод расширения, который позволяет пользователю отключать ленивую загрузку.Как написать метод расширения для возврата используемого типа?

public static IBaseEntityService<TEntity, TPrimaryKey> EnableLazyLoading<TEntity, TPrimaryKey>(
     this IBaseEntityService<TEntity, TPrimaryKey> baseService, 
     bool enabled) 
     where TEntity :Entity<TPrimaryKey> where TPrimaryKey : struct 
    { 
     baseService.UnitOfWork.EnableLazyLoading(enabled); 
     baseService.UnitOfWork.EnableProxyCreation(enabled); 
     var type = baseService.GetType().; 
     return (type)baseService; 
    } 

Вот пример базового интерфейса:

public interface IBaseEntityService<TEntity,TPrimaryKey> : 
    IBaseService<TEntity, TPrimaryKey> 
    where TEntity: Entity<TPrimaryKey> where TPrimaryKey : struct 
{ 

    TEntity FindByTenantId(Guid tenantId); 
    IBaseEntitySpecification<TEntity,TPrimaryKey> Specification { get; } 
} 

Скажем, у меня есть этот сервис, который реализует интерфейс IBaseEntityService<TEntity,TPrimaryKey>:

public IUserService: IBaseEntityService<User,int> 
{ 
     User FindByUserName(string username); 
} 

Вот что я хочу добиться:

var user = _userService.EnableLazyLoading(false).FindByUserName("someUsername"); 

Как вы можете видеть в моем примере после EnableLazyLoading(false), я могу перейти к методу FindByUserName. В настоящее время, поскольку он возвращает только IBaseEntityService, у меня нет такой опции.

Я хочу, чтобы метод расширения знал, чтобы вернуть IUserService, поскольку он реализует IBaseEntityService. Я знаю, что в какой-то момент мне пришлось бы бросить его, и я хочу избежать необходимости писать конкретную реализацию того же метода EnableLazyLoading для

Я думал о чем-то подобном, но, похоже, я мог что-то сделать без имея в неявном вызове метода Cast:

public static TEntityService Cast<TEntity, TPrimaryKey, TEntityService>(
      this IBaseEntityService<TEntity, TPrimaryKey> baseEntityService) 
      where TEntity : Entity<TPrimaryKey> 
      where TPrimaryKey : struct 
      where TEntityService : IBaseEntityService<TEntity, TPrimaryKey> 
     { 
      return (TEntityService) baseEntityService; 
     } 

Так он может работать так:

var user = _userService.EnableLazyLoading(false).Cast<IUserService>().FindByUserName("someUsername"); 
+0

Приложите больше усилий для форматирования кода в своих вопросах - вы задали более 200 вопросов, поэтому вы должны * действительно * знать, как форматировать сообщения. –

+0

@JonSkeet, я был на самом деле посреди этого, когда вы, вероятно, писали свой комментарий. – DDiVita

+1

Он по-прежнему выглядит сломанным для меня ... –

ответ

4

Вы можете просто сделать приемник EnableLazyLoading общим типом, ограниченным IBaseService. Это многословие, но должно сделать трюк.

public static TService EnableLazyLoading<TService, TEntity, TKey>(this TService service) 
    where TService : IBaseService<TEntity, TKey> 
    where TEntity : Entity<TKey> 
    where TKey : struct 
{ 
    // do stuff 
    return service; 
} 

Таким образом, вы получаете фактический тип обслуживания в качестве возвращаемого типа. Я не сделал C# через некоторое время, поэтому я могу забыть что-то важное, но IIRC это работает отлично.

+0

Yup, вот и все! – BartoszKP

+0

Это было передо мной все время! Ницца! – DDiVita

1

лучшее решение, обеспечивается Ben в his answer является:

public static T EnableLazyLoading<T, TEntity, TKey>(
    this T @this, 
    bool enabled) 
         where T  : IBaseService<TEntity, TKey> 
         where TEntity : Entity<TKey> 
         where TKey : struct 
{ 
    @this.UnitOfWork.EnableLazyLoading(enabled); 
    @this.UnitOfWork.EnableProxyCreation(enabled); 
    return @this; 
} 

Другое решение, но дешевле, но не то, что в чистоте, чтобы использовать dynamic ключевое слово:

public static dynamic EnableLazyLoading<TEntity, TPrimaryKey>(
    this IBaseEntityService<TEntity, TPrimaryKey> @this, 
    bool enabled) 
         where TEntity  : Entity<TPrimaryKey> 
         where TPrimaryKey : struct 
{ 
    @this.UnitOfWork.EnableLazyLoading(enabled); 
    @this.UnitOfWork.EnableProxyCreation(enabled); 
    return @this; 
} 

Стоимость является то, что вы теряете удобство IntelliSense, и, возможно, некоторые показатели.

Смежные вопросы