¿De qué manera la asignación en serviceStack.ormlite o Dapper depende del tipo de columna?

c# dapper ormlite-servicestack

Pregunta

¿Cómo puedo hacer un mapeo en serviceStack.ormlite o Dapper dependiendo del tipo de columna?

Por ejemplo, tengo las siguientes clases:

//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
  }
}

Desde ORM necesito algo lite que:

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

Cómo veo esta lógica:

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
    }
  }
}

Entonces you puedo:

-use a continuación:

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

-si necesito agregar un nuevo tipo de dispositivo, implemento solo la clase D: A y edito el mapeador, y no toco la lógica del programa global.

Esto generalmente se implementa en el contexto de ORM y С # idea?

Si entiende lo que quiero, indique la dirección de cómo hacer similares. Muchas gracias.

Respuesta aceptada

Estás esperando un poco más de Dapper que siento. No es el trabajo de Dapper hacer esto. Pero en lugar de escribir sus propias fábricas, ¿por qué no introduce un contenedor DI? Con TinyIoC, por ejemplo, registrarías B y C como implementaciones con nombre de la interfaz A. Cuando aparece otro DeviceType, solo registras una nueva implementación y estás en el negocio.

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);
            }
        }

    }
}

Respuesta popular

Yo no haría que B o C deriven de A En cambio, les haría tener una instancia miembro. Todavía podría tener B y C implementar alguna interfaz:

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
    }
}

Luego puede usar Linq para devolver instancias de B o C como IProcessA :

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

Si va a agregar nuevos tipos D o E , querrá mover el trabajo realizado en el Select a un método o fábrica que podría agregar más adelante.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué