Find out if a property is declared virtual
Sorry, I am looking up the System.Type
type and the PropertyInfo
type in the documentation but I can't seem to find the thing I need.
How do I tell if a property (or method or any other member) was开发者_运维问答 declared virtual
in its declaring class?
For e.g.
class Cat
{
public string Name { get; set; }
public virtual int Age { get; set; }
}
How do I tell if the Age
property was declared virtual
or not?
You could use the IsVirtual property:
var isVirtual = typeof(Cat).GetProperty("Age").GetGetMethod().IsVirtual;
Technically, properties are not virtual -- their accessors are. Try this:
typeof(Cat).GetProperty("Age").GetAccessors()[0].IsVirtual
If you wanted, you could use an extension method like the following to determine if a property is virtual:
public static bool? IsVirtual(this PropertyInfo self)
{
if (self == null)
throw new ArgumentNullException("self");
bool? found = null;
foreach (MethodInfo method in self.GetAccessors()) {
if (found.HasValue) {
if (found.Value != method.IsVirtual)
return null;
} else {
found = method.IsVirtual;
}
}
return found;
}
If it returns null
, either the property has no accessors (which should never happen) or all of the property accessors do not have the same virtual status -- at least one is and one is not virtual.
IsVirtual alone didn't work for me. It was telling me that all my non-virtual non-nullable properties were virtual. I had to use a combination of IsFinal and IsVirtual
Here's what I ended up with:
PropertyInfo[] nonVirtualProperties = myType.GetProperties().Where(x => x.GetAccessors()[0].IsFinal || !x.GetAccessors()[0].IsVirtual).ToArray();
PropertyInfo[] virtualProperties = myType.GetProperties().Where(x => !x.GetAccessors()[0].IsFinal && x.GetAccessors()[0].IsVirtual).ToArray();
If a class inherits from an interface all of the properties in the interface are marked as virtual. If you want to check if a property is overridable you need to check that IsFinal is false as well
public static bool IsPropertyOverridable(this PropertyInfo propertyInfo)
{
return (propertyInfo.IsGetPropertyVirtual() || propertyInfo.IsSetPropertyOverridable());
}
public static bool IsGetPropertyVirtual(this PropertyInfo propertyInfo)
{
if (false == propertyInfo.CanRead)
{
return false;
}
return propertyInfo.GetGetMethod(nonPublic: true).IsOverridable();
}
public static bool IsSetPropertyOverridable(this PropertyInfo propertyInfo)
{
if (false == propertyInfo.CanWrite)
{
return false;
}
return propertyInfo.GetSetMethod(nonPublic: true).IsOverridable();
}
if you are using an generic class of type T then get its properities using the GetProperties method. In this case, I want to bypass any virtual collections that entity framework generates when assign values from by view class to my entity class. The GetAccessors()[0].IsVirtual method will tell me if the property is virtual.
var propts = typeof(T).GetProperties();
T model = new T();
foreach (var viewFieldProperty in propts)
{
sourceFieldName = viewFieldProperty.Name;
Type fieldTypeSource = viewFieldProperty.PropertyType;
sourceFieldNameType = fieldTypeSource.ToString();
if(viewFieldProperty.GetAccessors()[0].IsVirtual==false) //bypass virtual collections
{
…
val = entityObject.GetType().GetProperty(viewFieldProperty.Name).GetValue(entityObject, null);
if (val != null) { viewFieldProperty.SetValue(model, val); }
}
}
精彩评论