1 // -----------------------------------------------------------------------
\r
2 // Copyright (c) Microsoft Corporation. All rights reserved.
\r
3 // -----------------------------------------------------------------------
\r
5 using System.Diagnostics.CodeAnalysis;
\r
6 using System.Globalization;
\r
8 using System.Reflection;
\r
9 using System.Threading;
\r
10 using Microsoft.Internal;
\r
12 namespace System.ComponentModel.Composition.ReflectionModel
\r
14 public struct LazyMemberInfo
\r
16 private readonly MemberTypes _memberType;
\r
17 private MemberInfo[] _accessors;
\r
18 private readonly Func<MemberInfo[]> _accessorsCreator;
\r
20 public LazyMemberInfo(MemberInfo member)
\r
22 Requires.NotNull(member, "member");
\r
23 EnsureSupportedMemberType(member.MemberType, "member");
\r
25 this._accessorsCreator = null;
\r
26 this._memberType = member.MemberType;
\r
28 switch(this._memberType)
\r
30 case MemberTypes.Property:
\r
31 PropertyInfo property = (PropertyInfo)member;
\r
32 Assumes.NotNull(property);
\r
33 this._accessors = new MemberInfo[] { property.GetGetMethod(true), property.GetSetMethod(true) };
\r
35 case MemberTypes.Event:
\r
36 EventInfo event_ = (EventInfo)member;
\r
37 this._accessors = new MemberInfo[] { event_.GetRaiseMethod(true), event_.GetAddMethod(true), event_.GetRemoveMethod(true) };
\r
40 this._accessors = new MemberInfo[] { member };
\r
45 public LazyMemberInfo(MemberTypes memberType, params MemberInfo[] accessors)
\r
47 EnsureSupportedMemberType(memberType, "memberType");
\r
48 Requires.NotNull(accessors, "accessors");
\r
50 string errorMessage;
\r
51 if (!LazyMemberInfo.AreAccessorsValid(memberType, accessors, out errorMessage))
\r
53 throw new ArgumentException(errorMessage, "accessors");
\r
56 this._memberType = memberType;
\r
57 this._accessors = accessors;
\r
58 this._accessorsCreator = null;
\r
61 public LazyMemberInfo(MemberTypes memberType, Func<MemberInfo[]> accessorsCreator)
\r
63 EnsureSupportedMemberType(memberType, "memberType");
\r
64 Requires.NotNull(accessorsCreator, "accessorsCreator");
\r
66 this._memberType = memberType;
\r
67 this._accessors = null;
\r
68 this._accessorsCreator = accessorsCreator;
\r
71 public MemberTypes MemberType
\r
73 get { return this._memberType; }
\r
76 public MemberInfo[] GetAccessors()
\r
78 if ((this._accessors == null) && (this._accessorsCreator != null))
\r
80 MemberInfo[] accessors = this._accessorsCreator.Invoke();
\r
82 string errorMessage;
\r
83 if (!LazyMemberInfo.AreAccessorsValid(this.MemberType, accessors, out errorMessage))
\r
85 throw new InvalidOperationException(errorMessage);
\r
88 this._accessors = accessors;
\r
91 return this._accessors;
\r
94 public override int GetHashCode()
\r
96 if (this._accessorsCreator != null)
\r
98 return this.MemberType.GetHashCode() ^ this._accessorsCreator.GetHashCode();
\r
102 Assumes.NotNull(this._accessors);
\r
103 Assumes.NotNull(this._accessors[0]);
\r
104 return this.MemberType.GetHashCode() ^ this._accessors[0].GetHashCode();
\r
108 public override bool Equals(object obj)
\r
110 LazyMemberInfo that = (LazyMemberInfo)obj;
\r
112 // Difefrent member types mean different members
\r
113 if (this._memberType != that._memberType)
\r
118 // if any of the lazy memebers create accessors in a delay-loaded fashion, we simply compare the creators
\r
119 if ((this._accessorsCreator != null) || (that._accessorsCreator != null))
\r
121 return object.Equals(this._accessorsCreator, that._accessorsCreator);
\r
124 // we are dealing with explicitly passed accessors in both cases
\r
125 Assumes.NotNull(this._accessors);
\r
126 Assumes.NotNull(that._accessors);
\r
127 return this._accessors.SequenceEqual(that._accessors);
\r
130 public static bool operator ==(LazyMemberInfo left, LazyMemberInfo right)
\r
132 return left.Equals(right);
\r
135 public static bool operator !=(LazyMemberInfo left, LazyMemberInfo right)
\r
137 return !left.Equals(right);
\r
140 private static void EnsureSupportedMemberType(MemberTypes memberType, string argument)
\r
142 MemberTypes supportedTypes = MemberTypes.TypeInfo | MemberTypes.NestedType | MemberTypes.Constructor | MemberTypes.Field | MemberTypes.Method | MemberTypes.Property | MemberTypes.Event;
\r
143 Requires.IsInMembertypeSet(memberType, argument, supportedTypes);
\r
146 private static bool AreAccessorsValid(MemberTypes memberType, MemberInfo[] accessors, out string errorMessage)
\r
148 errorMessage = string.Empty;
\r
149 if (accessors == null)
\r
151 errorMessage = Strings.LazyMemberInfo_AccessorsNull;
\r
155 if (accessors.All(accessor => accessor == null))
\r
157 errorMessage = Strings.LazyMemberInfo_NoAccessors;
\r
161 switch (memberType)
\r
163 case MemberTypes.Property:
\r
164 if (accessors.Length != 2)
\r
166 errorMessage = Strings.LazyMemberInfo_InvalidPropertyAccessors_Cardinality;
\r
170 if (accessors.Where(accessor => (accessor != null) && (accessor.MemberType != MemberTypes.Method)).Any())
\r
172 errorMessage = Strings.LazyMemberinfo_InvalidPropertyAccessors_AccessorType;
\r
178 case MemberTypes.Event:
\r
179 if (accessors.Length != 3)
\r
181 errorMessage = Strings.LazyMemberInfo_InvalidEventAccessors_Cardinality;
\r
185 if (accessors.Where(accessor => (accessor != null) && (accessor.MemberType != MemberTypes.Method)).Any())
\r
187 errorMessage = Strings.LazyMemberinfo_InvalidPropertyAccessors_AccessorType;
\r
195 (accessors.Length != 1) ||
\r
196 ((accessors.Length == 1) && (accessors[0].MemberType != memberType)))
\r
198 errorMessage = string.Format(CultureInfo.CurrentCulture, Strings.LazyMemberInfo_InvalidAccessorOnSimpleMember, memberType);
\r