The Labs \ Source Viewer \ SSCLI \ System.ComponentModel.Design.Serialization \ MemberRelationship

  1. //------------------------------------------------------------------------------
  2. // <copyright file="MemberRelationshipService.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.ComponentModel.Design.Serialization
  16. {
  17.     using System.Collections.Generic;
  18.     using System.Diagnostics.CodeAnalysis;
  19.     using System.Security.Permissions;
  20.    
  21.     [HostProtection(SharedState = true)]
  22.     public abstract class MemberRelationshipService
  23.     {
  24.         private Dictionary<RelationshipEntry, RelationshipEntry> _relationships = new Dictionary<RelationshipEntry, RelationshipEntry>();
  25.        
  26.         /// <devdoc>
  27.         /// Returns the the current relationship associated with the source, or MemberRelationship.Empty if
  28.         /// there is no relationship. Also sets a relationship between two objects. Empty
  29.         /// can also be passed as the property value, in which case the relationship will
  30.         /// be cleared.
  31.         /// </devdoc>
  32.         [SuppressMessage("Microsoft.Design", "CA1043:UseIntegralOrStringArgumentForIndexers")]
  33.         public MemberRelationship this[MemberRelationship source]
  34.         {
  35.             get {
  36.                 if (source.Owner == null)
  37.                     throw new ArgumentNullException("Owner");
  38.                 if (source.Member == null)
  39.                     throw new ArgumentNullException("Member");
  40.                
  41.                 return GetRelationship(source);
  42.             }
  43.             set {
  44.                 if (source.Owner == null)
  45.                     throw new ArgumentNullException("Owner");
  46.                 if (source.Member == null)
  47.                     throw new ArgumentNullException("Member");
  48.                
  49.                 SetRelationship(source, value);
  50.             }
  51.         }
  52.        
  53.         /// <devdoc>
  54.         /// Returns the the current relationship associated with the source, or null if
  55.         /// there is no relationship. Also sets a relationship between two objects. Null
  56.         /// can be passed as the property value, in which case the relationship will
  57.         /// be cleared.
  58.         /// </devdoc>
  59.         [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1023:IndexersShouldNotBeMultidimensional")]
  60.         public MemberRelationship this[object sourceOwner, MemberDescriptor sourceMember]
  61.         {
  62.             get {
  63.                 if (sourceOwner == null)
  64.                     throw new ArgumentNullException("sourceOwner");
  65.                 if (sourceMember == null)
  66.                     throw new ArgumentNullException("sourceMember");
  67.                
  68.                 return GetRelationship(new MemberRelationship(sourceOwner, sourceMember));
  69.             }
  70.             set {
  71.                 if (sourceOwner == null)
  72.                     throw new ArgumentNullException("sourceOwner");
  73.                 if (sourceMember == null)
  74.                     throw new ArgumentNullException("sourceMember");
  75.                
  76.                 SetRelationship(new MemberRelationship(sourceOwner, sourceMember), value);
  77.             }
  78.         }
  79.        
  80.         /// <devdoc>
  81.         /// This is the implementation API for returning relationships. The default implementation stores the
  82.         /// relationship in a table. Relationships are stored weakly, so they do not keep an object alive.
  83.         /// </devdoc>
  84.         protected virtual MemberRelationship GetRelationship(MemberRelationship source)
  85.         {
  86.             RelationshipEntry retVal;
  87.            
  88.             if (_relationships != null && _relationships.TryGetValue(new RelationshipEntry(source), out retVal) && retVal.Owner.IsAlive) {
  89.                 return new MemberRelationship(retVal.Owner.Target, retVal.Member);
  90.             }
  91.            
  92.             return MemberRelationship.Empty;
  93.         }
  94.        
  95.         /// <devdoc>
  96.         /// This is the implementation API for returning relationships. The default implementation stores the
  97.         /// relationship in a table. Relationships are stored weakly, so they do not keep an object alive. Empty can be
  98.         /// passed in for relationship to remove the relationship.
  99.         /// </devdoc>
  100.         protected virtual void SetRelationship(MemberRelationship source, MemberRelationship relationship)
  101.         {
  102.            
  103.             if (!relationship.IsEmpty && !SupportsRelationship(source, relationship)) {
  104.                 string sourceName = TypeDescriptor.GetComponentName(source.Owner);
  105.                 string relName = TypeDescriptor.GetComponentName(relationship.Owner);
  106.                 if (sourceName == null) {
  107.                     sourceName = source.Owner.ToString();
  108.                 }
  109.                 if (relName == null) {
  110.                     relName = relationship.Owner.ToString();
  111.                 }
  112.                 throw new ArgumentException(SR.GetString(SR.MemberRelationshipService_RelationshipNotSupported, sourceName, source.Member.Name, relName, relationship.Member.Name));
  113.             }
  114.            
  115.             if (_relationships == null) {
  116.                 _relationships = new Dictionary<RelationshipEntry, RelationshipEntry>();
  117.             }
  118.            
  119.             _relationships[new RelationshipEntry(source)] = new RelationshipEntry(relationship);
  120.         }
  121.        
  122.         /// <devdoc>
  123.         /// Returns true if the provided relatinoship is supported.
  124.         /// </devdoc>
  125.         public abstract bool SupportsRelationship(MemberRelationship source, MemberRelationship relationship);
  126.        
  127.         /// <devdoc>
  128.         /// Used as storage in our relationship table
  129.         /// </devdoc>
  130.         private struct RelationshipEntry
  131.         {
  132.             internal WeakReference Owner;
  133.             internal MemberDescriptor Member;
  134.             private int hashCode;
  135.            
  136.             internal RelationshipEntry(MemberRelationship rel)
  137.             {
  138.                 Owner = new WeakReference(rel.Owner);
  139.                 Member = rel.Member;
  140.                 hashCode = rel.Owner == null ? 0 : rel.Owner.GetHashCode();
  141.             }
  142.            
  143.            
  144.             public override bool Equals(object o)
  145.             {
  146.                 if (o is RelationshipEntry) {
  147.                     RelationshipEntry e = (RelationshipEntry)o;
  148.                     return this == e;
  149.                 }
  150.                
  151.                 return false;
  152.             }
  153.            
  154.             public static bool operator ==(RelationshipEntry re1, RelationshipEntry re2)
  155.             {
  156.                 object owner1 = (re1.Owner.IsAlive ? re1.Owner.Target : null);
  157.                 object owner2 = (re2.Owner.IsAlive ? re2.Owner.Target : null);
  158.                 return owner1 == owner2 && re1.Member.Equals(re2.Member);
  159.             }
  160.            
  161.             public static bool operator !=(RelationshipEntry re1, RelationshipEntry re2)
  162.             {
  163.                 return !(re1 == re2);
  164.             }
  165.            
  166.             public override int GetHashCode()
  167.             {
  168.                 return hashCode;
  169.             }
  170.         }
  171.     }
  172.    
  173.     /// <devdoc>
  174.     /// This class represents a single relationship between an object and a member.
  175.     /// </devdoc>
  176.     public struct MemberRelationship
  177.     {
  178.         private object _owner;
  179.         private MemberDescriptor _member;
  180.        
  181.         public static readonly MemberRelationship Empty = new MemberRelationship();
  182.        
  183.         /// <devdoc>
  184.         /// Creates a new member relationship.
  185.         /// </devdoc>
  186.         public MemberRelationship(object owner, MemberDescriptor member)
  187.         {
  188.             if (owner == null)
  189.                 throw new ArgumentNullException("owner");
  190.             if (member == null)
  191.                 throw new ArgumentNullException("member");
  192.            
  193.             _owner = owner;
  194.             _member = member;
  195.         }
  196.        
  197.         /// <devdoc>
  198.         /// Returns true if this relationship is empty.
  199.         /// </devdoc>
  200.         public bool IsEmpty {
  201.             get { return _owner == null; }
  202.         }
  203.        
  204.         /// <devdoc>
  205.         /// The member in this relationship.
  206.         /// </devdoc>
  207.         public MemberDescriptor Member {
  208.             get { return _member; }
  209.         }
  210.        
  211.         /// <devdoc>
  212.         /// The object owning the member.
  213.         /// </devdoc>
  214.         public object Owner {
  215.             get { return _owner; }
  216.         }
  217.        
  218.         /// <devdoc>
  219.         /// Infrastructure support to make this a first class struct
  220.         /// </devdoc>
  221.         public override bool Equals(object obj)
  222.         {
  223.             if (!(obj is MemberRelationship))
  224.                 return false;
  225.            
  226.             MemberRelationship rel = (MemberRelationship)obj;
  227.             return rel.Owner == Owner && rel.Member == Member;
  228.         }
  229.        
  230.         /// <devdoc>
  231.         /// Infrastructure support to make this a first class struct
  232.         /// </devdoc>
  233.         public override int GetHashCode()
  234.         {
  235.             if (_owner == null)
  236.                 return base.GetHashCode();
  237.             return _owner.GetHashCode() ^ _member.GetHashCode();
  238.         }
  239.         /// <devdoc>
  240.         /// Infrastructure support to make this a first class struct
  241.         /// </devdoc>
  242.         public static bool operator ==(MemberRelationship left, MemberRelationship right)
  243.         {
  244.             return left.Owner == right.Owner && left.Member == right.Member;
  245.         }
  246.        
  247.         /// <devdoc>
  248.         /// Infrastructure support to make this a first class struct
  249.         /// </devdoc>
  250.         public static bool operator !=(MemberRelationship left, MemberRelationship right)
  251.         {
  252.             return !(left == right);
  253.         }
  254.     }
  255. }

Developer Fusion