internal static Assignability IsAssignableTo(ImportDefinitionBinding import, ExportDefinitionBinding export) { Requires.NotNull(import, nameof(import)); Requires.NotNull(export, nameof(export)); var receivingTypeRef = import.ImportingSiteElementTypeRef; var exportingTypeRef = export.ExportedValueTypeRef; if (exportingTypeRef.IsGenericTypeDefinition && receivingTypeRef.IsGenericType) { exportingTypeRef = exportingTypeRef.MakeGenericTypeRef(receivingTypeRef.GenericTypeArguments); } // Quick assignability check to attempt to exit early if assignable, otherwise use the slower methods if (receivingTypeRef.IsAssignableFrom(exportingTypeRef)) { return(Assignability.Definitely); } else if (typeof(Delegate).GetTypeInfo().IsAssignableFrom(exportingTypeRef.ResolvedType) && typeof(Delegate).GetTypeInfo().IsAssignableFrom(receivingTypeRef.ResolvedType)) { // Delegates of varying types may be assigned to each other. // For example Action<object, EventArgs> can be assigned to EventHandler. // The simplest way to test for it is to ask the CLR to do it. // http://stackoverflow.com/questions/23075298/how-to-detect-compatibility-between-delegate-types/23088194#23088194 try { Assumes.NotNull(export.ExportingMember); ((MethodInfo)export.ExportingMember).CreateDelegate(receivingTypeRef.ResolvedType, null); return(Assignability.Definitely); } catch (ArgumentException) { return(Assignability.DefinitelyNot); } catch (TargetParameterCountException) { return(Assignability.DefinitelyNot); } } else { bool valueTypeKnownExactly = export.ExportingMemberRef == null || // When [Export] appears on the type itself, we instantiate that exact type. exportingTypeRef.ResolvedType.GetTypeInfo().IsSealed; if (valueTypeKnownExactly) { // There is no way that an exported value can implement the required types to make it assignable. return(Assignability.DefinitelyNot); } if (receivingTypeRef.ResolvedType.GetTypeInfo().IsInterface || exportingTypeRef.ResolvedType.GetTypeInfo().IsAssignableFrom(receivingTypeRef.ResolvedType)) { // The actual exported value at runtime *may* be a derived type that *is* assignable to the import site. return(Assignability.Maybe); } return(Assignability.DefinitelyNot); } }
private static RuntimeExport CreateRuntimeExport(ExportDefinitionBinding exportDefinitionBinding, Resolver resolver) { Requires.NotNull(exportDefinitionBinding, nameof(exportDefinitionBinding)); Requires.NotNull(resolver, nameof(resolver)); var partDefinitionType = exportDefinitionBinding.PartDefinition.TypeRef.Resolve(); return(CreateRuntimeExport( exportDefinitionBinding.ExportDefinition, partDefinitionType, exportDefinitionBinding.ExportingMemberRef, resolver)); }
private static string GetDiagnosticLocation(ExportDefinitionBinding export) { Requires.NotNull(export, nameof(export)); if (export.ExportingMemberRef != null) { return(string.Format( CultureInfo.CurrentCulture, "{0}.{1}", export.PartDefinition.Type.FullName, export.ExportingMember.Name)); } else { return(export.PartDefinition.Type.FullName); } }
private static string?GetDiagnosticLocation(ExportDefinitionBinding export) { Requires.NotNull(export, nameof(export)); if (export.ExportingMemberRef != null) { return(string.Format( CultureInfo.CurrentCulture, Strings.TypeNameWithAssemblyLocation, export.PartDefinition.Type.FullName, export.ExportingMemberRef.Name, export.PartDefinition.Type.GetTypeInfo().Assembly.FullName)); } else { return(export.PartDefinition.Type.FullName); } }