OnDemandAttribute
public class OnDemandAttribute : DictionaryBehaviorAttribute, IDictionaryPropertyGetter, IDictionaryBehavior
Support for on-demand value resolution.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
namespace Castle.Components.DictionaryAdapter
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Interface, AllowMultiple = false)]
public class OnDemandAttribute : DictionaryBehaviorAttribute, IDictionaryPropertyGetter, IDictionaryBehavior
{
public Type Type { get; set; }
public object Value { get; set; }
public OnDemandAttribute()
{
}
public OnDemandAttribute(Type type)
{
if ((object)type.GetConstructor(Type.EmptyTypes) == null)
throw new ArgumentException("On-demand values must have a parameterless constructor");
Type = type;
}
public OnDemandAttribute(object value)
{
Value = value;
}
public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue, PropertyDescriptor property, bool ifExists)
{
if (storedValue == null && !ifExists) {
IValueInitializer initializer = null;
if (Value != null)
storedValue = Value;
else {
Type type = Type ?? GetInferredType(dictionaryAdapter, property, out initializer);
if (IsAcceptedType(type)) {
if (type.IsInterface) {
if (!property.IsDynamicProperty && storedValue == null)
storedValue = dictionaryAdapter.Create(property.PropertyType);
} else if (type.IsArray) {
storedValue = Array.CreateInstance(type.GetElementType(), 0);
} else if (storedValue == null) {
object[] parameters = null;
ConstructorInfo constructorInfo = null;
if (property.IsDynamicProperty) {
constructorInfo = (from <>h__TransparentIdentifier0 in (from ctor in type.GetConstructors()
select new {
ctor = ctor,
parms = ctor.GetParameters()
}).Where(<>h__TransparentIdentifier0 => {
if (<>h__TransparentIdentifier0.parms.Length == 1)
return <>h__TransparentIdentifier0.parms[0].ParameterType.IsAssignableFrom(dictionaryAdapter.Meta.Type);
return false;
})
select <>h__TransparentIdentifier0.ctor).FirstOrDefault();
if ((object)constructorInfo != null)
parameters = new IDictionaryAdapter[1] {
dictionaryAdapter
};
}
if ((object)constructorInfo == null)
constructorInfo = type.GetConstructor(Type.EmptyTypes);
if ((object)constructorInfo != null)
storedValue = constructorInfo.Invoke(parameters);
}
}
}
if (storedValue != null) {
using (dictionaryAdapter.SuppressNotificationsBlock()) {
if (storedValue is ISupportInitialize) {
((ISupportInitialize)storedValue).BeginInit();
((ISupportInitialize)storedValue).EndInit();
}
initializer?.Initialize(dictionaryAdapter, storedValue);
property.SetPropertyValue(dictionaryAdapter, property.PropertyName, ref storedValue, dictionaryAdapter.This.Descriptor);
return storedValue;
}
}
}
return storedValue;
}
private static bool IsAcceptedType(Type type)
{
if ((object)type != null && (object)type != typeof(string) && !type.IsPrimitive)
return !type.IsEnum;
return false;
}
private static Type GetInferredType(IDictionaryAdapter dictionaryAdapter, PropertyDescriptor property, out IValueInitializer initializer)
{
Type type = null;
initializer = null;
type = property.PropertyType;
if (!typeof(IEnumerable).IsAssignableFrom(type))
return type;
Type type2 = null;
if (type.IsGenericType) {
Type genericTypeDefinition = type.GetGenericTypeDefinition();
Type genericArg = type.GetGenericArguments()[0];
bool flag = (object)genericTypeDefinition == typeof(System.ComponentModel.BindingList<>);
if (flag || (object)genericTypeDefinition == typeof(List<>)) {
if (dictionaryAdapter.CanEdit)
type2 = (flag ? typeof(EditableBindingList<>) : typeof(EditableList<>));
if (flag && genericArg.IsInterface) {
Func<object> func = () => dictionaryAdapter.Create(genericArg);
initializer = (IValueInitializer)Activator.CreateInstance(typeof(BindingListInitializer<>).MakeGenericType(genericArg), null, func, null, null, null);
}
} else if ((object)genericTypeDefinition == typeof(IList<>) || (object)genericTypeDefinition == typeof(ICollection<>)) {
type2 = (dictionaryAdapter.CanEdit ? typeof(EditableList<>) : typeof(List<>));
}
if ((object)type2 != null)
return type2.MakeGenericType(genericArg);
} else if ((object)type == typeof(IList) || (object)type == typeof(ICollection)) {
if (!dictionaryAdapter.CanEdit)
return typeof(List<object>);
return typeof(EditableList);
}
return type;
}
}
}