提问人:pietro 提问时间:10/30/2023 更新时间:10/30/2023 访问量:70
.NET 如何解决层之间所需的泛性
.NET how resolve needed genericity between layers
问:
我有一个问题,对某些人来说可能微不足道。我正在 .NET 中制作一个应用程序,我试图在其中创建拆分层。应用程序(仅抽象)和 Infrstructure(实现)。我的问题是我想使用 Azure TableClient 来存储 Azure 存储表中的数据。但是,存储方法需要在该实体上实现 ITableEntity 接口。我只是无法在存储方法的应用程序层中声明这一点,因为我将依赖 Azure.Data.Tables,而我不想这样做。我真的不知道如何用这个编写我的界面,然后“覆盖”它,我猜。
应用:
public interface ITableStorage
{
public Task SaveItemsAsync<T>(IEnumerable<T> entites, string tableName = nameof(T)) where T : ITableEntity; // where T : ITableEntity is problem
}
基础设施:
public async Task SaveItemsAsync<T>(IEnumerable<T> entites, string tableName = nameof(T)) where T : ITableEntity
{
var tableClient = _tableServiceClient.GetTableClient(tableName);
......
}
提前感谢您的建议。
答:
1赞
NotFound
10/30/2023
#1
完全基于您希望它实现的目标来构建您的接口,而无需考虑实现。例如
public interface ICustomerService
{
public Task AddNewCustomerAsync<T>(Customer customer);
}
完成此操作后,添加实现。
public class TableStorageCustomerService : ICustomerService
{
public async<Task> AddNewCustomerAsync<T>(Customer customer)
{
//map your customer class to your table entity
//save the table entity to your table storage
}
}
如您所见,界面中根本没有实现细节。由于您只使用 ,因此可以自由地将其映射到服务实现中数据库可能需要的任何类。Customer
评论
0赞
pietro
10/30/2023
谢谢。但我想对我的方法有一些抽象。我不想为每个“实体”新方法编写。有灵魂吗?
0赞
NotFound
10/30/2023
如果你想抽象你的实现,你的接口自然会这样定义。当您的实现更改或创建单元测试时,它还提供了很大的灵活性。如果您担心过多的重复,您还可以创建一个总体服务,就像您现在添加到 such 中一样。TableStorageCustomerService
public TableStorageCustomerService(ITableStorage tableStorage)
1赞
JonasH
10/30/2023
#2
解决方案是使用“实体”的多种表示形式。该应用程序使用规范表示,包括方法、逻辑等。然后,将其转换为适合在 Azure 中存储的类型,或存储实体的其他类型。
这确实需要对同一数据进行多次表示,但它确实增加了一些灵活性。如果更改数据模型,则可以保留旧版 Azure 表示形式,以便可以读取旧数据,同时在保存时使用新的实体类型。这类似于数据传输对象的概念。
要进行类型之间的转换,有几个选项:
- 使用类型切换
- 使用访客模式。这样做的好处是,可以强制为每个应用程序类型创建一个 azure 类型。所以忘记的机会更少。
您可能需要为应用程序端的实体提供一些通用接口,以便编译器可以帮助确保您只保存设计为要保存的对象。
一个非常简单的例子来说明这个想法:
public interface IMyEntity{}
public class MyEntity {};
public interface IEntityStorage{
void Save(IMyEntity entity);
}
public class MyEntityAzure : ITableEntity {
public MyEntityAzure(MyEntity entity){
// copy properties etc.
}
public MyEntity ToModel(){
// Convert back to application entity
}
}
public class AzureStorage : IEntityStorage{
private AzureStorage storage;
public void Save(IMyEntity entity){
switch(entity){
case MyEntity myEntity:
storage.Save(new MyEntityAzure(myEntity));
break;
// All other entity classes
}
}
}
评论