【问题标题】: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; }
}

【问题讨论】:

    标签: c# linq class reflection


    【解决方案1】:

    您应该将属性“名称”移动到父类。并尝试将其扩展/继承到子类。

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案2】:

    如果您已经初始化 NotificationModel 并且已经初始化了HardwareFaultTimeoutFaultGenericFault 属性,则可以使用此示例:

    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,但没有初始化HardwareFaultTimeoutFaultGenericFault属性,你可以使用这个例子:

    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】:

      如果我理解正确,您想将每个AlarmModelName 属性设置为父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
      猜你喜欢
      • 1970-01-01
      • 2018-05-22
      • 2014-03-10
      • 1970-01-01
      • 1970-01-01
      • 2019-09-15
      • 2015-01-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多