-1

I'm trying to set default property values for certain classes. Because the classes are generated automatically, I don't want to have to set them in the individual classes, so I created an extension method. It works great until I come across nullable properties, such as bool? properties because PropertyInfo.PropertyType will not return bool. In fact, it's unclear to me what to test for when PropertyType comes across a nullable bool.

Here's the outline of my method:

    public static T SetDefaults<T>(this T model) where T : IModelClasses
    {

        //set values
        foreach (PropertyInfo prop in model.GetType().GetProperties())
        {
            if (prop.PropertyType == typeof(string)) prop.SetValue(model, string.Empty, null);

            else if (prop.PropertyType == typeof(bool)) prop.SetValue(model, false, null); //Will not set the property to false if the property is a nullable bool
        
            ...

        }
        return model;
    }

I've looked into ways of getting the underlying type, such as below but the original object is required. Because PorpertyType does not return the actual property, I cannot test it using this method:

    private static Type GetType<T>(T obj)
    {
        return typeof(T);
    }

Is there any way to evaluate the PropertyInfo or ProperType to determine if it is a bool? so that I can set it to false?

E. A. Bagby
  • 824
  • 9
  • 24
  • https://stackoverflow.com/questions/8939939/correct-way-to-check-if-a-type-is-nullable – ClearlyClueless Feb 10 '23 at 21:52
  • 2
    Well a nullable bool is a `bool?`, and `typeof(bool?)` is what `PropertyType` will return. There are interesting caveats with nullable types where you sometimes have to treat them specially to prevent the runtime's automatic conversions from mucking things up, but this particular type test is straightforward (as long as you're OK with directly testing for `bool?`, and not nullables in general). – Jeroen Mostert Feb 10 '23 at 21:54

2 Answers2

1

Updated Answer

I needed similar functionality for one of my projects so I posted the code to GitHub and NuGet for reference. It use dynamic code gen and Roslyn compilation for performance.

If you paste the code below into LINQPad and install the NuGet package Initialize, it should work. If it throw an error about extension methods, just copy the following code from the repo into your project - Initializer.cs, InitializerTemplate.cs, InitializerExtensions.cs

void Main()
{
    //Install-Package Initialize
    //Github code url: https://github.com/adam-dot-cohen/initialize
    
    var test = new Test();
    var test2 = new Test2();

    // INITIALIZER EXAMPLE
    test.Dump("Test Pre Init");

    // 1.Optional If you want to manipuate the default initialization logic.
    Initializer<Test>.Template.Clear();

    Initializer<Test>.Template.Add(typeof(string),
        (obj, propInfo) => "string.Empty");
    Initializer<Test>.Template.Add(typeof(Nullable<>),
        (obj, propInfo) => string.Format("{0}.{1}!.InitValueOrDefault()", obj, propInfo.Name));
    Initializer<Test>.Template.Add(typeof(ValueType),
        (obj, propInfo) => string.Format("{0}.{1}.InitValueOrDefault()", obj, propInfo.Name));
        
    // 2. Call initialize 
    Initializer<Test>.Initialize(test);
    test.Dump("Test Post Init");

}
public class Test2
{
    public int Prop { get; set; }
    public int? PropNullable { get; set; }
    public string PropString { get; set; }
    public int? FieldNullable { get; set; }
}
public class Test
{
    public int Prop { get; set; } 
    public int? PropNullable { get; set; }
    public string PropString { get; set; }
    public int? FieldNullable { get; set; }
}
  • See above. I solved it with `else if (prop.PropertyType == typeof(bool?)) prop.SetValue(pdb, false, null);` – E. A. Bagby Feb 10 '23 at 22:08
  • @EdwardBagby That's fine if you're only expecting bool, but you're going to have to hard code every nullable value type you want to support. And you obviously can't handle structs globally with your approach. –  Feb 10 '23 at 22:13
  • Yes, I need to support every type anyhow because I need to give each type a different default value. Also, I tried `var prop = entity.GetType().GetProperty("P");` and the "P" was not accepted as an argument. – E. A. Bagby Feb 10 '23 at 22:20
  • The sample code in my post is the only solution that I've found that works consistently across OS and framework version. Hope it saves you a few headaches. –  Feb 10 '23 at 23:54
  • @EdwardBagby - sorry - replace the `"P"` with the name of the property...`obj.P` –  Feb 11 '23 at 10:41
0

If you don't want to install anything

public static void Method<T>()
    {
        foreach (var prop in typeof(T).GetProperties())
        {
            if (prop.PropertyType.Name == typeof(Nullable<>).Name) // true if property is Nullable
            {
                // Do something
            }
        }
    }

and then use it like this

Method<Object>();
Marko
  • 1