Wie machen Mapping in serviceStack.ormlite oder Dapper abhängig vom Spaltentyp?

c# dapper ormlite-servicestack

Frage

Wie kann ich Mapping in ServiceStack.ormlite oder Dapper abhängig vom Spaltentyp machen?

Zum Beispiel habe ich nächste Klassen:

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

Von ORM brauche ich etwas lite das:

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

Wie ich diese Logik sehe:

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

Dann kann ich:

-Nutzen:

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

-wenn ich einen neuen Gerätetyp hinzufügen muss, implementiere ich nur Klasse D: A und bearbeite den Mapper, und berühre die globale Programmlogik nicht.

Dies wird in der Regel im Kontext von ORM und Ð # Idee?

Wenn Sie verstehen, was ich will, geben Sie bitte die Richtung an, wie Sie ähnlich machen. Danke vielmals.

Akzeptierte Antwort

Du erwartest ein bisschen viel von Dapper, was ich fühle. Es ist nicht Dappers Aufgabe, das zu tun. Aber anstatt Ihre eigenen Fabriken zu schreiben, warum stellen Sie nicht einen DI-Container vor? Mit TinyIoC zum Beispiel würden Sie B und C als benannte Implementierungen der Schnittstelle A registrieren. Wenn ein anderer DeviceType kommt, registrieren Sie einfach eine neue Implementierung und Sie sind im Geschäft.

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

    }
}

Beliebte Antwort

Ich würde B oder C von A ableiten. Stattdessen würde ich sie ein Mitglied Instanz machen besitzen. Sie könnten immer noch B und C eine Schnittstelle implementieren:

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

Dann können Sie Linq verwenden, um Instanzen von B oder C als IProcessA :

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

Wenn Sie neue Typen D oder E hinzufügen möchten, sollten Sie die in Select Arbeit in eine Methode oder Fabrik verschieben, die Sie später hinzufügen könnten.



Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum