Home > Back-end >  How to reference property of another object if the current object's property is null
How to reference property of another object if the current object's property is null

Time:12-30

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

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.

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.

CodePudding user response:

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:

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

CodePudding user response:

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