2013-06-16 5 views
6

Ho scritto un metodo di estensione su IQueryable che restituisce lo stesso tipo di IQueryable, solo filtrato un po '. Diciamo che è qualcosa di simile:metodo di estensione generico su IQueryable <T>

public static IEnumerable<T> Foo<T>(this IEnumerable<T> source, int? howmany = null) 
{ 
    if (howmany.HasValue) 
     return source.Take(howmany.Value); 
    return source; 
} 

chiamando il metodo di cui sopra è semplice come someLinqResult.Foo(2)

ho bisogno di altro metodo che restituisce un'istanza di altri classe generica, ma con altra classe di base (non lo stesso della fonte T sopra). Quindi, ecco il codice, supponiamo che questo metodo restituisca un elenco di tipo specificato (diverso dal tipo di input che IQueryable ha!) Ma la stessa lunghezza [il vero problema riguarda la trasformazione dei risultati della query di NHibernate, ma non lo fa t importa):

public static List<TTarget> Bar<TTarget,TSource>(this IEnumerable<TSource> source) 
{ 
    return new List<TTarget>(source.Count()); 
} 

ora, dato che il strLinqResult è IQueryable<string>, ho bisogno di chiamarlo strLinqResult.Bar<int,string>();.

Il punto è Devo passare entrambi i tipi, anche se il primo è già noto come sto chiamando il metodo su già definito IQuerable.

Dal momento che era abbastanza per chiamare Foo(2) e nonFoo<string>(2) ho pensato che il compilatore è in grado di "passare/indovinare" il tipo automaticamente.

Quindi, perché è necessario chiamare il secondo metodo Bar<int,string>(); e non solo Bar<int>()?


il codice effettivo:

public static ListResponse<TResponse> 
     BuildListResponse<T,TResponse>(this IQueryable<T> iq, ListRequest request) 
     where TResponse: new() 
    { 
     var result = iq.ApplyListRequestParams(request).ToList().ConvertAll(x => x.TranslateTo<TResponse>()); 
     var tcount = iq.Count(); 
     return new ListResponse<TResponse> { 
       Items = result, 
       _TotalCount = tcount, 
       _PageNumber = request._PageNumber ?? 1, 
      }; 
    } 

ApplyListRequestParams è sorta di Foo metodo dal codice esempio - si applica solo paginazione & params ordinazione disponibili in ListRequest oggetto.

Items è un public List<T> Items in un class ListResponse<T>.

TranslateTo è un metodo di ServiceStack.

Il metodo sopra invitato IQueryable<T> restituito da NHibernate (T è Domain Model) prende i parametri di richiesta (ordinamento, impaginazione), li applica, e quindi trasforma l'elenco dei risultati da DomainModel a DTO oggetto di tipo TResponse. L'elenco viene quindi incluso in una classe di risposta generica (generica, quindi è riutilizzabile per molti tipi di DTO)

+0

Hai provato a cambiare la definizione in 'Barra (...)'? – PinnyM

+0

@PinnyM sì, l'ho fatto. dice ancora che ho bisogno di passare 2 parametri di tipo – migajek

+0

@Jon potrei aver frainteso l'altra soluzione, ma estendere la classe effettiva è fuori questione - deve essere il metodo di estensione! – migajek

risposta

3

Se sto capendo correttamente il problema, si sta tentando di inserire il minor numero di parametri possibile. Questo non è possibile. È tutto o nessuno dove può capire tutto da solo.

Il problema, specificando solo alcuni, è che sarà possibile introdurre un metodo simile con il parametro di tipo 1 in meno e ora l'implementazione sarà stata interrotta.

Ma c'è qualche possibilità di condividere il tuo problema originale? Potrebbe essere in grado di permettere al compilatore di capirlo in qualche altro modo?