Aggiungi un ICrudRepository invariante di chiave che può essere implementato dall'ignoranza

1

In questo esempio, TItem.GetKeyType() è ciò che mi piacerebbe ottenere.

Definizione dell'interfaccia del repository CRUD di base:

ICrudRepository<TItem> where TItem : BaseItem where TKey : TItem.GetKeyType()
public Tkey Id { get; set; }

Definizione entità di base:

class BaseItem<TKey>
this.GetKeyType = Tkey.GetType()

Implementazione delle entità:

class Book : BaseItem<Int> //declaration of item's tkey

Implementazione dell'interfaccia CRUD:

IBooksRepository : ICrudRepository<Book>
BookRepository : IBookRepository --> Ignorance of key struct

In questo modo, chiunque implementa BooksRepository è costretto a utilizzare la struttura di implementazione dell'entità, int in questo caso. Inoltre, potrei definire nuove entità usando chiavi diverse usando la stessa entità di base e il repository crud, per esempio

class Truck : BaseItem<Guid>

Al momento ci sono 2 problemi

  1. Nell'interfaccia CRUD, non posso chiamare TItem.GetKeyType (), anche se so che il suo tipo è BaseItem, quindi deve definire questo metodo
  2. Non posso chiamare TKey.GetType () su BaseItem, anche se deve essere una struct, definendo così questo metodo

C'è un modo per ottenere questo tipo di pattern, senza dover definire più BaseEntities e CRUD Repositories per ogni tipo di chiave / struttura che si intende utilizzare, su un sistema in cui le chiavi possono essere di tipi diversi?

    
posta Alexander D 09.05.2017 - 11:51
fonte

1 risposta

3

Ok, ho provato questo e sembra funzionare.

La cosa fondamentale di cui hai bisogno nel repository è ..

return typeof(TItem).BaseType.GenericTypeArguments[0];

Nel BaseItem ..

return typeof(TKey);

Non puoi fare il

where TItem : BaseItem<???> 

ma puoi rendere BaseItem ereditato da una classe RootItem vuota e usarlo invece.

Tuttavia !!

Poiché si tratta dell'ingegneria del software anziché dello stack overflow, aggiungerò che disapprovo l'intero schema del repository generico.

Penso che il difetto sia che avendo un repository per classe si perdono le relazioni tra le classi e le funzionalità extra specializzate come GetBooksByAuthorId (string AuthorId)

Modifica - codice completo

class Program
{
    static void Main(string[] args)
    {
        var repo = new BookRepo();
        repo.Items.Add(new Book());
        var item = repo.Items.FirstOrDefault();

        Console.WriteLine(repo.IndexType);
        Console.WriteLine(item.IndexType);
        Console.ReadLine();
    }
}
public abstract class RootItem
{
    public virtual Type IndexType
    {
        get
        {
            return null;
        }
    }
}
public class Item<TKey> : RootItem
{
    public TKey Id { get; set; }

     public override Type IndexType
    {
        get
        {
            return typeof(TKey);
        }
    }
}

public class Book : Item<int>
{

}

public class BaseRepo<TItem> where TItem : RootItem
{
    public List<TItem> Items { get; set; }
    public Type IndexType
    {
        get
        {
            return typeof(TItem).BaseType.GenericTypeArguments[0];
        }
    }
    public BaseRepo()
    {
        this.Items = new List<TItem>();
    }
}

public class BookRepo : BaseRepo<Book>
{

}
    
risposta data 09.05.2017 - 21:47
fonte

Leggi altre domande sui tag