简体   繁体   English

如果当前对象的属性是 null,如何引用另一个 object 的属性

[英]How to reference property of another object if the current object's property is null

I have a public Dictionary<string, PostRenewalActionJobs> Jobs to store some actions I would like to trigger for specific accounts, the key of this dictionary being the account name.我有一个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; }
    }

The properties of PostRenewalActionJobs type ( AlterDataBaseLink , DatabaseConnectionCheck , etc) can be defined for a specific account or for all accounts by using * as key in the dictionary: PostRenewalActionJobs类型( AlterDataBaseLinkDatabaseConnectionCheck等)的属性可以通过使用*作为字典中的键为特定帐户或所有帐户定义:

By using below method I am able to retrieve the jobs for an account (if exists) or the general jobs:通过使用以下方法,我可以检索帐户的作业(如果存在)或一般作业:

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

I would like to have a dynamic way of getting a job from the all accounts object ("*") if the one from the specific account is null.如果来自特定帐户的帐户是 null,我希望有一种动态的方式从所有帐户 object(“*”)中获取工作。

Something like below but whit out repeating the same code for all job types and also a solution that should work when new job types are introduced.类似下面的内容,但没有为所有工作类型重复相同的代码,并且在引入新工作类型时应该可以工作的解决方案。

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

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

I was thinking to use some reflection, but I am not sure how to do it.我正在考虑使用一些反射,但我不知道该怎么做。

You don't need to use reflection.你不需要使用反射。 You can already determine whether to get the specific jobs for an account or the generic ones, you could then use a Func to get the job you want:您已经可以确定是获取帐户的特定作业还是通用作业,然后可以使用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);

I found a way to do it, not sure if there is a better way:我找到了一种方法,不知道是否有更好的方法:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM