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;
 | |
|     }
 | |
|   }
 | |
| }
 |