我正在使用客户端来调用API。在API中-我希望从请求正文中填充模型-但我希望根据单个属性的名称以不同的方式构造模型。基本上,我想使用数据模型创建类似开关/案例方案的东西,但是不确定如何实现此目的。最后一个模型包含基于我要达到的目标的伪代码(显然,通用类型无法按照我所描述的方式工作,但我认为它可以完成我的示例)。这是我的示例:
控制器:
[HttpPost("customer", Name = "Submit Customer")]
public IActionResult ActivateCustomer([FromBody]Customer customer)
{
//Do something with the Customer object.
return Ok();
}
客户模型:
public class Customer
{
public CustomerInfo customerInfo { get; set; }
public SponserInfo sponserInfo { get; set; }
}
CustomerInfo:
public class CustomerInfo
{
public int CustomerId { get; set; }
public string CustomerName { get; set; }
//etc.
}
SponserA:
public class SponserA
{
public int ReferenceId { get; set; }
public string Password { get; set; }
}
SponserB:
public class SponserB
{
public string UserName{ get; set; }
public string Relation { get; set; }
public string Department { get; set; }
}
SponserInfo :(我想要的伪代码)
public class SponserInfo
{
public string SponserName { get; set; }
public T SponserInfo { get; set; }
switch(this.SponserName)
{
case "Sponser A's Name":
T = SponserA;
break;
case "Sponser B's Name":
T = SponserB;
break;
}
}
答案 0 :(得分:1)
怎么样呢?
public abstract class SponsorInfo
{
public string SponserName { get; set; }
protected SponsorInfo(string sponserName)
{
SponserName = sponserName;
}
}
public class SponsorA : SponsorInfo
{
public int ReferenceId { get; set; }
public string Password { get; set; }
public SponsorA(string sponserName, int referenceId, string password)
: base(sponserName)
{
ReferenceId = referenceId;
Password = password;
}
}
public class SponsorB : SponsorInfo
{
public string UserName { get; set; }
public string Relation { get; set; }
public string Department { get; set; }
public SponsorB(string sponsorName, string userName, string relation, string department)
: base(sponsorName)
{
UserName = userName;
Relation = relation;
Department = department;
}
}
然后,不理会客户类(但要解决输入错误):
public class Customer
{
public CustomerInfo customerInfo { get; set; }
public SponsorInfo sponsorInfo { get; set; }
}
,然后在您的控制器中添加switch语句,并根据数据的外观构造SponsorA
或SponsorB
。这两个都是SponsorInfo,因此您可以将其作为sponsorInfo
对象中的Customer
附加。
答案 1 :(得分:0)
为什么不创建一个包含所有字段的名为Sponsor
的模型,然后如果ReferenceId
为空,您会知道它是哪种赞助商?
public class SponsorInfo
{
public int? ReferenceId { get; set; }
public string Password { get; set; }
public string UserName { get; set; }
public string Relation { get; set; }
public string Department { get; set; }
}
[HttpPost("customer", Name = "Submit Customer")]
public IActionResult ActivateCustomer([FromBody]Customer customer)
{
//Do something with the Customer object.
if (customer.sponsorInfo.ReferenceId == null || !customer.sponsorInfo.ReferenceId.HasValue)
{
//is SponsorB
}
else
{
//is SponsorA
}
return Ok();
}
答案 2 :(得分:0)
这是一种可扩展的方式。
属性将赞助者名称映射到子类,因此SponsorInfo不必知道所有子类。
它对所有赞助者类型都使用抽象基类(Sponsor
)(也由@ Flydog57建议)。
分配了SponsorInfo.SponsorName
时,将创建其子类的实例(因此您必须首先分配SponsorName
)。
您可以根据实际从模型映射属性的方式进行调整。
using System;
using System.Linq;
using System.Reflection;
/// <summary>
/// Attribute to indicate the name mapped to a <see cref="Sponsor"/> subclass.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class SponsorAttribute : Attribute
{
public SponsorAttribute(string name)
{
this.Name = name;
}
/// <summary>
/// The value that <see cref="SponserInfo.SponserName"/> must match for the attribute class to be used.
/// </summary>
public virtual string Name { get; set; }
}
public abstract class Sponsor
{
public int ReferenceId { get; set; }
public string Password { get; set; }
}
[Sponsor("Sponser A's Name")]
public class SponsorA : Sponsor
{
}
[Sponsor("Sponser B's Name")]
public class SponsorB : Sponsor
{
public string Department { get; set; }
}
// More subclasses can be added.
public class SponsorInfo
{
/// <summary>
/// The Sponsor name.
/// Changing this sets <see cref="Sponsor"/> to a new instance of the corresponding class.
/// </summary>
public string SponsorName
{
get { return _sponsorName; }
set
{
if (_sponsorName != value)
{
_sponsorName = value;
// Find a Sponsor subclass with a SponsorAttribute.Name matching the given value:
Type sponsorType = Assembly.GetExecutingAssembly().GetTypes() // you might want to also scan other assemblies
.Where(t =>
t.IsSubclassOf(typeof(Sponsor))
&& (t.GetCustomAttribute<SponsorAttribute>()?.Name?.Equals(_sponsorName) ?? false)
).FirstOrDefault(); // null if none is found
if (sponsorType == null)
Sponsor = null; // no matching class
else
Sponsor = (Sponsor)Activator.CreateInstance(sponsorType); // new instance of the matching class
}
}
}
private string _sponsorName;
public Sponsor Sponsor { get; set; } // renamed from "SponsorInfo" because that's the name of this class
}