public IEnumerable <BindingRule> GetRules() { if (typeof(TTriggerValue).IsPublic) { yield return(new BindingRule { SourceAttribute = typeof(TAttribute), UserType = OpenType.FromType <TTriggerValue>() }); } var cm = (ConverterManager)_converterManager; var types = cm.GetPossibleDestinationTypesFromSource(typeof(TAttribute), typeof(TTriggerValue)); var converters = new Type[] { typeof(TTriggerValue) }; foreach (OpenType type in types) { yield return(new BindingRule { SourceAttribute = typeof(TAttribute), Converters = converters, UserType = type }); } }
public Type GetDefaultType(Attribute attribute, FileAccess access, Type requestedType) { if (access == FileAccess.Write) { // TType is OpenType // TType is CloudMessage, String --> CloudMessage var openType = OpenType.FromType <TType>(); // Check for a direct match. // Check if there's a converter // This is critical when there are no converters, such as if TType is an OpenType foreach (var target in _defaultTypes) { if (openType.IsMatch(target) || _converterManager.HasConverter <TAttribute>(target, typeof(TType))) { return(typeof(IAsyncCollector <>).MakeGenericType(target)); } } return(null); } return(null); }
// Parse the signature to determine which mode this is. // Can also check with converter manager to disambiguate some cases. private CollectorBindingPattern GetMode(ParameterInfo parameter) { Type parameterType = parameter.ParameterType; if (parameterType.IsGenericType) { var genericType = parameterType.GetGenericTypeDefinition(); var elementType = parameterType.GetGenericArguments()[0]; if (genericType == typeof(IAsyncCollector <>)) { return(new CollectorBindingPattern(Mode.IAsyncCollector, elementType)); } else if (genericType == typeof(ICollector <>)) { return(new CollectorBindingPattern(Mode.ICollector, elementType)); } // A different interface. Let another rule try it. return(null); } if (parameter.IsOut) { // How should "out byte[]" bind? // If there's an explicit "byte[] --> TMessage" converter, then that takes precedence. // Else, bind over an array of "byte --> TMessage" converters Type elementType = parameter.ParameterType.GetElementType(); bool hasConverter = this._converterManager.HasConverter <TAttribute>(elementType, typeof(TType)); if (hasConverter) { // out T, where T might be an array return(new CollectorBindingPattern(Mode.OutSingle, elementType)); } if (elementType.IsArray) { // out T[] var messageType = elementType.GetElementType(); return(new CollectorBindingPattern(Mode.OutArray, messageType)); } var validator = OpenType.FromType <TType>(); if (validator.IsMatch(elementType)) { // out T, t is not an array return(new CollectorBindingPattern(Mode.OutSingle, elementType)); } // For out-param ,we don't expect another rule to claim it. So give some rich errors on mismatch. if (typeof(IEnumerable).IsAssignableFrom(elementType)) { throw new InvalidOperationException( "Enumerable types are not supported. Use ICollector<T> or IAsyncCollector<T> instead."); } else if (typeof(object) == elementType) { throw new InvalidOperationException("Object element types are not supported."); } } // No match. Let another rule claim it return(null); }
public static ExactBinding <TMessage> TryBuild( AsyncCollectorBindingProvider <TAttribute, TType> parent, Mode mode, BindingProviderContext context) { var patternMatcher = parent._patternMatcher; var parameter = context.Parameter; var attributeSource = TypeUtility.GetResolvedAttribute <TAttribute>(parameter); FuncAsyncConverter buildFromAttribute; FuncAsyncConverter <TMessage, TType> converter = null; // Prefer the shortest route to creating the user type. // If TType matches the user type directly, then we should be able to directly invoke the builder in a single step. // TAttribute --> TUserType var checker = OpenType.FromType <TType>(); if (checker.IsMatch(typeof(TMessage))) { buildFromAttribute = patternMatcher.TryGetConverterFunc( typeof(TAttribute), typeof(IAsyncCollector <TMessage>)); } else { var converterManager = parent._converterManager; // Try with a converter // Find a builder for : TAttribute --> TType // and then couple with a converter: TType --> TParameterType converter = converterManager.GetConverter <TMessage, TType, TAttribute>(); if (converter == null) { // Preserves legacy behavior. This means we can only have 1 async collector. // However, the collector's builder object can switch. throw NewMissingConversionError(typeof(TMessage)); } buildFromAttribute = patternMatcher.TryGetConverterFunc( typeof(TAttribute), typeof(IAsyncCollector <TType>)); } if (buildFromAttribute == null) { context.BindingErrors.Add(String.Format(Constants.BindingAssemblyConflictMessage, typeof(TType).AssemblyQualifiedName, typeof(TMessage).AssemblyQualifiedName)); return(null); } ParameterDescriptor param; if (parent.BuildParameterDescriptor != null) { param = parent.BuildParameterDescriptor(attributeSource, parameter, parent._nameResolver); } else { param = new ParameterDescriptor { Name = parameter.Name, DisplayHints = new ParameterDisplayHints { Description = "output" } }; } var cloner = new AttributeCloner <TAttribute>(attributeSource, context.BindingDataContract, parent._nameResolver); return(new ExactBinding <TMessage>(cloner, param, mode, buildFromAttribute, converter)); }
public IEnumerable <BindingRule> GetRules() { var accessProp = typeof(TAttribute).GetProperty("access", BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase); foreach (var type in new Type[] { typeof(Stream), }) { yield return(new BindingRule { SourceAttribute = typeof(TAttribute), Filter = FilterNode.NotNull(accessProp), // For stream, Must specify Read vs. Write UserType = OpenType.FromType(type) }); } // Read foreach (var filter in new FilterNode[] { FilterNode.IsEqual(accessProp, FileAccess.Read), FilterNode.Null(accessProp) // Not write }) { foreach (var type in new Type[] { typeof(TextReader), typeof(string), typeof(byte[]) }) { yield return(new BindingRule { Filter = filter, SourceAttribute = typeof(TAttribute), UserType = OpenType.FromType(type) }); } } // Write foreach (var filter in new FilterNode[] { FilterNode.IsEqual(accessProp, FileAccess.Write), FilterNode.Null(accessProp) // Not Read }) { foreach (var type in new Type[] { typeof(TextWriter), typeof(string).MakeByRefType(), typeof(byte[]).MakeByRefType() }) { yield return(new BindingRule { Filter = filter, SourceAttribute = typeof(TAttribute), UserType = OpenType.FromType(type) }); } } }
public static ExactBinding TryBuild( BindToInputBindingProvider <TAttribute, TType> parent, BindingProviderContext context) { var cm = parent._converterManager; var patternMatcher = parent._patternMatcher; var parameter = context.Parameter; var userType = parameter.ParameterType; var attributeSource = TypeUtility.GetResolvedAttribute <TAttribute>(parameter); var cloner = new AttributeCloner <TAttribute>(attributeSource, context.BindingDataContract, parent._configuration, parent._nameResolver); FuncAsyncConverter buildFromAttribute; FuncAsyncConverter converter = null; // Prefer the shortest route to creating the user type. // If TType matches the user type directly, then we should be able to directly invoke the builder in a single step. // TAttribute --> TUserType var checker = OpenType.FromType <TType>(); if (checker.IsMatch(userType)) { buildFromAttribute = patternMatcher.TryGetConverterFunc(typeof(TAttribute), userType); } else { // Try with a converter // Find a builder for : TAttribute --> TType // and then couple with a converter: TType --> TParameterType converter = cm.GetConverter <TAttribute>(typeof(TType), userType); if (converter == null) { var targetType = typeof(TType); context.BindingErrors.Add(String.Format(Resource.BindingAssemblyConflictMessage, targetType.AssemblyQualifiedName, userType.AssemblyQualifiedName)); return(null); } buildFromAttribute = patternMatcher.TryGetConverterFunc(typeof(TAttribute), typeof(TType)); } if (buildFromAttribute == null) { return(null); } ParameterDescriptor param; if (parent.BuildParameterDescriptor != null) { param = parent.BuildParameterDescriptor(attributeSource, parameter, parent._nameResolver); } else { param = new ParameterDescriptor { Name = parameter.Name, DisplayHints = new ParameterDisplayHints { Description = "input" } }; } return(new ExactBinding(cloner, param, buildFromAttribute, converter, userType)); }