// Copyright 2009-2022 Josh Close // This file is a part of CsvHelper and is dual licensed under MS-PL and Apache 2.0. // See LICENSE.txt for details or visit http://www.opensource.org/licenses/ms-pl.html for MS-PL and http://opensource.org/licenses/Apache-2.0 for Apache 2.0. // https://github.com/JoshClose/CsvHelper using System; namespace CsvHelper { /// /// Creates objects from a given type. /// public class ObjectResolver : IObjectResolver { private static IObjectResolver current; private readonly ObjectCreator objectCreator = new ObjectCreator(); /// /// Gets or sets the current resolver. /// Use an instance of this instead if at all possible. /// public static IObjectResolver Current { get { return current; } set { if (value == null) { throw new InvalidOperationException($"{nameof(IObjectResolver)} cannot be null."); } current = value; } } /// /// A value indicating if the resolver's /// returns false that an object will still be created using /// CsvHelper's object creation. True to fallback, otherwise false. /// Default value is true. /// public bool UseFallback { get; private set; } /// /// A function that returns a value indicating if the resolver /// is able to resolve the given type. True if the type can be /// resolved, otherwise false. /// public Func CanResolve { get; private set; } /// /// The function that creates an object from a given type. /// public Func ResolveFunction { get; private set; } static ObjectResolver() { var objectCreator = new ObjectCreator(); var locker = new object(); current = new ObjectResolver(type => true, (type, args) => { lock (locker) { return objectCreator.CreateInstance(type, args); } }); } /// /// Creates an instance of the object resolver using default values. /// public ObjectResolver() { CanResolve = type => true; ResolveFunction = ResolveWithObjectCreator; UseFallback = true; } /// /// Creates an instance of the object resolver using the given can create function /// and create function. /// /// A function that returns a value indicating if the resolver /// is able to resolve the given type. True if the type can be /// resolved, otherwise false. /// The function that creates an object from a given type. /// A value indicating if the resolver's /// returns false that an object will still be created using /// CsvHelper's object creation. True to fallback, otherwise false. /// Default value is true. public ObjectResolver(Func canResolve, Func resolveFunction, bool useFallback = true) { CanResolve = canResolve ?? throw new ArgumentNullException(nameof(canResolve)); ResolveFunction = resolveFunction ?? throw new ArgumentNullException(nameof(resolveFunction)); UseFallback = useFallback; } /// /// Creates an object from the given type using the /// function. If is false, the object will be /// created using CsvHelper's default object creation. If /// is false, an exception is thrown. /// /// The type to create an instance from. The created object /// may not be the same type as the given type. /// Constructor arguments used to create the type. public object Resolve(Type type, params object[] constructorArgs) { if (CanResolve(type)) { return ResolveFunction(type, constructorArgs); } if (UseFallback) { return objectCreator.CreateInstance(type, constructorArgs); } throw new CsvHelperException($"Type '{type.FullName}' can't be resolved and fallback is turned off."); } /// /// Creates an object from the given type using the /// function. If is false, the object will be /// created using CsvHelper's default object creation. If /// is false, an exception is thrown. /// /// The type to create an instance from. The created object /// may not be the same type as the given type. /// Constructor arguments used to create the type. public T Resolve(params object[] constructorArgs) { return (T)Resolve(typeof(T), constructorArgs); } private object ResolveWithObjectCreator(Type type, params object[] args) { return objectCreator.CreateInstance(type, args); } } }