Skip to content

Instantly share code, notes, and snippets.

@tncbbthositg
Created August 7, 2009 15:48
Show Gist options
  • Save tncbbthositg/163975 to your computer and use it in GitHub Desktop.
Save tncbbthositg/163975 to your computer and use it in GitHub Desktop.
[Serializable]
[AttributeUsage(AttributeTargets.Property)]
public class PropertyDefault : OnMethodInvocationAspect
{
private enum AccessorType
{
Get,
Set
}
// a place to store the parameters passed to the property
private object[] _parameters;
// gonna need at least an empty parameter collection
public PropertyDefault() : this(new Type[]{})
{ }
// save the parameters
public PropertyDefault(params object[] parameters)
{
_parameters = parameters;
}
// named parameter to support either a direct assignment or
// a backup plan if reflection fails to find a valid constructor
// on your object
public object DefaultValue { get; set; }
public override void OnInvocation(MethodInvocationEventArgs eventArgs)
{
// make sure eventArgs isn't null
if (eventArgs == null) return;
// if the accessor type is set, just go ahead and execute the method
if (GetAccessorType(eventArgs.Delegate.Method) == AccessorType.Set)
{
base.OnInvocation(eventArgs);
return;
}
// if it's the get accessor, get the current value
eventArgs.ReturnValue = eventArgs.Delegate.DynamicInvoke(eventArgs.GetArgumentArray());
// if the current value isn't null, return the value
if (eventArgs.ReturnValue != null) return;
// otherwise, get the default value
eventArgs.ReturnValue = GetDefaultObject(eventArgs.Delegate.Method.ReturnType);
// now that we have the value, we need to make sure
// we store the reference to it so we take our new
// result and assign it to our property
Type target = eventArgs.Delegate.Target.GetType();
PropertyInfo property = target.GetProperty(eventArgs.Delegate.Method.Name.Substring(5));
property.SetValue(eventArgs.Delegate.Target, eventArgs.ReturnValue, null);
}
private object GetDefaultObject(Type type)
{
// if you specified a default value only, then
// you probably want that value back instead of
// the empty constructor
if (_parameters.Length == 0 && DefaultValue != null)
return DefaultValue;
// get the array of types from the parameters you specified
// to try to find a valid constructor
Type[] types = (from p in _parameters
select p.GetType()).ToArray();
// get the constructor with the type array
ConstructorInfo constructor = type.GetConstructor(types);
// if there's not a valid constructor then go with
// the backup plan (i.e., DefaultValue)
if (constructor != null)
return constructor.Invoke(_parameters);
return DefaultValue;
}
private AccessorType GetAccessorType(MethodInfo method)
{
// the tilde is put there by postsharp
// the get_ and set_ are put there by c sharp
if (method.Name.StartsWith("~get_"))
return AccessorType.Get;
else if (method.Name.StartsWith("~set_"))
return AccessorType.Set;
else throw new Exception("Unknown method type for property accessor.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment