如何从父类中的名称动态设置属性?
Posted
技术标签:
【中文标题】如何从父类中的名称动态设置属性?【英文标题】:How do I Dynamically set properties from the name in a parent class? 【发布时间】:2021-12-30 03:41:31 【问题描述】:如何将每个 AlarmModel 的“名称”属性动态设置为父类中的模型名称(即 HardwareFault)?
public class NotificationModel
public string UnrelatedProperty get; set; // any solution should ignore other properties.
public AlarmModel HardwareFault get; set;
public AlarmModel TimeoutFault get; set;
public AlarmModel GenericFault get; set;
public class AlarmModel
public string Name get; set;
public bool isActive get; set;
public bool isEnabled get; set;
public bool isSilenced get; set;
【问题讨论】:
【参考方案1】:您应该将属性“名称”移动到父类。并尝试将其扩展/继承到子类。
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案2】:如果您已经初始化 NotificationModel
并且已经初始化了HardwareFault
、TimeoutFault
、GenericFault
属性,则可以使用此示例:
var notificationModel = new NotificationModel()
HardwareFault = new AlarmModel(),
GenericFault = new AlarmModel(),
TimeoutFault = new AlarmModel()
;
notificationModel?.GetType().GetProperties().Where(p => p.PropertyType.Name == "AlarmModel") // Or p.PropertyType == typeof(AlarmModel)
.ToList().ForEach(alarmModelProperty =>
// Get AlarmModel property instance
var alarmModelInstance = alarmModelProperty.GetValue(notificationModel);
// Get Name property
var nameProperty = alarmModelIntance?.GetType().GetProperty("Name");
// Set Name property value with name of AlarmModel property
nameProperty?.SetValue(alarmModelInstance, alarmModelProperty.Name);
);
如果你有已经初始化NotificationModel
,但没有初始化HardwareFault
、TimeoutFault
、GenericFault
属性,你可以使用这个例子:
var notificationModel = new NotificationModel();
notificationModel?.GetType().GetProperties().Where(p => p.PropertyType.Name == "AlarmModel") // Or p.PropertyType == typeof(AlarmModel)
.ToList().ForEach(alarmModelProperty =>
// Initialize new AlarmModel
var alarmModelInstance = Activator.CreateInstance(alarmModelProperty.PropertyType);
// Get Name property of AlarmModel
var nameProperty = alarmModelInstance.GetType().GetProperty("Name");
// Set Name property of AlarmModel
nameProperty?.SetValue(alarmModelInstance, alarmModelProperty.Name);
// Set AlarmModel property of NotificationModel
alarmModelProperty.SetValue(notificationModel, alarmModelInstance);
);
如果您需要使用反射进行完全初始化,可以使用以下示例:
var notificationModelType = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(type => type.Name == "NotificationModel"); // Or type == typeof(NotificationModel)
if (notificationModelType is null) // No NotificationModel found in current assembly
return;
// Initializing NotificationModel
var notificationModel = Activator.CreateInstance(notificationModelType);
notificationModel?.GetType().GetProperties().Where(p => p.PropertyType.Name == "AlarmModel") // Or p.PropertyType == typeof(AlarmModel)
.ToList().ForEach(alarmModelProperty =>
// Initialize new AlarmModel
var alarmModelInstance = Activator.CreateInstance(alarmModelProperty.PropertyType);
// Get Name property of AlarmModel
var nameProperty = alarmModelInstance.GetType().GetProperty("Name");
// Set Name property of AlarmModel
nameProperty?.SetValue(alarmModelInstance, alarmModelProperty.Name);
// Set AlarmModel property of NotificationModel
alarmModelProperty.SetValue(notificationModel, alarmModelInstance);
);
如果NotificationModel
声明不在当前程序集中(所以它不会在Assembly.GetExecutingAssembly().GetTypes()
中) - 您可以在AppDomain.CurrentDomain
中搜索所有已加载的程序集:
var notificationModelType = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(assembly => assembly.GetTypes())
.FirstOrDefault(type => type.Name == "NotificationModel");
【讨论】:
【参考方案3】:如果我理解正确,您想将每个AlarmModel
的Name
属性设置为父NotificationModel
中的属性名称?
如果是这样,你可以这样做:
public class NotificationModel
private AlarmModel _hardwareFault;
private AlarmModel _timeoutFault;
private AlarmModel _genericFault;
public string UnrelatedProperty get; set; // any solution should ignore other properties.
public AlarmModel HardwareFault
get => _hardwareFault;
set
_hardwareFault = value;
SetName(value);
public AlarmModel TimeoutFault
get => _timeoutFault;
set
_timeoutFault= value;
SetName(value);
public AlarmModel GenericFault
get => _genericFault;
set
_genericFault= value;
SetName(value);
private void SetName(AlarmModel model, [CallerMemberName] string propertyName = null)
model.Name = propertyName;
【讨论】:
private SetName
缺少 void
的返回类型。另外我建议为model.Name
(例如if (model is not null) model.Name = propertyName;
)添加一个空检查以避免NullReferenceException
。以上是关于如何从父类中的名称动态设置属性?的主要内容,如果未能解决你的问题,请参考以下文章