/// <summary> /// 获取类型转换器 /// </summary> /// <param name="typeToConvert"></param> /// <returns></returns> public BinaryConverter GetConverter(Type typeToConvert) { // 从缓存获取 if (_converters.TryGetValue(typeToConvert, out BinaryConverter converter)) { Debug.Assert(converter != null); return(converter); } // Priority 2: Attempt to get custom converter added at runtime. // Currently there is not a way at runtime to overide the [BinaryConverter] when applied to a property. foreach (BinaryConverter item in Converters) { if (item.CanConvert(typeToConvert)) { converter = item; break; } } // Priority 3: Attempt to get converter from [BinaryConverter] on the type being converted. if (converter == null) { BinaryConverterAttribute converterAttribute = (BinaryConverterAttribute) GetAttributeThatCanHaveMultiple(typeToConvert, typeof(BinaryConverterAttribute)); if (converterAttribute != null) { converter = GetConverterFromAttribute(converterAttribute, typeToConvert: typeToConvert, classTypeAttributeIsOn: typeToConvert, memberInfo: null); } } // Priority 4: Attempt to get built-in converter. if (converter == null) { if (s_defaultSimpleConverters.TryGetValue(typeToConvert, out BinaryConverter foundConverter)) { Debug.Assert(foundConverter != null); converter = foundConverter; } else { foreach (BinaryConverter item in s_defaultFactoryConverters) { if (item.CanConvert(typeToConvert)) { converter = item; break; } } // Since the object and IEnumerable converters cover all types, we should have a converter. Debug.Assert(converter != null); } } // Allow redirection for generic types or the enum converter. if (converter is BinaryConverterFactory factory) { converter = factory.GetConverterInternal(typeToConvert, this); // A factory cannot return null; GetConverterInternal checked for that. Debug.Assert(converter != null); } Type converterTypeToConvert = converter.TypeToConvert; if (!converterTypeToConvert.IsAssignableFromInternal(typeToConvert) && !typeToConvert.IsAssignableFromInternal(converterTypeToConvert)) { ThrowHelper.ThrowInvalidOperationException_SerializationConverterNotCompatible(converter.GetType(), typeToConvert); } // Only cache the value once (de)serialization has occurred since new converters can be added that may change the result. if (_haveTypesBeenCreated) { // A null converter is allowed here and cached. // Ignore failure case here in multi-threaded cases since the cached item will be equivalent. _converters.TryAdd(typeToConvert, converter); } return(converter); }