223 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			223 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.ComponentModel;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Windows.Forms;
 | 
						|
using System.Reflection;
 | 
						|
 | 
						|
namespace Csla.Windows
 | 
						|
{
 | 
						|
  /// <summary>
 | 
						|
  /// Windows Forms extender control that automatically
 | 
						|
  /// enables and disables detail form controls based
 | 
						|
  /// on the authorization settings from a CSLA .NET 
 | 
						|
  /// business object.
 | 
						|
  /// </summary>
 | 
						|
  [DesignerCategory("")]
 | 
						|
  [ProvideProperty("ApplyAuthorization", typeof(Control))]
 | 
						|
  public class ReadWriteAuthorization : Component, IExtenderProvider
 | 
						|
  {
 | 
						|
 | 
						|
    private Dictionary<Control, bool> _sources = 
 | 
						|
      new Dictionary<Control, bool>();
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Creates an instance of the object.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="container">The container of the control.</param>
 | 
						|
    public ReadWriteAuthorization(IContainer container)
 | 
						|
    { container.Add(this); }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Gets a value indicating whether the extender control
 | 
						|
    /// can extend the specified control.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="extendee">The control to be extended.</param>
 | 
						|
    /// <remarks>
 | 
						|
    /// Any control implementing either a ReadOnly property or
 | 
						|
    /// Enabled property can be extended.
 | 
						|
    /// </remarks>
 | 
						|
    public bool CanExtend(object extendee)
 | 
						|
    {
 | 
						|
      if (IsPropertyImplemented(extendee, "ReadOnly") 
 | 
						|
        || IsPropertyImplemented(extendee, "Enabled"))
 | 
						|
        return true;
 | 
						|
      else
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Gets the custom ApplyAuthorization extender
 | 
						|
    /// property added to extended controls.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="source">Control being extended.</param>
 | 
						|
    public bool GetApplyAuthorization(Control source)
 | 
						|
    {
 | 
						|
      if (_sources.ContainsKey(source))
 | 
						|
        return _sources[source];
 | 
						|
      else
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Sets the custom ApplyAuthorization extender
 | 
						|
    /// property added to extended controls.
 | 
						|
    /// </summary>
 | 
						|
    /// <param name="source">Control being extended.</param>
 | 
						|
    /// <param name="value">New value of property.</param>
 | 
						|
    public void SetApplyAuthorization(Control source, bool value)
 | 
						|
    {
 | 
						|
      if (_sources.ContainsKey(source))
 | 
						|
        _sources[source] = value;
 | 
						|
      else
 | 
						|
        _sources.Add(source, value);
 | 
						|
    }
 | 
						|
 | 
						|
    /// <summary>
 | 
						|
    /// Causes the ReadWriteAuthorization control
 | 
						|
    /// to apply authorization rules from the business
 | 
						|
    /// object to all extended controls on the form.
 | 
						|
    /// </summary>
 | 
						|
    /// <remarks>
 | 
						|
    /// Call this method to refresh the display of detail
 | 
						|
    /// controls on the form any time the authorization
 | 
						|
    /// rules may have changed. Examples include: after
 | 
						|
    /// a user logs in or out, and after an object has
 | 
						|
    /// been updated, inserted, deleted or retrieved
 | 
						|
    /// from the database.
 | 
						|
    /// </remarks>
 | 
						|
    public void ResetControlAuthorization()
 | 
						|
    {
 | 
						|
      foreach (KeyValuePair<Control, bool> item in _sources)
 | 
						|
      {
 | 
						|
        if (item.Value)
 | 
						|
        {
 | 
						|
          // apply authorization rules
 | 
						|
          ApplyAuthorizationRules(item.Key);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    private void ApplyAuthorizationRules(Control control)
 | 
						|
    {
 | 
						|
      foreach (Binding binding in control.DataBindings)
 | 
						|
      {
 | 
						|
        // get the BindingSource if appropriate
 | 
						|
        if (binding.DataSource is BindingSource)
 | 
						|
        {
 | 
						|
          BindingSource bs =
 | 
						|
            (BindingSource)binding.DataSource;
 | 
						|
          // get the BusinessObject if appropriate
 | 
						|
          Csla.Security.IAuthorizeReadWrite ds = 
 | 
						|
            bs.Current as Csla.Security.IAuthorizeReadWrite;
 | 
						|
          if (ds != null)
 | 
						|
          {
 | 
						|
            // get the object property name
 | 
						|
            string propertyName =
 | 
						|
              binding.BindingMemberInfo.BindingField;
 | 
						|
 | 
						|
            ApplyReadRules(
 | 
						|
              control, binding,
 | 
						|
              ds.CanReadProperty(propertyName));
 | 
						|
            ApplyWriteRules(
 | 
						|
              control, binding,
 | 
						|
              ds.CanWriteProperty(propertyName));
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    private void ApplyReadRules(
 | 
						|
      Control ctl, Binding binding, 
 | 
						|
      bool canRead)
 | 
						|
    {
 | 
						|
      // enable/disable reading of the value
 | 
						|
      if (canRead)
 | 
						|
      {
 | 
						|
        bool couldRead = ctl.Enabled;
 | 
						|
        ctl.Enabled = true;
 | 
						|
        binding.Format -= 
 | 
						|
          new ConvertEventHandler(ReturnEmpty);
 | 
						|
        if (!couldRead) binding.ReadValue();
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        ctl.Enabled = false;
 | 
						|
        binding.Format += 
 | 
						|
          new ConvertEventHandler(ReturnEmpty);
 | 
						|
 | 
						|
        // clear the value displayed by the control
 | 
						|
        PropertyInfo propertyInfo = 
 | 
						|
          ctl.GetType().GetProperty(binding.PropertyName,
 | 
						|
          BindingFlags.FlattenHierarchy |
 | 
						|
          BindingFlags.Instance |
 | 
						|
          BindingFlags.Public);
 | 
						|
        if (propertyInfo != null)
 | 
						|
        {
 | 
						|
          propertyInfo.SetValue(ctl, 
 | 
						|
            GetEmptyValue(
 | 
						|
              Utilities.GetPropertyType(
 | 
						|
                propertyInfo.PropertyType)), 
 | 
						|
              new object[] { });
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    private void ApplyWriteRules(
 | 
						|
      Control ctl, Binding binding, 
 | 
						|
      bool canWrite)
 | 
						|
    {
 | 
						|
      if (ctl is Label) return;
 | 
						|
 | 
						|
      // enable/disable writing of the value
 | 
						|
      PropertyInfo propertyInfo =
 | 
						|
        ctl.GetType().GetProperty("ReadOnly",
 | 
						|
        BindingFlags.FlattenHierarchy |
 | 
						|
        BindingFlags.Instance |
 | 
						|
        BindingFlags.Public);
 | 
						|
      if (propertyInfo != null)
 | 
						|
      {
 | 
						|
        bool couldWrite = 
 | 
						|
          (!(bool)propertyInfo.GetValue(
 | 
						|
          ctl, new object[] { }));
 | 
						|
        propertyInfo.SetValue(
 | 
						|
          ctl, !canWrite, new object[] { });
 | 
						|
        if ((!couldWrite) && (canWrite))
 | 
						|
          binding.ReadValue();
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        bool couldWrite = ctl.Enabled;
 | 
						|
        ctl.Enabled = canWrite;
 | 
						|
        if ((!couldWrite) && (canWrite))
 | 
						|
          binding.ReadValue();
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    private void ReturnEmpty(
 | 
						|
      object sender, ConvertEventArgs e)
 | 
						|
    {
 | 
						|
      e.Value = GetEmptyValue(e.DesiredType);
 | 
						|
    }
 | 
						|
 | 
						|
    private object GetEmptyValue(Type desiredType)
 | 
						|
    {
 | 
						|
      object result = null;
 | 
						|
      if (desiredType.IsValueType)
 | 
						|
        result = Activator.CreateInstance(desiredType);
 | 
						|
      return result;
 | 
						|
    }
 | 
						|
 | 
						|
    private static bool IsPropertyImplemented(
 | 
						|
      object obj, string propertyName)
 | 
						|
    {
 | 
						|
      if (obj.GetType().GetProperty(propertyName,
 | 
						|
        BindingFlags.FlattenHierarchy |
 | 
						|
        BindingFlags.Instance |
 | 
						|
        BindingFlags.Public) != null)
 | 
						|
        return true;
 | 
						|
      else
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |