我有一个方法可以迭代对象的属性,并将值设置为其类型的默认值。一些属性是枚举。我有另一个函数,它获取枚举的默认值(不是0),但是它需要传递当前方法未知的枚举类型。
[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);
}
}
我尝试过typeof(t)
,t.GetType()
。
我希望Colors枚举属性的默认值为Red。导致错误的行是
var val = EnumFunctions.GetDefaultValue<t>();
Error CS0118 't' is a variable but is used like a type
答案 0 :(得分:2)
这里不需要泛型
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;
}
}
然后像这样使用它
var val = EnumFunctions.GetDefaultValue(t);
if(val != null)
pi.SetValue(obj, val);
您的困惑之源:
一般而言,泛型不是运行时构造,它们是编译时构造,因此您不能在反射中使用它们,因为反射在运行时起作用。
答案 1 :(得分:0)
您还可以像这样通过反射调用该方法:
typeof(EnumFunctions).GetMethod("GetDefaultValue").MakeGenericMethod(t).Invoke(null, null);
答案 2 :(得分:0)
根据我上面的评论(我想可以发布代码)。我还想确保将枚举实例化为有效值。一些枚举没有0,因此默认的数字类型不起作用。
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;
}
}