2016-12-16 8 views
1

Как я могу сделать сопоставление в serviceStack.ormlite или Dapper в зависимости от типа столбца?Как сделать сопоставление в 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 
    } 
} 

От ОРМ мне нужно что-то облегченной, что:

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

Тогда я могу:

-u себе следующий:

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

-если мне нужно добавить новый DeviceType я реализую только класса D: A и редактировать картографа, и не коснитесь глобальной логики программы.

Это обычно реализуется в контексте идей ORM и С #?

Если вы понимаете, что я хочу, укажите направление, как сделать подобное. Большое спасибо.

ответ

1

Вы ожидаете немного ощущения от Даппера. Это не работа Даппера. Но вместо того, чтобы писать свои собственные фабрики, почему бы вам не ввести контейнер 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); 
      } 
     } 

    } 
} 
2

Я бы не сделал B или C от A. Вместо этого я бы сделал их собственностью экземпляром участника. Вы могли бы еще B и C реализовать некоторый интерфейс:

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, на метод или завод, которые вы могли бы добавить позже.

+0

Мне это нравится. Интерфейсы здесь - то, что мне нужно. Но я позабочусь о вашем решении чуть позже. Я хочу знать, возможно ли это, что делает linq.select делать это в сопоставлениях ORM. – Vilix

+0

Потому что мы итерируем коллекцию дважды, один раз, когда ORM-сопоставления, второй, когда выбирается linq. – Vilix