#region Copyright 2009-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Reflection;
namespace CSharpTest.Net.Reflection
{
///
/// Allows reflection upon a property or field by name.
///
public class PropertyType : ICustomAttributeProvider
{
private readonly Type _type;
private readonly MemberInfo _member;
///
/// Constructs the PropertyType info from a source type and an instance property or field name
///
/// Any System.Type object to find the property or field on
/// The name of the property or field to find
public PropertyType(Type type, string name)
{
_type = Check.NotNull(type);
Check.NotEmpty(name);
BindingFlags baseFlags = BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy;
//see if we can find a property by this name
System.Type temp = _type;
while (temp != typeof(Object) && _member == null)
{
_member = temp.GetProperty(name, baseFlags | BindingFlags.GetProperty | BindingFlags.SetProperty);
if (_member == null)
_member = temp.GetField(name, baseFlags | BindingFlags.GetField | BindingFlags.SetField);
temp = temp.BaseType;
}
if (_member == null)
throw new System.MissingMemberException(_type.FullName, name);
}
///
/// Walks a heirarchy of properties from the given type down. You can specify in any of the
/// following ways: "ClientRectangle.X", "ClientRectangle/X"
///
///
///
/// //dotted notation:
/// PropertyType pt = PropertyType.TraverseProperties(typeof(Form), "ClientRectangle.X");
/// //path notation:
/// PropertyType pt = PropertyType.TraverseProperties(typeof(Form), "ClientRectangle/X");
/// //individual names:
/// PropertyType pt = PropertyType.TraverseProperties(typeof(Form), "ClientRectangle", "X");
///
///
/// Any System.Type object to traverse from
/// The name of the properties or fields usually '.' delimited
public static PropertyType TraverseProperties(Type fromType, params string[] propertyNames)
{
PropertyType prop = null;
Type t = fromType;
foreach (string propnames in Check.NotEmpty(propertyNames))
{
foreach (string name in Check.NotEmpty(propnames).Split('.', '/', '\\'))
{
prop = new PropertyType(t, Check.NotEmpty(name));
t = prop.Type;
}
}
return Check.NotNull(prop);
}
///
/// Returns the name of the property/field
///
public string Name { get { return _member.Name; } }
///
/// Returns the type of the property/field
///
public Type Type
{
get
{
if (_member is PropertyInfo)
return ((PropertyInfo)_member).PropertyType;
else //if (_member is FieldInfo)
return ((FieldInfo)_member).FieldType;
}
}
///
/// Returns the value of the property for the specified instance
///
public object GetValue(object instance)
{
if (_member is PropertyInfo)
return ((PropertyInfo)_member).GetValue(instance, null);
else //if (_member is FieldInfo)
return ((FieldInfo)_member).GetValue(instance);
}
///
/// Sets the specified value for the instance supplied
///
public void SetValue(object instance, object value)
{
if (_member is PropertyInfo)
((PropertyInfo)_member).SetValue(instance, value, null);
else //if (_member is FieldInfo)
((FieldInfo)_member).SetValue(instance, value);
}
///
/// Returns an array of all of the custom attributes defined on this member, excluding named
/// attributes, or an empty array if there are no custom attributes.
///
public object[] GetCustomAttributes(bool inherit)
{
return _member.GetCustomAttributes(inherit);
}
///
/// Returns an array of custom attributes defined on this member, identified by type, or an
/// empty array if there are no custom attributes of that type.
///
public object[] GetCustomAttributes(Type attributeType, bool inherit)
{
return _member.GetCustomAttributes(attributeType, inherit);
}
///
/// Indicates whether one or more instance of is defined
/// on this member.
///
public bool IsDefined(Type attributeType, bool inherit)
{
return _member.IsDefined(attributeType, inherit);
}
}
}