2016-03-03 13 views
6

Sto tentando di implementare un metodo generico GetById(T id) che soddisferà i tipi che potrebbero avere tipi di ID diversi. Nel mio esempio, ho un'entità che ha un ID di tipo int e uno di tipo string.Come implementare GetById generico() dove Id può essere di vari tipi

Tuttavia, io continuo a ricevere un errore e non ho idea del perché:

Il tipo 'int' deve essere un tipo di riferimento al fine di utilizzarlo come parametro 'TID' nel tipo generico di metodo IEntity

Entity Interfaccia:

per soddisfare i miei modelli di dominio che possono avere Id del tipo di int o string.

public interface IEntity<TId> where TId : class 
{ 
    TId Id { get; set; } 
} 

Entità Implementazioni:

public class EntityOne : IEntity<int> 
{ 
    public int Id { get; set; } 

    // Other model properties... 
} 

public class EntityTwo : IEntity<string> 
{ 
    public string Id { get; set; } 

    // Other model properties... 
} 

Repository Generico Interfaccia:

public interface IRepository<TEntity, TId> where TEntity : class, IEntity<TId> 
{ 
    TEntity GetById(TId id); 
} 

Generico Attuazione Repository:

public abstract class Repository<TEntity, TId> : IRepository<TEntity, TId> 
    where TEntity : class, IEntity<TId> 
    where TId : class 
{ 
    // Context setup... 

    public virtual TEntity GetById(TId id) 
    { 
     return context.Set<TEntity>().SingleOrDefault(x => x.Id == id); 
    } 
} 

Implementazioni repository:

public class EntityOneRepository : Repository<EntityOne, int> 
    { 
     // Initialise... 
    } 

    public class EntityTwoRepository : Repository<EntityTwo, string> 
    { 
     // Initialise... 
    } 
+6

Perché stai limitando 'TId' a' class' tipi? Questo non funzionerà con 'int' (il messaggio di errore lo rende abbastanza chiaro). 'class' indica" tipo di riferimento "in termini generici. –

risposta

2

è necessario rimuovere il vincolo sul TID dal Repository classe

public abstract class Repository<TEntity, TId> : IRepository<TEntity, TId> 
where TEntity : class, IEntity<TId> 
{ 
    public virtual TEntity GetById(TId id) 
    { 
     return context.Set<TEntity>().Find(id); 
    } 
} 
+0

Questo suggerimento risolve l'errore del tipo di riferimento, tuttavia, sto ottenendo un 'Operatore == non può essere applicato agli operandi di tipo TId e TId' quando si cerca di eseguire la corrispondenza con Id – Tomuke

+0

Si scopre che funziona bene se uso' .Find (id) 'invece di' .SingleOrDefault (x => x.Id == id) '. Mi aspetterei che stia facendo esattamente la stessa cosa con questo metodo, quindi non sono sicuro del perché '.Find()' sia valido. – Tomuke

+0

non funziona per me. mostrando l'errore –

1

Alla tua domanda:
Sto cercando di implementare un generico Metodo GetById (T id) che soddisferà i tipi che potrebbero avere tipi di ID diversi. Nel mio esempio, ho un'entità che ha un ID di tipo int e uno di tipo string.

public virtual TEntity GetById<TId>(TId id) 
    { 
     return context.Set<TEntity>().SingleOrDefault(x => x.Id == id); 
    } 

Per parametro generico, basta fare un metodo generico come sopra

2
public interface IEntity<TId> where TId : class 
{ 
    TId Id { get; set; } 
} 

Il vincolo where TId : class richiede ogni implementazione di avere un Id che deriva da oggetto non è vero per i tipi di valore come int .

questo è ciò che il messaggio di errore che dice: The type 'int' must be a reference type in order to use it as parameter 'TId' in the generic type of method IEntity

è sufficiente rimuovere la contraint da IEntity<TId>

Problemi correlati