// This file is part of YamlDotNet - A .NET library for YAML. // Copyright (c) Antoine Aubry and contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using System; using System.Collections.Generic; using YamlDotNet.Core; using YamlDotNet.Serialization.Converters; using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.TypeInspectors; namespace YamlDotNet.Serialization { /// /// Common implementation of and . /// public abstract class BuilderSkeleton where TBuilder : BuilderSkeleton { internal INamingConvention namingConvention = NullNamingConvention.Instance; internal ITypeResolver typeResolver; internal readonly YamlAttributeOverrides overrides; internal readonly LazyComponentRegistrationList typeConverterFactories; internal readonly LazyComponentRegistrationList typeInspectorFactories; private bool ignoreFields; private bool includeNonPublicProperties = false; internal BuilderSkeleton(ITypeResolver typeResolver) { overrides = new YamlAttributeOverrides(); typeConverterFactories = new LazyComponentRegistrationList { { typeof(GuidConverter), _ => new GuidConverter(false) }, { typeof(SystemTypeConverter), _ => new SystemTypeConverter() } }; typeInspectorFactories = new LazyComponentRegistrationList(); this.typeResolver = typeResolver ?? throw new ArgumentNullException(nameof(typeResolver)); } protected abstract TBuilder Self { get; } internal ITypeInspector BuildTypeInspector() { ITypeInspector innerInspector = new ReadablePropertiesTypeInspector(typeResolver, includeNonPublicProperties); if (!ignoreFields) { innerInspector = new CompositeTypeInspector( new ReadableFieldsTypeInspector(typeResolver), innerInspector ); } return typeInspectorFactories.BuildComponentChain(innerInspector); } /// /// Prevents serialization and deserialization of fields. /// /// public TBuilder IgnoreFields() { ignoreFields = true; return Self; } /// /// Allows serialization and deserialization of non-public properties. /// public TBuilder IncludeNonPublicProperties() { includeNonPublicProperties = true; return Self; } /// /// Sets the that will be used by the (de)serializer. /// public TBuilder WithNamingConvention(INamingConvention namingConvention) { this.namingConvention = namingConvention ?? throw new ArgumentNullException(nameof(namingConvention)); return Self; } /// /// Sets the that will be used by the (de)serializer. /// public TBuilder WithTypeResolver(ITypeResolver typeResolver) { this.typeResolver = typeResolver ?? throw new ArgumentNullException(nameof(typeResolver)); return Self; } public abstract TBuilder WithTagMapping(TagName tag, Type type); #if !NET20 /// /// Register an for a given property. /// /// /// An expression in the form: x => x.SomeProperty /// The attribute to register. /// public TBuilder WithAttributeOverride(System.Linq.Expressions.Expression> propertyAccessor, Attribute attribute) { overrides.Add(propertyAccessor, attribute); return Self; } #endif /// /// Register an for a given property. /// public TBuilder WithAttributeOverride(Type type, string member, Attribute attribute) { overrides.Add(type, member, attribute); return Self; } /// /// Registers an additional to be used by the (de)serializer. /// public TBuilder WithTypeConverter(IYamlTypeConverter typeConverter) { return WithTypeConverter(typeConverter, w => w.OnTop()); } /// /// Registers an additional to be used by the (de)serializer. /// /// /// Configures the location where to insert the public TBuilder WithTypeConverter( IYamlTypeConverter typeConverter, Action> where ) { if (typeConverter == null) { throw new ArgumentNullException(nameof(typeConverter)); } if (where == null) { throw new ArgumentNullException(nameof(where)); } where(typeConverterFactories.CreateRegistrationLocationSelector(typeConverter.GetType(), _ => typeConverter)); return Self; } /// /// Registers an additional to be used by the (de)serializer. /// /// A factory that creates the based on a previously registered . /// Configures the location where to insert the public TBuilder WithTypeConverter( WrapperFactory typeConverterFactory, Action> where ) where TYamlTypeConverter : IYamlTypeConverter { if (typeConverterFactory == null) { throw new ArgumentNullException(nameof(typeConverterFactory)); } if (where == null) { throw new ArgumentNullException(nameof(where)); } where(typeConverterFactories.CreateTrackingRegistrationLocationSelector(typeof(TYamlTypeConverter), (wrapped, _) => typeConverterFactory(wrapped))); return Self; } /// /// Unregisters an existing of type . /// public TBuilder WithoutTypeConverter() where TYamlTypeConverter : IYamlTypeConverter { return WithoutTypeConverter(typeof(TYamlTypeConverter)); } /// /// Unregisters an existing of type . /// public TBuilder WithoutTypeConverter(Type converterType) { if (converterType == null) { throw new ArgumentNullException(nameof(converterType)); } typeConverterFactories.Remove(converterType); return Self; } /// /// Registers an additional to be used by the (de)serializer. /// /// A function that instantiates the type inspector. public TBuilder WithTypeInspector(Func typeInspectorFactory) where TTypeInspector : ITypeInspector { return WithTypeInspector(typeInspectorFactory, w => w.OnTop()); } /// /// Registers an additional to be used by the (de)serializer. /// /// A function that instantiates the type inspector. /// Configures the location where to insert the public TBuilder WithTypeInspector( Func typeInspectorFactory, Action> where ) where TTypeInspector : ITypeInspector { if (typeInspectorFactory == null) { throw new ArgumentNullException(nameof(typeInspectorFactory)); } if (where == null) { throw new ArgumentNullException(nameof(where)); } where(typeInspectorFactories.CreateRegistrationLocationSelector(typeof(TTypeInspector), inner => typeInspectorFactory(inner))); return Self; } /// /// Registers an additional to be used by the (de)serializer. /// /// A function that instantiates the type inspector based on a previously registered .. /// Configures the location where to insert the public TBuilder WithTypeInspector( WrapperFactory typeInspectorFactory, Action> where ) where TTypeInspector : ITypeInspector { if (typeInspectorFactory == null) { throw new ArgumentNullException(nameof(typeInspectorFactory)); } if (where == null) { throw new ArgumentNullException(nameof(where)); } where(typeInspectorFactories.CreateTrackingRegistrationLocationSelector(typeof(TTypeInspector), (wrapped, inner) => typeInspectorFactory(wrapped, inner))); return Self; } /// /// Unregisters an existing of type . /// public TBuilder WithoutTypeInspector() where TTypeInspector : ITypeInspector { return WithoutTypeInspector(typeof(TTypeInspector)); } /// /// Unregisters an existing of type . /// public TBuilder WithoutTypeInspector(Type inspectorType) { if (inspectorType == null) { throw new ArgumentNullException(nameof(inspectorType)); } typeInspectorFactories.Remove(inspectorType); return Self; } protected IEnumerable BuildTypeConverters() { return typeConverterFactories.BuildComponentList(); } } /// /// A factory that creates instances of based on an existing . /// /// The type of the wrapped component. /// The type of the component that this factory creates. /// The component that is to be wrapped. /// Returns a new instance of that is based on . public delegate TComponent WrapperFactory(TComponentBase wrapped) where TComponent : TComponentBase; /// /// A factory that creates instances of based on an existing and an argument. /// /// The type of the argument. /// The type of the wrapped component. /// The type of the component that this factory creates. /// The component that is to be wrapped. /// The argument of the factory. /// Returns a new instance of that is based on and . public delegate TComponent WrapperFactory(TComponentBase wrapped, TArgument argument) where TComponent : TComponentBase; }