简体   繁体   中英

Extension method with nested generics

I work on a multilingual site and I have built this structure for my "localizable" entities.

The interfaces:

public interface ILocalizable<T>
    where T : ILocalized
{
    ICollection<T> Content { get; set; }
}

public interface ILocalized
{
    int LanguageId { get; set; }
    virtual Language Language { get; set; }
}

And implementation:

public class Entity : ILocalizable<EntityLocalized>
{
    public int Id { get; set; }
    public ICollection<EntityLocalized> Content { get; set; }
}

public class EntityLocalized : ILocalized
{
    public int LanguageId { get; set; }
    public virtual Language Language { get; set; }

    public int EntityId { get; set; }
    public string Title { get; set; }
}

The reason for this is that I could write an extension method that allows me to get the right string this way:

Entity entity; // get entity from database
string localizedString = entity.Content.Translate(localized => localized.Title);

Everything works just fine. I just had an idea to write another extension method that would save me some work while building a query. So that I don't have to write all the time:

IQueryable<Entity> query; // some query
return query.Include(entity => entity.Content.Select(localized => localized.Language));

So I have this:

public static IQueryable<TEntity> WithLocalization<TEntity>(this IQueryable<TEntity> query)
{
    return query.Include(entity => entity.Content.Select(content => content.Language));
}

But obviously I need to specify the generic type. This won't compile. I tried everything.

public static IQueryable<TEntity> WithLocalization<TEntity>(this IQueryable<ILocalizable<ILocalized>> set) where TEntity : ILocalizable<ILocalized> {}

IQueryable<Entity> query; // get query
query.WithLocalization(); // intellisense doesn't display and this won't compile

I kind of understand the reason. It's been discussed there many times. I'm just wondering if there's a way how to build such an extension method without a need to explicitly use and pass 2 generics types, like:

public static IQueryable<TEntity> WithLocalization<TEntity, TEntityLocalized>(this IQueryable<TEntity> set)           
    where TEntityLocalized : ILocalized
    where TEntity : ILocalizable<TEntityLocalized> {}

Thank you!

I think you want...

public static IQueryable<ILocalizable<TEntityLocalized>> WithLocalization<TEntityLocalized>(this IQueryable<ILocalizable<TEntityLocalized>> query)
    where TEntityLocalized : ILocalized {
    return query.Include(entity => entity.Content.Select(content => content.Language));
}

You aren't propagating the TEntity generic parameter into the signature correctly.

public static IQueryable<ILocalizable<TEntity>> WithLocalization<TEntity>(this IQueryable<ILocalizable<TEntity>> query)
    where TEntity : ILocalized
  {
      return query.Include (entity => entity.Content.Select (content => content.Language));
  }

public class Test
{
   public Test()
   {
      IQueryable<Entity> query;
      query.WithLocalization ();
   }
}

compiles correctly and gives correct intellisense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM