// 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);
}
}
}