What is the best approach for implementing a per-property authorization rule that depends on the result of an async, lazy-loaded property?
Here's my suggestion:
[Serializable]
public sealed class Parent : BusinessBase<Parent>
{
public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(c => c.Name);
public string Name
{
get { return GetProperty(NameProperty); }
set { SetProperty(NameProperty, value); }
}
public static readonly PropertyInfo<ChildrenList> ChildrenProperty = RegisterProperty<ChildrenList>(c => c.Children, RelationshipTypes.Child | RelationshipTypes.LazyLoad);
public ChildrenList Children
{
get
{
if (!FieldManager.FieldExists(ChildrenProperty))
{
if (IsNew)
LoadProperty(ChildrenProperty, ChildrenList.NewList());
else
{
ChildrenList.GetListAsync(Id, (o, e) =>
{
if (e.Error != null)
throw e.Error;
LoadProperty(ChildrenProperty, e.Object);
OnPropertyChanged(ChildrenProperty);
});
return null;
}
}
return GetProperty(ChildrenProperty);
}
}
protected override void AddBusinessRules()
{
base.AddBusinessRules();
BusinessRules.AddRule(new Required(NameProperty));
BusinessRules.AddRule(new MaxLength(NameProperty, 255));
BusinessRules.AddRule(new CanWriteParentNameRule(AuthorizationActions.WriteProperty, NameProperty));
BusinessRules.AddRule(new Dependency(ChildrenProperty, NameProperty));
}
}
public class CanWriteParentNameRule : AuthorizationRule
{
public CanWriteParentNameRule(AuthorizationActions action, IMemberInfo element)
: base(action, element) { }
protected override void Execute(AuthorizationContext context)
{
var parent = context.Target as Parent;
if (parent != null && parent.Children != null)
context.HasPermission = (parent.Children.Count == 0);
else
context.HasPermission = false;
}
}
The binding of the name property causes the authorization rule to be evaluated which in turn triggers the async retrieval by accessing the Children property. The property returns null and we default HasPermission to false until we have the children.
When the Children property eventually returns, it raises OnPropertyChanged which in turn (via the Dependency business rule) causes the name property rules to be re-evaluated including the authorization rule. This time the authorization rule gets the children and sets HasPermission accordingly.
What do you think? Does this seem plausible?
Thanks in advance,