serviceStack.ormlite 또는 Dapper의 매핑을 열 유형에 의존하는 방법은 무엇입니까?

c# dapper ormlite-servicestack

문제

어떻게 serviceStack.ormlite 또는 Dapper에 매핑 할 수 있습니까?

예를 들어 다음 수업이 있습니다.

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

ORM에서 나는 lite가 필요합니다 :

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

나는이 논리를 어떻게 보았는가?

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

그러면 나는 할 수있다 :

- 다음 사용 :

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

- 새로운 deviceType을 추가해야한다면 D 클래스 만 구현하고 매퍼를 편집하고 전역 프로그램 로직을 건드리지 마십시오.

이것은 일반적으로 ORM 및 С # idea의 컨텍스트에서 구현됩니까?

내가 원하는 것을 이해한다면, 비슷한 방법을 제시해주십시오. 많은 감사합니다.

수락 된 답변

당신은 내가 생각하는 Dapper에 대해 약간의 기대를하고 있습니다. Dapper가하는 일이 아닙니다. 하지만 자신의 공장을 쓰는 대신 DI 컨테이너를 도입하는 것이 어떻습니까? 예를 들어, TinyIoC를 사용하면 B와 C를 인터페이스 A의 명명 된 구현으로 등록 할 수 있습니다. 다른 DeviceType이 나오면 새 구현을 등록하면됩니다.

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

    }
}

인기 답변

B 또는 CA 에서 파생시키지 않을 것입니다. 대신에, 나는 그들이 멤버 인스턴스를 소유 할 것입니다. 당신은 여전히 BC 가 어떤 인터페이스를 구현하도록 할 수 있습니다 :

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

그런 다음 Linq를 사용하여 B 또는 C 중 하나의 인스턴스를 IProcessA 로 반환 할 수 있습니다.

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

새로운 유형 D 또는 E 추가하려는 경우 나중에 Select 수있는 방법 또는 팩토리로 Select 에서 완료된 작업을 이동하려고합니다.



아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.