9 namespace Core.TypeCast
12 using System.Collections;
13 using System.Collections.Concurrent;
14 using System.Collections.Generic;
15 using System.Globalization;
17 using System.Linq.Expressions;
18 using System.Reflection;
19 using System.Runtime.CompilerServices;
20 using System.Runtime.InteropServices;
21 using System.Threading;
37 [Singleton(disposable:
true, createInternal:
true, initByAttribute:
true)]
38 [System.Runtime.InteropServices.ComVisible(
false)]
39 public partial class ConverterCollection : Singleton<ConverterCollection>, IConverterCollection, IDisposable, IEnumerable<Converter>, IQueryable<Converter>
50 private readonly Dictionary<string, List<Type>> loadOnDemandConverters;
62 : this(application: null, numberFormatDefault: null, converterClasses: null)
73 : this(application: application, numberFormatDefault: null, converterClasses: null)
85 public ConverterCollection(Type application, Type converterClass, NumberFormatInfo numberFormatDefault = null)
86 : this(application: application, numberFormatDefault: numberFormatDefault, converterClasses: converterClass)
98 : this(application: null, numberFormatDefault: numberFormatDefault, converterClasses: null)
100 this.Initialize(assembly);
109 : this(application: application, numberFormatDefault: null, converterClasses: converterClasses)
133 public ConverterCollection(Type application = null, NumberFormatInfo numberFormatDefault = null, params Type[] converterClasses)
136 this.loadOnDemandConverters =
new Dictionary<string, List<Type>>();
141 this.AssemblyInitialized =
new ConcurrentDictionary<Assembly, bool>();
142 this.ConverterClassInitialized =
new ConcurrentDictionary<TypeInfo, bool>();
143 this.ConstructorAddedClasses =
new List<Type>();
144 this.Items =
new BlockingCollection<Converter>(boundedCapacity: this.Settings.BoundedCapacity);
146 if(application != null)
148 ApplicationNameSpace = application.Namespace;
149 this.Initialize(ApplicationNameSpace);
152 if(numberFormatDefault as NumberFormatInfo != null)
154 this.Settings.NumberFormat = numberFormatDefault;
157 if(converterClasses != null)
159 foreach(var converterClass
in converterClasses)
161 if(converterClass != null && converterClass.GetTypeInfo().IsClass ==
true)
163 ConstructorAddedClasses.Add(converterClass);
165 this.AddAllConvertersByAttribute(converterClass.GetTypeInfo());
171 this.Initialize(this.GetType().GetTypeInfo()?.Assembly.DefinedTypes);
188 public string ApplicationNameSpace {
get;
set; }
193 public List<Type> ConstructorAddedClasses {
get; }
198 public ConcurrentDictionary<Assembly, bool> AssemblyInitialized {
get; }
203 public ConcurrentDictionary<TypeInfo, bool> ConverterClassInitialized {
get; }
223 return this.Items.Count;
228 if(value != this.count)
240 public BlockingCollection<Converter> Items {
get; }
246 public bool IsAddingCompleted
250 return this.Items.IsAddingCompleted;
256 this.Items.CompleteAdding();
262 #region Implementation of IQueryable<Converter> 268 public Type ElementType
272 return this.Items.AsQueryable().ElementType;
280 public Expression Expression
284 return this.Items.AsQueryable().Expression;
292 public IQueryProvider Provider
296 return this.Items.AsQueryable().Provider;
311 return this.Items?.Skip(index)?.FirstOrDefault();
321 public Converter this[Type typeFrom, Type typeTo]
325 return this.Get(typeFrom.GetTypeInfo(), typeTo.GetTypeInfo());
335 public Converter this[TypeInfo typeFrom, TypeInfo typeTo]
339 return this.Get(typeFrom, typeTo);
349 public IEnumerable<Converter>
this[TypeInfo typeFrom]
353 return this.WithFrom(typeFrom);
367 CancellationToken cancellationToken =
default(CancellationToken)) where TBase :
class 369 return new AddBuilder<TBase>(
this, settings: settings, cancellationToken: ref cancellationToken);
382 ref CancellationToken cancellationToken) where TBase :
class 384 return new AddBuilder<TBase>(
this, settings: settings, cancellationToken: ref cancellationToken);
399 Func<TIn, TOut> converterAction,
400 Type baseType = null,
401 CancellationToken cancellationToken =
default(CancellationToken))
404 return this.Add(converter: converter, baseType: baseType, cancellationToken: cancellationToken);
422 Func<TIn, TOut> converterActionForward,
423 Func<TOut, TIn> converterActionBackward,
424 Type baseType = null,
425 CancellationToken cancellationToken =
default(CancellationToken))
427 this.Add(converterAction: converterActionForward, baseType: baseType, cancellationToken: cancellationToken);
428 return this.Add(converterAction: converterActionBackward, baseType: baseType, cancellationToken: cancellationToken);
442 public IConverterCollection Add<TIn, TOut, TBase>(Func<TIn, TOut> converterAction, CancellationToken cancellationToken =
default(CancellationToken))
446 return this.Add(converter: converter, baseType: typeof(TBase), cancellationToken: cancellationToken);
460 Func<TIn, TOut, TOut> converterActionDefault,
461 CancellationToken cancellationToken =
default(CancellationToken)) where TBase :
class 463 var converter =
Factory.
Create<TIn, TOut>(converterActionDefault);
464 return this.Add(converter: converter, baseType: typeof(TBase), cancellationToken: cancellationToken);
480 Func<TIn, TArg, TOut> converterActionAny,
481 CancellationToken cancellationToken =
default(CancellationToken))
483 if(typeof(TOut) == typeof(TArg))
485 var converter =
Factory.
Create<TIn, TOut>((Func<TIn, TOut, TOut>)(
object)converterActionAny);
486 return this.Add(converter: converter, baseType: typeof(TBase), cancellationToken: cancellationToken);
488 return this.Add(converterDelegate: converterActionAny, baseType: typeof(TBase), cancellationToken: cancellationToken);
504 Func<TIn, TArg, TOut> converterActionAny,
505 Type baseType = null,
506 CancellationToken cancellationToken =
default(CancellationToken))
508 if(typeof(TOut) == typeof(TArg))
510 var converter =
Factory.
Create<TIn, TOut>((Func<TIn, TOut, TOut>)(
object)converterActionAny);
511 return this.Add(converter: converter, baseType: baseType, cancellationToken: cancellationToken);
513 return this.Add(converterDelegate: converterActionAny, baseType: baseType, cancellationToken: cancellationToken);
525 public IConverterCollection Add<TBase>(
object converterDelegate, CancellationToken cancellationToken =
default(CancellationToken)) where TBase :
class 527 return this.Add(converterDelegate: converterDelegate, baseType: typeof(TBase), cancellationToken: cancellationToken);
551 public IConverterCollection Add(
object converterDelegate, Type baseType = null, CancellationToken cancellationToken =
default(CancellationToken))
553 if(converterDelegate == null)
557 if((converterDelegate is Delegate) ==
false)
564 baseType = ((Delegate)converterDelegate).Target.GetType().DeclaringType;
567 var methodInfo = ((Delegate)converterDelegate).GetMethodInfo();
568 return this.Add(methodInfo: methodInfo, converterDelegate: converterDelegate, baseType: baseType, cancellationToken: cancellationToken);
581 public IConverterCollection Add(MethodInfo methodInfo,
object converterDelegate = null, Type baseType = null,
object baseInstance = null,
582 CancellationToken cancellationToken =
default(CancellationToken))
585 var converter = this.
Factory.
Create(methodInfo, converterDelegate);
587 if(converter != null)
589 converter.Base = baseInstance;
590 return this.Add(converter: converter, baseType: baseType, cancellationToken: cancellationToken);
608 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Usage",
"CA2200:RethrowToPreserveStackDetails")]
609 public IConverterCollection Add(
Converter converter, Type baseType = null,
bool allowDisambiguates =
false, CancellationToken cancellationToken =
default(CancellationToken))
611 if(converter == null)
623 converter.SetCollectionDefaults(
this);
625 if(allowDisambiguates ==
false && baseType?.GetTypeInfo().BaseType == typeof(MulticastDelegate))
627 allowDisambiguates =
true;
632 if(allowDisambiguates ==
false && converter.
Standard)
634 var converterLookup = this.Get(typeFrom: converter.
From, typeTo: converter.
To, typeArgument: typeof(
object).GetTypeInfo(), loadOnDemand:
false, isStandard:
true);
637 if(converterLookup?.MergeStandard(converter) ==
true)
649 converter.SetBaseType(baseType);
651 this.Items.TryAdd(converter, 100, cancellationToken);
652 OnPropertyChanged(converter);
678 return this.WithFrom(typeFrom.GetTypeInfo()).FirstOrDefault() != null;
687 public bool CanConvertFrom<TIn>()
689 return this.WithFrom(typeof(TIn).GetTypeInfo()).FirstOrDefault() != null;
700 return this.WithTo(typeTo.GetTypeInfo()).FirstOrDefault() != null;
709 public bool CanConvertTo<TOut>()
711 return this.WithTo(typeof(TOut).GetTypeInfo()).FirstOrDefault() != null;
723 if(baseType == null || (attribute != null && update ==
false))
730 attribute.BaseType = baseType;
732 var converter = this.Get(baseType.AsType());
733 if(converter != null && (converter.Attribute == null || converter.Attribute != null && update ==
true))
752 var nameSpace = typeTo?.Namespace.Split(
'.').Last();
753 if(nameSpace != null && this.loadOnDemandConverters.ContainsKey(nameSpace))
755 var loaded = this.loadOnDemandConverters[nameSpace].Select(this.CreateConverterClassInstance).Count();
756 this.loadOnDemandConverters.Remove(nameSpace);
766 private static bool AutoInitialized;
779 if(AutoInitialized ==
false && CurrentInstance.Settings.AutoInitialize ==
true)
783 var getEntryAssembly = typeof(Assembly).GetRuntimeMethods().FirstOrDefault(m => m.Name.Equals(
"GetEntryAssembly"));
784 if(getEntryAssembly != null)
786 var assembly = getEntryAssembly.Invoke(null, null) as Assembly;
787 CurrentInstance.Initialize(assembly);
788 CurrentInstance.ApplicationNameSpace = assembly?.GetNamespacesByLevel(0)?.FirstOrDefault();
791 AutoInitialized =
true;
815 IEnumerable<TypeInfo> types = Assembly.Load(
new AssemblyName(applicationNameSpace)).DefinedTypes;
816 this.Initialize(types);
834 if(applicationClass != null)
836 var assembly = applicationClass.GetTypeInfo().Assembly;
837 this.Initialize(
new[] { assembly });
854 this.Initialize(
new[] { assembly });
871 foreach(var assembly
in assemblies)
873 if(assembly == null || this.AssemblyInitialized.ContainsKey(assembly) ==
true)
879 this.Initialize(types);
896 foreach(var type
in types)
898 this.AddAllConvertersByAttribute(type);
909 [System.Diagnostics.CodeAnalysis.SuppressMessage(
"Microsoft.Usage",
"CA2213:DisposableFieldsShouldBeDisposed", MessageId =
"<Items>k__BackingField")]
910 protected override void Dispose(
bool disposing)
912 this.Items.Dispose();
913 base.Dispose(disposing);
923 return this.AssemblyInitialized.AddOrUpdate(type.Assembly,
true, (oldkey, oldval) =>
true);
934 return this.ConverterClassInitialized.AddOrUpdate(converterClass,
true, (oldkey, oldval) =>
true);
943 private object CreateConverterClassInstance(Type converterClass)
945 object customConverter;
947 customConverter = this.FactoryBaseClass.Create(converterClass,
this);
948 this.SetConverterClassInitialized(converterClass.GetTypeInfo());
950 return customConverter;
960 private bool AddAllConvertersByAttribute(TypeInfo type)
962 int count = this.Count;
963 object converterCustom = null;
965 if(ConstructorAddedClasses?.Contains(type.AsType()) ==
false)
968 if(attribute == null)
970 if(type.IsClass ==
true && type.ImplementedInterfaces.Contains(typeof(
IConverter)) ==
true)
972 attribute = this.ConverterAttributeFromIConverter(type, attribute, update:
true);
978 if(attribute?.LoadOnDemand ==
true)
980 if(this.loadOnDemandConverters?.ContainsKey(attribute.NameSpace) ==
false)
982 this.loadOnDemandConverters.Add(attribute.NameSpace,
new List<Type>());
985 if(this.loadOnDemandConverters[attribute.NameSpace]?.Contains(type.AsType()) ==
false)
987 this.loadOnDemandConverters[attribute.NameSpace].Add(type.AsType());
993 if(attribute?.DependencInjection ==
true)
995 converterCustom = this.CreateConverterClassInstance(type.AsType());
1000 foreach(var declaredMethod
in type.DeclaredMethods)
1003 if(customAttribute != null)
1007 if((declaredMethod.IsStatic ==
false && declaredMethod.GetParameters().Length == 0) || customAttribute.PassInstance ==
true)
1010 this.Add(converter: converter, baseType: type.AsType());
1014 if(converterCustom == null)
1016 converterCustom = this.CreateConverterClassInstance(type.AsType());
1018 if(converterCustom != null)
1020 this.Add(methodInfo: declaredMethod, baseType: type.AsType(), baseInstance: converterCustom);
1026 this.SetAssemblyInitialized(type);
1027 return count != this.Count;
1030 #region Implementation of IEnumerable 1040 var enumerator = this.Items as IEnumerable<Converter>;
1041 return enumerator.GetEnumerator();
1050 IEnumerator IEnumerable.GetEnumerator()
1052 return ((IEnumerable)this.Items).GetEnumerator();
int LoadOnDemandConverter(Type typeTo)
Tries to lookup the namespace obtained from typeTo in loadOnDemandConverters and add the converters...
void Initialize(Type applicationClass)
Initializes all attributed Converter classes, Initialize(Assembly[])
void Initialize(Assembly assembly)
Initializes all attributed Converter classes, Initialize(Assembly[])
ConverterCollection(Type application=null, params Type[] converterClasses)
Initializes a new instance of the ConverterCollection class with default-parameters.
IConverterCollection Add(Converter converter, Type baseType=null, bool allowDisambiguates=false, CancellationToken cancellationToken=default(CancellationToken))
Adds a Converter instance to the collection of ConverterCollection.Items
static void AutoInitialize()
Checks if the ConverterCollection is initialized. Attempts to initialize and load the user-assembly i...
ConverterCollection(Type application)
Initializes a new instance of the ConverterCollection class with default-parameters.
abstract TInstance Create(TIn1 parameter)
Abstract method for creating instances of TInstance defined only through parameter ...
bool HasFunction
Gets a value indicating whether the converter has either Function or FunctionDefault set...
bool SetAssemblyInitialized(TypeInfo type)
Sets the Assembly as initialized in AssemblyInitialized
IConverterCollection Add(MethodInfo methodInfo, object converterDelegate=null, Type baseType=null, object baseInstance=null, CancellationToken cancellationToken=default(CancellationToken))
Creates and adds a Converter instance to the collection of ConverterCollection.Items using a MethodIn...
Creates instances from classes which are attributed by ConverterAttribute
TypeInfo From
Gets the Type of the object instance which is to be converted.
bool CanConvertFrom(Type typeFrom)
Returns bool true if the ConverterCollection supports conversion for a given Type typeFrom ...
The thread-safe, static collection of Converter items, using Core.Singleton and supporting Core...
TypeInfo To
Gets the Type that the instance will be converted to.
Use ConverterAttribute to declare a class as a logical Type Converter. As such the only contingent de...
Use ConverterMethodAttribute to declare a method in an arbitrary class as a logical Converter functio...
IConverterCollection Add(object converterDelegate, Type baseType=null, CancellationToken cancellationToken=default(CancellationToken))
Initializes a new instance of the ConverterCollection class with default-parameters.
The Exception-type which is raised exclusively by the Converter<TIn,TOut> Library ...
void Initialize(Assembly[] assemblies)
Initializes all attributed Converter classes, unless the ConverterAttribute parameter ConverterAttrib...
ConverterCollection(Assembly assembly, NumberFormatInfo numberFormatDefault=null)
Initializes a new instance of the ConverterCollection class with default-parameters.
The settings for the ConverterCollection.
void Initialize(IEnumerable< TypeInfo > types)
Initializes all attributed Converter classes, unless the ConverterAttribute parameter ConverterAttrib...
override void Dispose(bool disposing)
Dispose of the Items and underlying static Singleton<TClass> references.
void Initialize(string applicationNameSpace)
Initializes all attributed Converter classes, Initialize(Assembly[])
The Base Converter interface.
bool Standard
Gets a value indicating whether the Converter instance is strictly typed such that the ArgumentType i...
ConverterCollectionCause
Contains the reasons for a ConverterCollectionException to be raised.
ConverterAttribute Attribute
Gets or sets the ConverterAttribute if the custom converter class has one defined, else it is set null.
The abstract generic factory for creating arbitrary instances requiring up to two arguments...
Allows to perform a deferred adding operation of multiple adds using a common Base-Class Type argumen...
bool SetConverterClassInitialized(TypeInfo converterClass)
Sets the Converter of the ConverterCollection as initialized
ConverterCollection()
Initializes a new instance of the ConverterCollection class with default-parameters.
ConverterCollectionCause Cause
Gets or sets the exception's ConverterCollectionCause, which is set through the parameterized excepti...
The Exception-type which is raised exclusively by the Converter<T> Library
Creates new instances of Converter<TIn, TOut> dependent on the source TIn and target Type TOut ...
bool CanConvertTo(Type typeTo)
Returns bool true if the ConverterCollection supports conversion for a given Type typeTo ...
IEnumerator< Converter > GetEnumerator()
Returns an enumerator that iterates through the collection.
ConverterAttribute ConverterAttributeFromIConverter(TypeInfo baseType, ConverterAttribute attribute=null, bool update=false)
Adds or updates an attribute for a Converter if it exists, dependent only on the source and target co...
ConverterCollection(Type application, Type converterClass, NumberFormatInfo numberFormatDefault=null)
Initializes a new instance of the ConverterCollection class with default-parameters.
bool AllowDisambiguates
Optional bool value to indicate whether a ConverterCollection is allowed to contain multiple converte...
ConverterCause
Contains the reasons for a ConverterException to be raised.
The Converter base class, providing a simple container for conversion types, ConverterAttribute and c...