我正在构建一个API,我只想在调用者将这些属性包含在HTTP调用的主体中时,为某些属性发送更新。
我目前正在做以下......但它看起来很笨重。有更简单的方法吗?
public void MergePerson(Person basePerson, Person updatedPerson)
{
if (updatedPerson.Title != null)
basePerson.Title = updatedPerson.Title;
if (updatedPerson.Initials != null)
basePerson.Initials = updatedPerson.Initials;
if (updatedPerson.FirstName != null)
basePerson.FirstName = updatedPerson.FirstName;
if (updatedPerson.LastName != null)
basePerson.LastName = updatedPerson.LastName;
if (updatedPerson.Sex != null)
basePerson.Sex = updatedPerson.Sex;
if (updatedPerson.DateOfBirth != null)
basePerson.DateOfBirth = updatedPerson.DateOfBirth;
if (updatedPerson.JobTitle != null)
basePerson.JobTitle = updatedPerson.JobTitle;
<<< snip >>>
由于这个原因......我不得不将像bool这样的东西设置为不可为空,这样我就可以确认它们实际上是传递的,而不是设置为默认的false。
我担心的是有一天我会在模型中添加新字段而忘记在这里添加它们。
答案 0 :(得分:2)
您要做的事情称为修补程序
检查此代码,
public class Car
{
public int Id { get; set; }
[Required]
[StringLength(20)]
public string Make { get; set; }
[Required]
[StringLength(20)]
public string Model { get; set; }
public int Year { get; set; }
[Range(0, 500000)]
public float Price { get; set; }
}
public class CarPatch
{
[StringLength(20)]
public string Make { get; set; }
[StringLength(20)]
public string Model { get; set; }
public int? Year { get; set; }
[Range(0, 500000)]
public float? Price { get; set; }
}
public class CarsController : ApiController
{
private readonly CarsContext _carsCtx = new CarsContext();
// PATCH /api/cars/{id}
public Car PatchCar(int id, CarPatch car)
{
var carTuple = _carsCtx.GetSingle(id);
if (!carTuple.Item1)
{
var response = Request.CreateResponse(HttpStatusCode.NotFound);
throw new HttpResponseException(response);
}
Patch<CarPatch, Car>(car, carTuple.Item2);
// Not required but better to put here to simulate the external storage.
if (!_carsCtx.TryUpdate(carTuple.Item2))
{
var response = Request.CreateResponse(HttpStatusCode.NotFound);
throw new HttpResponseException(response);
}
return carTuple.Item2;
}
// private helpers
private static ConcurrentDictionary<Type, PropertyInfo[]> TypePropertiesCache =
new ConcurrentDictionary<Type, PropertyInfo[]>();
private void Patch<TPatch, TEntity>(TPatch patch, TEntity entity)
where TPatch : class
where TEntity : class
{
PropertyInfo[] properties = TypePropertiesCache.GetOrAdd(
patch.GetType(),
(type) => type.GetProperties(BindingFlags.Instance | BindingFlags.Public));
foreach (PropertyInfo prop in properties)
{
PropertyInfo orjProp = entity.GetType().GetProperty(prop.Name);
object value = prop.GetValue(patch);
if (value != null)
{
orjProp.SetValue(entity, value);
}
}
}
}
答案 1 :(得分:0)
您可以使用反射轻松完成此操作:
public static void MapPersons(object basePerson, object updatedPerson)
{
var sourceT = basePerson.GetType();
var sourceProps = sourceT.GetProperties();
var targetT = updatedPerson.GetType();
var targetProps = targetT.GetProperties();
foreach (var sProp in sourceProps)
{
var sourceValue = sProp.GetValue(basePerson, null);
var propIndex = Array.IndexOf(targetProps, sProp);
if (propIndex != -1)
{
var tProp = targetProps[propIndex];
tProp.SetValue(updatedPerson, sourceValue);
}
}
}
但是这里有很多强大的工具,比如Automapper。他们会为你处理。