https://pulumi.com logo
#dotnet
Title
# dotnet
m

mysterious-australia-14256

05/17/2020, 8:33 PM
I'm hoping someone with more knowledge on reflection can help me here... I'm trying use reflection in order to loop through all of the properties in a Pulumi.Azure.AppService.Inputs.AppServiceArgs object and copy them to a Pulumi.Azure.AppService.Inputs.SlotArgs object. I can manage the first level of boolean and string values like this (source is the AppServiceArgs object and target is the SlotArgs object)
Copy code
private static void CopyArgs(Object source, Object target)
{
    foreach (var sourceProp in source.GetType().GetProperties())
    {
        var targetProp = target.GetType().GetProperty(sourceProp.Name);

        switch (sourceProp.PropertyType.ToString())
        {
            case "Pulumi.Input`1[System.Boolean]": 
            case "Pulumi.Input`1[System.String]": 
                if (targetProp != null) targetProp.SetValue(child, sourceProp.GetValue(parent), null);
                break;
            default:
                break;
        }
    }
}
The problem comes when handling more complex types such as the SiteConfig which is of Type Pulumi.Azure.AppService.Inputs.AppServiceSiteConfigArgs in the parent object That is wrapped as a Pulumi.Input which means I need to call Apply to get at the contents I can manage that adding another case like this that determines the Types of the new, next level objects (e,g, the AppServiceSiteConfigArgs and SlotSiteConfigArgs in the case of SiteConfig) and then recursively calls the CopyArgs method with them as arguments...
Copy code
case "Pulumi.Input`1[Pulumi.Azure.AppService.Inputs.AppServiceSiteConfigArgs]":
                var newSource = (Input<AppServiceSiteConfigArgs>)sourceProp.GetValue(source)!;
                if (newSource != null)
                {
                    newSource.Apply(x => 
                    {
                        var newTargetProp = target.GetType().GetProperty(sourceProp.Name);
                        if (newTargetProp != null) 
                        {
                            var newTarget = (Input<SlotSiteConfigArgs>)newTargetProp.GetValue(target)!;
                            if (newTarget != null)
                            {
                                newTarget.Apply(y => 
                                {
                                    CopyArgs(x, y);
                                    return y;
                                });
                            }
                        }
                        return x;
                    });
                }
                break;
The problem with the above is that I have hard coded in casts for (Input<AppServiceSiteConfigArgs>) and (Input<SlotSiteConfigArgs>) which means I would need a new case for each potential type. What I'd really like to do is to be able to determine the types by reflection (so I can create newSource and newTarget in the above without the fixed casts) and call the appropriate Apply methods, presumably using an Invoke command. Unfortunately I haven't been able to work out how to do that and successfully. It seems quite complicated with the mix of generics and extension methods :( If anyone has any tips they would be greatly appreciated! Thanks Alan
t

tall-librarian-49374

05/17/2020, 9:54 PM
What is the original goal that made you use reflection in the first place?
n

narrow-cat-84237

05/18/2020, 6:45 AM
There are a lot of settings in AppServiceArgs and the bulk of these are replicated in SlotArgs. I only want to specify them once (in the AppServiceArgs) and then iteratively copy them to the multiple slots I create. This avoids having to remember to make changes in multiple places (eg if I decide to set a new parameter)