/// <summary> /// Returns a value indicating whether a method named <paramref name="methodName"/> /// exposed by the <see cref="Type"/> specified by <paramref name="typeName"/> /// from the reference project is also visible to the dependent project. /// </summary> /// <param name="typeName">The full name of the <see cref="Type"/> from the reference project.</param> /// <param name="methodName">The name of the method.</param> /// <param name="parameterTypeNames">The full type names of the method parameters, in the order they must be declared.</param> /// <returns>The <see cref="CodeMemberShareKind"/> representing whether it is shared and in what way.</returns> public CodeMemberShareKind GetMethodShareKind(string typeName, string methodName, IEnumerable <string> parameterTypeNames) { CodeMemberKey key = CodeMemberKey.CreateMethodKey(typeName, methodName, parameterTypeNames == null ? null : parameterTypeNames.ToArray()); SharedCodeDescription description = this.GetSharedCodeDescription(key); return(description.ShareKind); }
/// <summary> /// Returns a value indicating whether the a property named <paramref name="propertyName"/> /// exposed by the <see cref="Type"/> specified by <paramref name="typeName"/> /// from the reference project is also visible to the dependent project. /// </summary> /// <param name="typeName">The full name of the <see cref="Type"/> from the reference project.</param> /// <param name="propertyName">The name of the property.</param> /// <returns>The <see cref="CodeMemberShareKind"/> representing whether it is shared and in what way.</returns> public CodeMemberShareKind GetPropertyShareKind(string typeName, string propertyName) { CodeMemberKey key = CodeMemberKey.CreatePropertyKey(typeName, propertyName); SharedCodeDescription description = this.GetSharedCodeDescription(key); return(description.ShareKind); }
/// <summary> /// Returns a value indicating whether the <see cref="Type"/>specified by <paramref name="typeName"/> /// from the reference project is also visible to the dependent project. /// </summary> /// <param name="typeName">The full name of the <see cref="Type"/>from the reference project.</param> /// <returns>The <see cref="CodeMemberShareKind"/> representing whether it is shared and in what way.</returns> public CodeMemberShareKind GetTypeShareKind(string typeName) { CodeMemberKey key = CodeMemberKey.CreateTypeKey(typeName); SharedCodeDescription description = this.GetSharedCodeDescription(key); return(description.ShareKind); }
/// <summary> /// Returns the <see cref="MethodBase"/> of the method or constructor from the /// set of shared assemblies, if it exists. /// </summary> /// <param name="typeName">The fully qualified type name declaring the method.</param> /// <param name="methodName">The name of the method</param> /// <param name="parameterTypeNames">The fully qualified type names of the method parameters.</param> /// <returns>The <see cref="MethodBase"/> if it exists in the shared assemblies, otherwise <c>null</c></returns> internal MethodBase GetSharedMethod(string typeName, string methodName, IEnumerable <string> parameterTypeNames) { Debug.Assert(!string.IsNullOrEmpty(typeName), "typeName cannot be null"); Debug.Assert(!string.IsNullOrEmpty(methodName), "methodName cannot be null"); MethodBase sharedMethod = null; Type sharedType = this.GetSharedType(typeName); if (sharedType != null) { CodeMemberKey key = CodeMemberKey.CreateMethodKey(typeName, methodName, parameterTypeNames == null ? new string[0] : parameterTypeNames.ToArray()); sharedMethod = this.FindSharedMethodOrConstructor(sharedType, key); } return(sharedMethod); }
/// <summary> /// Gets the <see cref="SharedCodeDescription"/> for the code member described by <paramref name="key"/>. /// </summary> /// <param name="key">Describes the code member.</param> /// <returns>The <see cref="SharedCodeDescription"/> or <c>null</c>.</returns> internal SharedCodeDescription GetSharedCodeDescription(CodeMemberKey key) { return(this._cachedDescriptions.GetOrAdd(key, k => { string sharedAssemblyLocation = this.SharedAssemblies.GetSharedAssemblyPath(key); if (sharedAssemblyLocation != null) { return new SharedCodeDescription(CodeMemberShareKind.SharedByReference, new[] { this._filenameMap.AddOrGet(sharedAssemblyLocation) }); } int[] fileIds = this.SharedSourceFiles.GetSharedFileIds(key); if (fileIds != null && fileIds.Length != 0) { return new SharedCodeDescription(CodeMemberShareKind.SharedBySource, fileIds); } return new SharedCodeDescription(CodeMemberShareKind.NotShared, null); })); }
/// <summary> /// Returns the location of the shared assembly containing the /// code member described by <paramref name="key"/>. /// </summary> /// <param name="key">The description of the code element.</param> /// <returns>The location of the assembly that contains it or <c>null</c> if it is not in a shared assembly.</returns> internal string GetSharedAssemblyPath(CodeMemberKey key) { Debug.Assert(key != null, "key cannot be null"); string location = null; Type type = this.GetSharedType(key.TypeName); if (type != null) { switch (key.KeyKind) { case CodeMemberKey.CodeMemberKeyKind.TypeKey: location = type.Assembly.Location; break; case CodeMemberKey.CodeMemberKeyKind.PropertyKey: PropertyInfo propertyInfo = type.GetProperty(key.MemberName); if (propertyInfo != null) { location = propertyInfo.DeclaringType.Assembly.Location; } break; case CodeMemberKey.CodeMemberKeyKind.MethodKey: Type[] parameterTypes = this.GetSharedTypes(key.ParameterTypeNames); if (parameterTypes != null) { MethodBase methodBase = this.FindSharedMethodOrConstructor(type, key); if (methodBase != null) { location = methodBase.DeclaringType.Assembly.Location; } } break; default: Debug.Fail("unsupported key kind"); break; } } return(location); }
/// <summary> /// Locates the <see cref="MethodBase"/> in the set of shared assemblies that /// corresponds to the method described by <paramref name="key"/>. /// </summary> /// <param name="sharedType">The <see cref="Type"/> we have already located in our set of shared assemblies.</param> /// <param name="key">The key describing the method to find.</param> /// <returns>The matching <see cref="MethodBase"/> or <c>null</c> if no match is found.</returns> private MethodBase FindSharedMethodOrConstructor(Type sharedType, CodeMemberKey key) { Type[] parameterTypes = this.GetSharedTypes(key.ParameterTypeNames); if (parameterTypes == null) { return(null); } bool isConstructor = key.IsConstructor; IEnumerable <MethodBase> methods = isConstructor ? sharedType.GetConstructors().Cast <MethodBase>() : sharedType.GetMethods().Cast <MethodBase>(); foreach (MethodBase method in methods) { if (!isConstructor && !string.Equals(method.Name, key.MemberName, StringComparison.OrdinalIgnoreCase)) { continue; } ParameterInfo[] parameterInfos = method.GetParameters(); if (parameterInfos.Length != parameterTypes.Length) { continue; } int matchedParameters = 0; for (int i = 0; i < parameterInfos.Length; ++i) { if (string.Equals(parameterInfos[i].ParameterType.FullName, parameterTypes[i].FullName, StringComparison.OrdinalIgnoreCase)) { ++matchedParameters; } else { break; } } if (matchedParameters == parameterInfos.Length) { return(method); } } return(null); }
/// <summary> /// Override to provide property equality checks using value-based comparison. /// </summary> /// <param name="obj">The object to compare against the current instance.</param> /// <returns><c>true</c> if the objects are equal.</returns> public override bool Equals(object obj) { CodeMemberKey other = obj as CodeMemberKey; if (Object.ReferenceEquals(other, null)) { return(false); } if (Object.ReferenceEquals(this, other)) { return(true); } if ((this.KeyKind != other.KeyKind) || !string.Equals(this.TypeName, other.TypeName, StringComparison.Ordinal) || !string.Equals(this.MemberName, other.MemberName, StringComparison.Ordinal)) { return(false); } int parameterCount = this.ParameterTypeNames == null ? 0 : this.ParameterTypeNames.Length; int otherParameterCount = other.ParameterTypeNames == null ? 0 : other.ParameterTypeNames.Length; if (parameterCount != otherParameterCount) { return(false); } for (int i = 0; i < parameterCount; ++i) { if (!string.Equals(this.ParameterTypeNames[i], other.ParameterTypeNames[i], StringComparison.Ordinal)) { return(false); } } return(true); }
/// <summary> /// Creates a new instance of the <see cref="CodeMemberKey"/> class that describes /// a property. /// </summary> /// <param name="propertyInfo">The <see cref="PropertyInfo"/> of that property.</param> /// <returns>A new instance which describes that property.</returns> public static CodeMemberKey CreatePropertyKey(PropertyInfo propertyInfo) { Debug.Assert(propertyInfo != null, "propertyInfo cannot be null"); return(CodeMemberKey.CreatePropertyKey(propertyInfo.DeclaringType.AssemblyQualifiedName, propertyInfo.Name)); }
/// <summary> /// Creates a new instance of the <see cref="CodeMemberKey"/> class /// to describe the a <see cref="Type"/> from the given <paramref name="type"/>. /// </summary> /// <param name="type">The <see cref="Type"/> from which to construct the key.</param> /// <returns>A new instance which describes that type.</returns> public static CodeMemberKey CreateTypeKey(Type type) { Debug.Assert(type != null, "type cannot be null"); return(CodeMemberKey.CreateTypeKey(type.AssemblyQualifiedName)); }
/// <summary> /// Creates a new instance of the <see cref="CodeMemberKey"/> class that describes /// a method or a constructor. /// </summary> /// <param name="methodBase">The <see cref="MethodBase"/> of the method or constructor.</param> /// <returns>A new instance that describes that method.</returns> public static CodeMemberKey CreateMethodKey(MethodBase methodBase) { Debug.Assert(methodBase != null, "methodBase cannot be null"); string[] parameterTypes = methodBase.GetParameters().Select <ParameterInfo, string>(p => p.ParameterType.AssemblyQualifiedName).ToArray(); return(CodeMemberKey.CreateMethodKey(methodBase.DeclaringType.AssemblyQualifiedName, methodBase.Name, parameterTypes)); }
/// <summary> /// Gets the collection of internal ID's of the files that collectively /// define the code member described by <paramref name="key"/>. /// </summary> /// <param name="key">The key describing the code member.</param> /// <returns>The collection of internal ID's, or <c>null</c> if no shared files exist for this code element.</returns> internal int[] GetSharedFileIds(CodeMemberKey key) { Debug.Assert(key != null, "key cannot be null"); // Early exit if no shared files were specified if (!this._anySharedFiles) { return(null); } Type type = key.Type; // If we don't have the type in this AppDomain, then we don't consider it shared. // For the sake of performance, System types are never considered // shared from the perspective of source files. This optimization // skips attempts to open PDB's or reflect into system types. // We don't even add an entry in the cache for these. if (type == null || type.Assembly.IsSystemAssembly()) { return(null); } int[] fileIds = null; switch (key.KeyKind) { case CodeMemberKey.CodeMemberKeyKind.TypeKey: IEnumerable <string> files = this.SourceFileLocationService.GetFilesForType(type); if (files != null && files.Any()) { IEnumerable <int> filesAsIds = files.Select <string, int>(s => this.FileNameToSharedID(s)).Distinct(); int[] sharedFileIds = filesAsIds.Where(i => i != SharedSourceFiles.NotShared).ToArray(); fileIds = sharedFileIds.Length == 0 ? null : sharedFileIds; } break; case CodeMemberKey.CodeMemberKeyKind.PropertyKey: PropertyInfo propertyInfo = key.PropertyInfo; if (propertyInfo == null) { return(null); } string propertyFile = this.SourceFileLocationService.GetFileForMember(propertyInfo); int sharedPropertyFileId = this.FileNameToSharedID(propertyFile); if (sharedPropertyFileId != SharedSourceFiles.NotShared) { fileIds = new int[] { sharedPropertyFileId }; } break; case CodeMemberKey.CodeMemberKeyKind.MethodKey: MethodBase methodBase = key.MethodBase; if (methodBase == null) { return(null); } string methodFile = this.SourceFileLocationService.GetFileForMember(methodBase); int sharedMethodFileId = this.FileNameToSharedID(methodFile); if (sharedMethodFileId != SharedSourceFiles.NotShared) { fileIds = new int[] { sharedMethodFileId }; } break; default: Debug.Fail("unsupported key kind"); break; } return(fileIds); }