Reputation: 631
I have a method that iterates through an object's properties and sets the values to their type's default values. Some properties are enums. I have another function that gets the default value of the enum (not 0), but it requires passing the enum type which is not known in the current method.
[DefaultValue(Red)]
public enum Colors
{
Red = 1,
green = 2
}
// In another class
public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
{
Type t = typeof(TEnum);
DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
if (attributes != null && attributes.Length > 0)
{
return (TEnum)attributes[0].Value;
}
else
{
return default(TEnum);
}
}
public static void ClearObject<T>(object obj)
{
obj = (T)obj;
PropertyInfo[] props = obj.GetType().GetProperties();
string propName = "";
try
{
foreach (PropertyInfo pi in props)
{
propName = pi.Name;
Type t = Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType;
if (t.IsEnum)
{
// This works
// var val = EnumFunctions.GetDefaultValue<Colors>();
// The error is here
var val = EnumFunctions.GetDefaultValue<t>();
// ^^^
pi.SetValue(obj, val);
}
// In case of nullable value types int,datetime, etc - set null
else if (Nullable.GetUnderlyingType(pi.PropertyType) != null)
pi.SetValue(obj, null);
else
pi.SetValue(obj, null, null);
}
}
catch (Exception e)
{
string msg = $"Error for {propName}: {e.Message}";
throw new Exception(msg);
}
}
I've tried typeof(t)
, t.GetType()
.
I want the default value for a Colors enum property to be Red. The line causing the error is
var val = EnumFunctions.GetDefaultValue<t>();
Error CS0118 't' is a variable but is used like a type
Upvotes: 0
Views: 1116
Reputation: 631
Per my comment above (thought I could post code). I also wanted to ensure that enums were instantiated to a valid value. Some enums do not have a 0 so the default of numeric types wouldn't work.
public MyClass()
{
// Sets default property values for all but dates
Basefunctions.Clear<InternalExaminer>(this);
// Sets default values by [DefalutValue()] tag.
foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(this))
{
pd.ResetValue(this);
}
// Sets date properties to current date.
Basefunctions.SetDates<MyClass>(this);
}
public static class Basefunctions
{
public static void SetDates<T>(object obj)
{
string propName = "";
try
{
obj = (T)obj;
PropertyInfo[] props = obj.GetType().GetProperties()
.Where(p => p.PropertyType == typeof(DateTime)).ToArray();
if (props != null)
{
DateTime date = DateTime.Now;
foreach (PropertyInfo pi in props)
{
propName = pi.Name;
if (Nullable.GetUnderlyingType(pi.PropertyType) == null)
pi.SetValue(obj, date);
}
}
}
catch (Exception e)
{
throw new Exception($"Could not set date for {propName}.\n{e.Message}");
}
}
public static void Clear<T>(object obj)
{
obj = (T)obj;
PropertyInfo[] props = obj.GetType().GetProperties();
string propName = "";
try
{
foreach (PropertyInfo pi in props)
{
propName = pi.Name;
Type t = Nullable.GetUnderlyingType(pi.PropertyType) ?? pi.PropertyType;
if (Nullable.GetUnderlyingType(pi.PropertyType) != null)
pi.SetValue(obj, null);
else
{
var val = GetDefaultVal(t);
if (t.IsEnum)
{
// In case enum does not have a 0
if (!Enum.IsDefined(t, val))
val = EnumMin(pi.PropertyType);
}
pi.SetValue(obj, val);
}
}
}
catch (Exception e)
{
string msg = $"Error for {propName}: {e.Message}";
throw new Exception(msg);
}
}
private static object GetDefaultVal(Type type)
{
DefaultValueAttribute att = (DefaultValueAttribute)type.GetCustomAttribute(typeof(DefaultValueAttribute));
if (att != null)
return att.Value;
else
return type.IsValueType ? Activator.CreateInstance(type) : null;
}
private static object EnumMin(Type t)
{
Array x = Enum.GetValues(t);
var ret = x.GetValue(0);
return ret;
}
private static object EnumMax(Type t)
{
Array x = Enum.GetValues(t);
var ret = x.GetValue(x.Length - 1);
return ret;
}
}
Upvotes: 0
Reputation: 1664
You can also invoke the method with reflection like this:
typeof(EnumFunctions).GetMethod("GetDefaultValue").MakeGenericMethod(t).Invoke(null, null);
Upvotes: 0
Reputation: 2195
You don't need generics here
public static object GetDefaultValue(Type type)
{
DefaultValueAttribute[] attributes = (DefaultValueAttribute[])type.GetCustomAttributes(typeof(DefaultValueAttribute), false);
if (attributes != null && attributes.Length > 0)
{
return attributes[0].Value;
}
else
{
return null;
}
}
And then you use it like this
var val = EnumFunctions.GetDefaultValue(t);
if(val != null)
pi.SetValue(obj, val);
Source of your confusion:
Generally speaking, generics are not runtime construct, they're compile-time construct, so you can't use them in reflection, because reflection works at run time.
Upvotes: 2