Comment rendre le mappage dans serviceStack.ormlite ou Dapper dépendant du type de colonne?

c# dapper ormlite-servicestack

Question

Comment puis-je faire le mappage dans serviceStack.ormlite ou Dapper en fonction du type de colonne?

Par exemple, j'ai les prochaines classes:

//table A
abstract Class A
{
  public ulong? id {get; set}
  public string Name {get; set}
  public string DeviceType {get; set}

  abstract public void method()
}

//no table
Class B : A
{
  public override void method()
  {
    //dependent on B implementation
  }
}

//no table
Class C : A
{
  public override void method()
  {
    //dependent on C implementation
  }
}

De l'ORM, j'ai besoin de quelque chose qui:

List<A> items = orm.Must_Return_list_With_B_and_C_Instances_From_A_Table();

Comment je vois cette logique:

function Must_Return_list_With_B_and_C_Instances_From_A_Table()
{
  var items = new List<A>();
  foreach(var row in rows)
  {
    if (row.DeviceType == "B")
    {
      items.Add(new B(row)); // mean mapping there
    }
    else if (row.DeviceType == "A")
    {
      items.Add(new C(row)); // mean mapping there
    }
  }
}

Alors je peux:

-use suivant:

foreach(var item in items)
{
  item.method(); // calls the right method  of class B or C
}

-si j'ai besoin d'ajouter un nouveau deviceType je n'implémente que la classe D: A et édite le mappeur, et ne touche pas à la logique du programme global.

Ceci est généralement implémenté dans le contexte de l'ORM et de l'idée С #?

Si vous comprenez ce que je veux, veuillez indiquer la direction à suivre pour faire la même chose. Merci beaucoup.

Réponse acceptée

Vous vous attendez un peu à Dapper. Ce n'est pas le travail de Dapper. Mais au lieu d'écrire vos propres usines, pourquoi ne pas introduire un conteneur DI? Avec TinyIoC par exemple, vous enregistrez B et C en tant qu'implémentations nommées de l'interface A. Lorsqu'un autre DeviceType arrive, vous venez d'enregistrer une nouvelle implémentation et vous êtes en affaires.

public interface A
{
    POCO poco { get; set; }
    void MyMethod();
}
public class B : A
{
    public void MyMethod()
    {
        throw new NotImplementedException();
    }
    public POCO poco { get; set; }
}
public class C : A
{
    public void MyMethod()
    {
        throw new NotImplementedException();
    }
    public POCO poco { get; set; }

}
public class POCO
{
    public ulong? id { get; set; }
    public string Name { get; set; }
    public string DeviceType { get; set; }
}

public class Program
{
    public static void main()
    {
        var ctr = TinyIoCContainer.Current;
        ctr.Register<A, B>("B");
        ctr.Register<A, C>("C");
        List<A> devices = new List<A>();
        using (var db = new SqlConnection(Config.DefaultConnectionString))
        {
            db.Open();
            List<POCO> queryResults = db.Query<POCO>("SELECT * FROM Devices").ToList();
            foreach (var queryResult in queryResults)
            {
                // the magic step where we create the right type of A based on the value in column Name...
                var newDevice = ctr.Resolve<A>(queryResult.Name);
                newDevice.poco = queryResult;
                devices.Add(newDevice);
            }
        }

    }
}

Réponse populaire

Je ne ferais pas B ou C de A Au lieu de cela, je les ferais posséder une instance membre. Vous pourriez toujours avoir B et C implémenter une interface:

interface IProcessA
{
    void Method();
}

class B : IProcessA
{
    readonly A _a;

    public B(A a)
    {
        _a = a;
    }

    public void Method()
    {
        // do something with _a
    }
}

class C : IProcessA
{
    readonly A _a;

    public C(A a)
    {
        _a = a;
    }

    public void Method()
    {
        // do something different with _a
    }
}

Vous pouvez ensuite utiliser Linq pour renvoyer des instances de B ou C tant IProcessA :

List<IProcessA> items = dbResult.Select(a => a.DeviceType == "B" ? new B(a) : new C(a))
    .ToList();

Si vous souhaitez ajouter de nouveaux types D ou E , vous souhaitez déplacer le travail effectué dans la méthode Select vers une méthode ou une fabrique que vous pouvez ajouter ultérieurement.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi