【问题标题】:How to reference property of another object if the current object's property is null如果当前对象的属性为空,如何引用另一个对象的属性
【发布时间】:2021-12-29 23:59:46
【问题描述】:

我有一个public Dictionary<string, PostRenewalActionJobs> Jobs 来存储我想为特定帐户触发的一些操作,此字典的键是帐户名称。

    public class PostRenewalActionJobs
    {
        public List<AlterDatabaseLinkJob> AlterDataBaseLink { get; set; }
        public DatabaseConnectionCheckJob DatabaseConnectionCheck { get; set; }
        public UnlockDatabaseAccountJob UnlockDatabaseAccount { get; set; }
        public LinuxConnectionCheckJob LinuxConnectionCheck { get; set; }
        public WindowsConnectionCheckJob WindowsConnectionCheck { get; set; }
        public ReplacePasswordInFileJob ReplacePasswordInFile { get; set; }
    }

PostRenewalActionJobs 类型的属性(AlterDataBaseLinkDatabaseConnectionCheck 等)可以使用* 作为字典中的键为特定帐户或所有帐户定义:

通过使用以下方法,我可以检索帐户的作业(如果存在)或一般作业:

public PostRenewalActionJobs GetJobsForAccount(string accountName)
{
  return Jobs.ContainsKey(accountName) ? Jobs[accountName] : Jobs["*"];
}

如果来自特定帐户的对象为空,我希望有一种从所有帐户对象 ("*") 获取工作的动态方式。

类似下面的内容,但没有为所有作业类型重复相同的代码,并且在引入新作业类型时应该可以工作的解决方案。

var dbConCheckJob = GetJobsForAccount("someAccount").AlterDataBaseLink;

if(dbConCheckJob == null || !dbConCheckJob.Any())
{
  dbConCheckJob = GetJobsForAccount("*").AlterDataBaseLink
}

我想使用一些反射,但我不知道该怎么做。

【问题讨论】:

  • 每个不同的作业类型之间是否有共同点,例如接口或基类?
  • 是的,它们都继承了一个基类名称JobBase
  • 您是否需要为每个不同的工作类型提供离散属性,或者您是否可以拥有一个作为 JobBase 集合(例如 List)的属性?
  • 我不确定我是否在关注这个问题。
  • @Mihaimyh - “如果来自特定帐户的帐户为空”是什么意思?

标签: c# .net


【解决方案1】:

您不需要使用反射。您已经可以确定是为某个帐户获取特定工作还是通用工作,然后您可以使用Func 来获取您想要的工作:

public TJob GetPostJobForAccount<TJob>(string accountName,
    Func<PostRenewalActionJobs, TJob> jobSelector) where TJob : JobBase
{
    var genericJobs = Jobs["*"];
    var accountJobs = Jobs.ContainsKey(accountName) ? Jobs[accountName] : genericJobs;

    // Account might be defined but without any job of the given type 
    // hence selecting from the defaults if need be
    return jobSelector(accountJobs) ?? jobSelector(genericJobs);
}

var bobJob = GetPostJobForAccount("bob", x => x.WindowsConnectionCheck);
var aliceJob = GetPostJobForAccount("alice", x => x.UnlockDatabaseAccount);

【讨论】:

    【解决方案2】:

    我找到了办法,不知道有没有更好的办法:

    public TJob GetPostJobForAccount<TJob>(string accountName)
    {
    
        Type type = typeof(PostRenewalActionJobs);
    
        var accountJobs = Jobs[accountName];
        var generalJobs = Jobs["*"];
    
        foreach (var item in type.GetProperties())
        {
            var itemType = item.PropertyType;
            var currentType = typeof(TJob);
    
            if (itemType != currentType)
            {
                continue;
            }
    
            var output = (TJob)accountJobs?.GetType()?.GetProperty(item.Name)?.GetValue(accountJobs, null);
    
            if (output is null)
            {
                output = (TJob)accountJobs?.GetType()?.GetProperty(item.Name)?.GetValue(generalJobs, null);
            }
    
            return output;
    
        }
    
        return default;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-10
      • 2016-10-04
      • 2011-01-26
      • 2019-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      相关资源
      最近更新 更多