将 C# 方法转换为泛型方法
Converting c# methods to a generic method
如何将这两个 ConvertDtoListToAddresses
和 ConvertDtoListToDocuments
C# 方法转换为 generic
?我试过传递两个通用类型变量,但是当我在循环中进入 'Add' 时,我遇到了各种错误。从 DTO 到其各自 DBO 的转换是在 DBO 的构造函数中完成的,我认为这是问题的一部分。
private void ConvertDtoToPerson(PersonDTO dto)
{
Id = dto.Id;
Fname = dto.FirstName;
Mname = dto.MiddleName;
Lname = dto.LastName;
Suffix = dto.Suffix;
Maiden = dto.MaidenName;
Addresses = ConvertDtoListToAddresses(dto.AddressesDto); // want to convert to generic
Documents = ConvertDtoListToDocuments(dto.DocumentsDto); // want to convert to generic
}
private static ICollection<Address>? ConvertDtoListToAddresses(ICollection<AddressDTO>? addressesDto)
{
if (addressesDto is not null && addressesDto.Any())
{
ICollection<Address> addys = new List<Address>();
foreach (AddressDTO dto in addressesDto)
{
// Converts from dto in constructor
addys.Add(new Address(dto));
}
return addys;
}
return null;
}
private static ICollection<Document>? ConvertDtoListToDocuments(ICollection<DocumentDTO>? documentsDto)
{
if (documentsDto is not null && documentsDto.Any())
{
ICollection<Document> docs = new List<Document>();
foreach (DocumentDTO dto in documentsDto)
{
// Converts from dto in constructor
docs.Add(new Document(dto));
}
return docs;
}
return null;
}
这是我尝试过的:
Addresses = ConvertDtoListToType<Address, AddressDTO>(dto.AddressesDto);
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection)
{
if (dtoCollection is not null && dtoCollection.Any())
{
ICollection<T> tList = new List<T>();
foreach (D dto in dtoCollection)
{
tList.Add(new T(dto)); // <-- This is where I'm having trouble
}
return tList;
}
return null;
}
使用 Func<D, T> factory
参数可以解决这个问题。
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection, Func<D, T> factory)
{
if (dtoCollection is not null && dtoCollection.Any())
{
ICollection<T> tList = new List<T>();
foreach (D dto in dtoCollection)
{
tList.Add(factory(dto));
}
return tList;
}
return null;
}
请记住,这 几乎 语义等同于此:
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection, Func<D, T> factory)
=> dtoCollection?.Select(d => factory(d))?.ToList();
我质疑一个空 dtoCollection
应该 return 一个 null
最终集合的想法。这可能是一个更好的实现。
因此,话虽如此,您的原始方法提供的功能优势非常小。这是为了代码而编写的代码。一个简单的 Select
/ToList
对让您的代码简单。
在任何情况下,您都可以提供 Address
和 Document
的静态方法来提供您需要的 Func<D, T>
。
public class Address
{
AddressDTO dto;
public static Address CreateFromDto(AddressDTO dto)
=> new Address(dto);
public Address(AddressDTO dto)
{
this.dto = dto;
}
}
现在,调用它是这样的:
var addresses = ConvertDtoListToType(addressDtos, Address.CreateFromDto);
或:
var addresses = addressDtos?.Select(Address.CreateFromDto)?.ToList();
您需要的是能够对类型 T
提供约束,以表明它具有采用类型 D
参数的构造函数。像这样:
private static ICollection<T>? ConvertDtoListToType<T, D>(
ICollection<D>? dtoCollection) where T : new(D)
{}
但这在C#中是不存在的。解决方法是提供一个工厂方法来创建给定类型 D
的类型 T
。即类似于:
private static ICollection<T>? ConvertDtoListToType<T, D>(
ICollection<D>? dtoCollection, Func<D, T> factory)
{
// Use factory(dto), instead of new T(dto)
}
但是正如@Zee 所说,您应该看看 Automapper,它可以在集合类型之间进行转换。
如何将这两个 ConvertDtoListToAddresses
和 ConvertDtoListToDocuments
C# 方法转换为 generic
?我试过传递两个通用类型变量,但是当我在循环中进入 'Add' 时,我遇到了各种错误。从 DTO 到其各自 DBO 的转换是在 DBO 的构造函数中完成的,我认为这是问题的一部分。
private void ConvertDtoToPerson(PersonDTO dto)
{
Id = dto.Id;
Fname = dto.FirstName;
Mname = dto.MiddleName;
Lname = dto.LastName;
Suffix = dto.Suffix;
Maiden = dto.MaidenName;
Addresses = ConvertDtoListToAddresses(dto.AddressesDto); // want to convert to generic
Documents = ConvertDtoListToDocuments(dto.DocumentsDto); // want to convert to generic
}
private static ICollection<Address>? ConvertDtoListToAddresses(ICollection<AddressDTO>? addressesDto)
{
if (addressesDto is not null && addressesDto.Any())
{
ICollection<Address> addys = new List<Address>();
foreach (AddressDTO dto in addressesDto)
{
// Converts from dto in constructor
addys.Add(new Address(dto));
}
return addys;
}
return null;
}
private static ICollection<Document>? ConvertDtoListToDocuments(ICollection<DocumentDTO>? documentsDto)
{
if (documentsDto is not null && documentsDto.Any())
{
ICollection<Document> docs = new List<Document>();
foreach (DocumentDTO dto in documentsDto)
{
// Converts from dto in constructor
docs.Add(new Document(dto));
}
return docs;
}
return null;
}
这是我尝试过的:
Addresses = ConvertDtoListToType<Address, AddressDTO>(dto.AddressesDto);
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection)
{
if (dtoCollection is not null && dtoCollection.Any())
{
ICollection<T> tList = new List<T>();
foreach (D dto in dtoCollection)
{
tList.Add(new T(dto)); // <-- This is where I'm having trouble
}
return tList;
}
return null;
}
使用 Func<D, T> factory
参数可以解决这个问题。
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection, Func<D, T> factory)
{
if (dtoCollection is not null && dtoCollection.Any())
{
ICollection<T> tList = new List<T>();
foreach (D dto in dtoCollection)
{
tList.Add(factory(dto));
}
return tList;
}
return null;
}
请记住,这 几乎 语义等同于此:
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection, Func<D, T> factory)
=> dtoCollection?.Select(d => factory(d))?.ToList();
我质疑一个空 dtoCollection
应该 return 一个 null
最终集合的想法。这可能是一个更好的实现。
因此,话虽如此,您的原始方法提供的功能优势非常小。这是为了代码而编写的代码。一个简单的 Select
/ToList
对让您的代码简单。
在任何情况下,您都可以提供 Address
和 Document
的静态方法来提供您需要的 Func<D, T>
。
public class Address
{
AddressDTO dto;
public static Address CreateFromDto(AddressDTO dto)
=> new Address(dto);
public Address(AddressDTO dto)
{
this.dto = dto;
}
}
现在,调用它是这样的:
var addresses = ConvertDtoListToType(addressDtos, Address.CreateFromDto);
或:
var addresses = addressDtos?.Select(Address.CreateFromDto)?.ToList();
您需要的是能够对类型 T
提供约束,以表明它具有采用类型 D
参数的构造函数。像这样:
private static ICollection<T>? ConvertDtoListToType<T, D>(
ICollection<D>? dtoCollection) where T : new(D)
{}
但这在C#中是不存在的。解决方法是提供一个工厂方法来创建给定类型 D
的类型 T
。即类似于:
private static ICollection<T>? ConvertDtoListToType<T, D>(
ICollection<D>? dtoCollection, Func<D, T> factory)
{
// Use factory(dto), instead of new T(dto)
}
但是正如@Zee 所说,您应该看看 Automapper,它可以在集合类型之间进行转换。