.NET Portable TypeCast  3.1.0.4
A, easy-to-use tested, generic, portable, runtime-extensible, arbitrary type converter library
ConverterCollectionFilters.cs
Go to the documentation of this file.
1 // <copyright file=mitlicense.md url=http://lsauer.mit-license.org/ >
2 // Lo Sauer, 2013-2016
3 // </copyright>
4 // <summary> A tested, generic, portable, runtime-extensible type converter library </summary
5 // <language> C# > 6.0 </language>
6 // <version> 3.1.0.2 </version>
7 // <author> Lorenz Lo Sauer; people credited in the sources </author>
8 // <project> https://github.com/lsauer/dotnet-portable-type-cast </project>
9 namespace Core.TypeCast
10 {
11  using System;
12  using System.Collections;
13  using System.Collections.Concurrent;
14  using System.Collections.Generic;
15  using System.Globalization;
16  using System.Linq;
17  using System.Linq.Expressions;
18  using System.Reflection;
19  using System.Runtime.CompilerServices;
20  using System.Runtime.InteropServices;
21  using System.Threading;
22 
23  using Core.Extensions;
24  using Core.Singleton;
25  using Core.TypeCast.Base;
26 
30  public static class ConverterCollectionFilters
31  {
32  private static TypeInfo objectTypeInfo = typeof(object).GetTypeInfo();
33  private static TypeInfo convertContexTypeInfo = typeof(IConvertContext).GetTypeInfo();
34 
42  [MethodImpl(MethodImplOptions.AggressiveInlining)]
43  public static IQueryable<Converter> WithFrom(this IQueryable<Converter> query, TypeInfo typeFrom, bool assignable = false)
44  {
45  if(typeFrom != null)
46  {
47  query = WithAssignable(query, c => c.From == typeFrom, c => c.From.IsSuperOrSubType(typeFrom), typeFrom, assignable);
48  }
49  return query;
50  }
51 
59  [MethodImpl(MethodImplOptions.AggressiveInlining)]
60  public static IQueryable<Converter> WithFrom(this IQueryable<Converter> query, Type typeFrom, bool assignable = false)
61  {
62  return WithFrom(query, typeFrom?.GetTypeInfo(), assignable);
63  }
64 
72  [MethodImpl(MethodImplOptions.AggressiveInlining)]
73  public static IQueryable<Converter> WithTo(this IQueryable<Converter> query, TypeInfo typeTo, bool assignable = false)
74  {
75  if(typeTo != null)
76  {
77  query = WithAssignable(query, c => c.To == typeTo, c => c.To.IsSuperOrSubType(typeTo), typeTo, assignable);
78  }
79  return query;
80  }
81 
89  [MethodImpl(MethodImplOptions.AggressiveInlining)]
90  public static IQueryable<Converter> WithTo(this IQueryable<Converter> query, Type typeTo, bool assignable = false)
91  {
92  return WithTo(query, typeTo?.GetTypeInfo(), assignable);
93  }
94 
102  [MethodImpl(MethodImplOptions.AggressiveInlining)]
103  public static IQueryable<Converter> WithBaseType(this IQueryable<Converter> query, TypeInfo typeBase, bool assignable = false)
104  {
105  if(typeBase != null && typeBase.AsType() != typeof(object))
106  {
107  query = WithAssignable(query, c => c.BaseType == typeBase, c => c.BaseType.IsSuperOrSubType(typeBase), typeBase, assignable);
108  }
109  return query;
110  }
111 
119  [MethodImpl(MethodImplOptions.AggressiveInlining)]
120  public static IQueryable<Converter> WithBaseType(this IQueryable<Converter> query, Type typeBase, bool assignable = false)
121  {
122  return WithBaseType(query, typeBase?.GetTypeInfo(), assignable);
123  }
124 
134  [MethodImpl(MethodImplOptions.AggressiveInlining)]
135  public static IQueryable<Converter> WithArgument(this IQueryable<Converter> query, TypeInfo typeArgument, bool assignable = false, bool withContext = false)
136  {
137  // extend converters taking a context to converters with object argument
138  if(withContext == true)
139  {
140  query = query.Where(c => c.Argument == objectTypeInfo || c.Argument.IsSuperOrSubType(convertContexTypeInfo));
141  }
142  else if(typeArgument != null && (assignable == false || typeArgument != objectTypeInfo))
143  {
144  query = WithAssignable(query, c => c.Argument == typeArgument, c => c.Argument.IsSuperOrSubType(typeArgument), typeArgument, assignable);
145  }
146 
147  return query;
148  }
149 
159  [MethodImpl(MethodImplOptions.AggressiveInlining)]
160  public static IQueryable<Converter> WithArgument(this IQueryable<Converter> query, Type typeArgument, bool assignable = true, bool withContext = false)
161  {
162  return WithArgument(query, typeArgument?.GetTypeInfo(), assignable, withContext);
163  }
164 
176  [MethodImpl(MethodImplOptions.AggressiveInlining)]
177  private static IQueryable<Converter> WithAssignable(IQueryable<Converter> query, Expression<Func<Converter, bool>> predicate, Expression<Func<Converter, bool>> predicateAssignable, TypeInfo type, bool assignable)
178  {
179  var testQuery = query.Where(predicate);
180  if((type == objectTypeInfo || testQuery.Any()) && assignable == false)
181  {
182  query = testQuery;
183  }
184  else
185  {
186  // check for interfaces, sub-types ...
187  query = query.Where(predicateAssignable);
188  }
189  return query;
190  }
191 
198  [MethodImpl(MethodImplOptions.AggressiveInlining)]
199  public static IQueryable<Converter> WithStandard(this IQueryable<Converter> query, bool? isStandard = true)
200  {
201  if(isStandard != null)
202  {
203  query = query.Where(c => c.Standard == isStandard);
204  }
205  return query;
206  }
207 
208 
216  [MethodImpl(MethodImplOptions.AggressiveInlining)]
217  public static IQueryable<Converter> WithFromIsGenericType(this IQueryable<Converter> query, bool? typeFromIsGenericType = true)
218  {
219  if(typeFromIsGenericType != null)
220  {
221  query = query.Where(c => c.From.IsGenericType == typeFromIsGenericType);
222  }
223  return query;
224  }
225 
233  [MethodImpl(MethodImplOptions.AggressiveInlining)]
234  public static IQueryable<Converter> WithToIsGenericType(this IQueryable<Converter> query, bool? typeToIsGenericType = true)
235  {
236  if(typeToIsGenericType != null)
237  {
238  query = query.Where(c => c.From.IsGenericType == typeToIsGenericType);
239  }
240  return query;
241  }
242 
243  //(converter.Function as Delegate).Method.Name
251  [MethodImpl(MethodImplOptions.AggressiveInlining)]
252  public static IQueryable<Converter> WithFunctionName(this IQueryable<Converter> query, string containedName = null)
253  {
254  if(containedName != null)
255  {
256  query = query.Where(c => (c.Function != null && (c.Function as Delegate).GetMethodInfo().Name.Contains(containedName) == true) ||
257  (c.FunctionDefault != null && (c.FunctionDefault as Delegate).GetMethodInfo().Name.Contains(containedName) == true)
258  );
259  }
260  return query;
261  }
262 
271  [MethodImpl(MethodImplOptions.AggressiveInlining)]
272  public static IQueryable<Converter> WithConverterAttributeName(this IQueryable<Converter> query, string containedName = null, bool caseSensitive = false)
273  {
274  if(string.IsNullOrWhiteSpace(containedName) == false)
275  {
276  if(caseSensitive == true)
277  {
278  query = query.Where(c => (c.Attribute != null && c.Attribute.Name.ToLowerInvariant().Equals(containedName.ToLowerInvariant()) == true));
279  }
280  else
281  {
282  query = query.Where(c => (c.Attribute != null && c.Attribute.Name.Equals(containedName) == true));
283  }
284  }
285  return query;
286  }
287 
294  [MethodImpl(MethodImplOptions.AggressiveInlining)]
295  public static IQueryable<Converter> WithDefaultFunction(this IQueryable<Converter> query, bool? hasDefaultFunction = true)
296  {
297  if(hasDefaultFunction != null)
298  {
299  query = query.Where(c => c.HasDefaultFunction == hasDefaultFunction);
300  }
301  return query;
302  }
303 
323  public static IQueryable<Converter> ApplyAllFilters(
324  this IQueryable<Converter> query,
325  TypeInfo typeFrom = null,
326  TypeInfo typeTo = null,
327  TypeInfo typeArgument = null,
328  TypeInfo typeBase = null,
329  bool? hasDefaultFunction = null,
330  bool? isStandard = null,
331  bool? typeFromIsGenericType = null,
332  bool? typeToIsGenericType = null,
333  string functionName = null,
334  string attributeName = null,
335  bool assignableFrom = false,
336  bool assignableTo = false,
337  bool assignableArgument = false,
338  bool assignableBaseType = false,
339  bool withContext = false)
340  {
341  var queryFiltered = query
342  .WithFrom(typeFrom, assignableFrom)
343  .WithTo(typeTo, assignableTo)
344  .WithArgument(typeArgument, assignableArgument, withContext)
345  .WithBaseType(typeBase, assignableBaseType)
346  .WithStandard(isStandard)
347  .WithDefaultFunction(hasDefaultFunction)
348  .WithFromIsGenericType(typeFromIsGenericType)
349  .WithToIsGenericType(typeToIsGenericType)
350  .WithFunctionName(functionName)
351  .WithConverterAttributeName(attributeName);
352 
353  // All converters are contained in Converter_T3's with the argument set as default to: `object` or to `TOut` with a generic Converter.Function
354  if(typeBase == null && queryFiltered.Count() > 1)
355  {
356  typeArgument = typeArgument ?? objectTypeInfo;
357 
358  queryFiltered = queryFiltered.WithArgument(typeArgument, assignableArgument);
359  }
360  return queryFiltered;
361  }
362 
363  }
364 
365 }