serviceStack.ormlite 或 Dapper 中的映射如何依赖于列类型?
How make mapping in serviceStack.ormlite or Dapper dependent on column type?
如何根据列类型在 serviceStack.ormlite 或 Dapper 中进行映射?
例如我有下一个 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
}
}
从 ORM 我需要一些简单的东西:
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
}
-如果我需要添加新的设备类型,我只实现 class D : A 并编辑映射器,不要触及全局程序逻辑。
这个一般是在ORM和C#idea的背景下实现的?
如果你明白我想要什么,请指出如何制作相似的方向。非常感谢。
我不会让 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
的 return 实例用作 IProcessA
:
List<IProcessA> items = dbResult.Select(a => a.DeviceType == "B" ? new B(a) : new C(a))
.ToList();
如果您要添加新类型 D
或 E
,您可能希望将 Select
中完成的工作移至您可以添加的方法或工厂稍后。
我觉得您对 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);
}
}
}
}
如何根据列类型在 serviceStack.ormlite 或 Dapper 中进行映射?
例如我有下一个 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
}
}
从 ORM 我需要一些简单的东西:
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
}
-如果我需要添加新的设备类型,我只实现 class D : A 并编辑映射器,不要触及全局程序逻辑。
这个一般是在ORM和C#idea的背景下实现的?
如果你明白我想要什么,请指出如何制作相似的方向。非常感谢。
我不会让 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
的 return 实例用作 IProcessA
:
List<IProcessA> items = dbResult.Select(a => a.DeviceType == "B" ? new B(a) : new C(a))
.ToList();
如果您要添加新类型 D
或 E
,您可能希望将 Select
中完成的工作移至您可以添加的方法或工厂稍后。
我觉得您对 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);
}
}
}
}