.NET Portable TypeCast  3.1.0.4
A, easy-to-use tested, generic, portable, runtime-extensible, arbitrary type converter library
Converter_3T.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.Reflection;
13  using System.Reflection.Emit;
14  using System.Runtime.Serialization;
15 
16  using Core.TypeCast.Base;
17 
25  [DataContract]
26  public class Converter<TIn, TOut, TArg> : Converter, IConverter<TIn, TOut>
27  {
34  public Converter(Func<TIn, TOut> converter)
35  : base(typeof(TIn), typeof(TOut), typeof(TArg))
36  {
37  // Prevent null types in the base
38  if(converter == null)
39  {
40  throw new ConverterException(ConverterCause.ConverterArgumentNull);
41  }
42 
43  this.ConverterFunc = converter;
44  }
45 
55  public Converter(Func<TIn, TOut, TOut> converterDefault)
56  : base(typeof(TIn), typeof(TOut), typeof(TArg))
57  {
58  if(converterDefault == null)
59  {
60  throw new ConverterException(ConverterCause.ConverterArgumentNull);
61  }
62 
63  this.ConverterDefaultFunc = converterDefault;
64  }
65 
76  public Converter(Func<TIn, TArg, TOut> converterAny, Type argument = null)
77  : base(typeof(TIn), typeof(TOut), argument ?? typeof(TArg))
78  {
79  if(converterAny == null)
80  {
81  throw new ConverterException(ConverterCause.ConverterArgumentNull);
82  }
83 
84  this.DefaultValueAnyType = true;
85  this.ConverterAnyFunc = converterAny;
86  }
87 
98  public Converter(MethodInfo converterInfo, Type argument = null)
99  : base(typeof(TIn), typeof(TOut), argument ?? typeof(TArg))
100  {
101  var parameterCount = converterInfo.GetParameters().Length;
102 
103  if(converterInfo == null || parameterCount == 0)
104  {
105  throw new ConverterException(ConverterCause.ConverterArgumentNull);
106  }
107 
108  if(parameterCount == 1)
109  {
110  this.FunctionInfo = converterInfo;
111  this.ConverterFunc = (Func<TIn, TOut>)converterInfo.CreateDelegate(typeof(Func<TIn, TOut>), null);
112  ;
113 
114  }
115  else if(parameterCount == 2)
116  {
117  this.FunctionDefaultInfo = converterInfo;
118  this.DefaultValueAnyType = true;
119  this.ConverterAnyFunc = (Func<TIn, TArg, TOut>)converterInfo.CreateDelegate(typeof(Func<TIn, TArg, TOut>), null);
120  }
121  else
122  {
123  throw new ConverterException(ConverterCause.ConverterArgumentDelegateTooManyParameters);
124  }
125  }
126 
132  [DataMember]
133  public Func<TIn, TArg, TOut> ConverterAnyFunc
134  {
135  get
136  {
137  return (Func<TIn, TArg, TOut>)this.FunctionDefault;
138  }
139 
140  set
141  {
142  this.FunctionDefault = (object)value;
143  }
144  }
145 
149  [DataMember]
150  public Func<TIn, TOut, TOut> ConverterDefaultFunc
151  {
152  get
153  {
154  return (Func<TIn, TOut, TOut>)this.FunctionDefault;
155  }
156 
157  set
158  {
159  this.FunctionDefault = (object)value;
160  }
161  }
162 
168  [DataMember]
169  public Func<TIn, TOut> ConverterFunc
170  {
171  get
172  {
173  return (Func<TIn, TOut>)this.Function;
174  }
175 
176  set
177  {
178  this.Function = (object)value;
179  }
180  }
181 
189  public override object Convert(object value, object defaultValue = null)
190  {
191  this.CheckConvertTypes(value, defaultValue);
192 
193  try
194  {
195  if(this.HasDefaultFunctionOnly == true || (defaultValue != null && ObjectExtension.IsDefaultValue<TOut>(defaultValue) == false))
196  {
197  return this.ConvertDefault(ref value, ref defaultValue);
198  }
199 
200  if(this.ConverterFunc != null)
201  {
202  if(this.Base != null && this.FunctionAttribute?.IsStatic == false && this.FunctionInfo?.IsStatic == false)
203  {
204  return this.FunctionInfo.Invoke(this.Base, new[] { value });
205  }
206 
207  return this.ConverterFunc.Invoke((TIn)value);
208  }
209  }
210  catch(InvalidCastException)
211  {
212  throw new ConverterException(ConverterCause.InvalidCast);
213  }
214  catch(Exception)
215  {
216  throw;
217  }
218 
219  throw new ConverterException(ConverterCause.ConverterFunctionNull);
220  }
221 
229  private object ConvertDefault(ref object value, ref object defaultValue)
230  {
231  if(this.HasDefaultFunction == true)
232  {
233  // note: no need to check for FunctionDefaultInfo.IsStatic, but strongly typed invocation is preferred
234  if(this.Base != null && this.FunctionDefaultAttribute?.IsStatic == false && this.FunctionDefaultInfo?.IsStatic == false)
235  {
236  return this.FunctionDefaultInfo.Invoke(this.Base, new[] { value, defaultValue });
237  }
238  else if(this.DefaultValueAnyType == true)
239  {
240  return this.ConverterAnyFunc.Invoke((TIn)value, (TArg)(defaultValue ?? default(TArg)));
241  }
242  return this.ConverterDefaultFunc.Invoke((TIn)value, (TOut)defaultValue);
243  }
244  else if(this.UseFunctionDefaultWrapper == true && this.ConverterFunc != null)
245  {
246  // Create a default-function wrapper using the existing TIn/TOut converter
247  try
248  {
249  Func<TIn, TOut, TOut> defaultWrapper = this.FunctionDefaultWrapper<TIn, TOut>();
250  return (TOut)defaultWrapper((TIn)value, (TOut)defaultValue);
251  }
252  catch(Exception exc)
253  {
254  throw new ConverterException(ConverterCause.ConvertFailed, exc);
255  }
256  }
257  throw new ConverterException(ConverterCause.ConverterFunctionDefaultNull, "A default value exists but no conversion function taking a default-value is defined");
258  }
259 
260 
270  public TOut Convert(TIn valueTyped, TOut defaultValueTyped = default(TOut))
271  {
272  return (TOut)this.Convert(value: valueTyped, defaultValue: defaultValueTyped);
273  }
274 
279  protected override void CheckConvertTypes(object value, object defaultValue)
280  {
281  if(value == null)
282  {
283  throw new ConverterException(ConverterCause.ConverterArgumentNull);
284  }
285 
286  if((value is TIn) == false)
287  {
288  throw new ConverterException(ConverterCause.ConverterArgumentWrongType, $"Object is not of the type {this.From.FullName}.");
289  }
290 
291  if(defaultValue != null && this.DefaultValueAnyType == false && (defaultValue is TOut) == false)
292  {
293  throw new ConverterException(ConverterCause.ConverterArgumentWrongType, $"Object is not of the type {this.To.FullName}.");
294  }
295  }
296  }
297 }
Converter(Func< TIn, TOut > converter)
Initializes a new instance of the Converter<TIn, TOut, TArg> class.
Definition: Converter_3T.cs:34
The Exception-type which is raised exclusively by the Converter<TIn,TOut> Library ...
The Base Converter interface.
Definition: IConverter.cs:31
Converter(MethodInfo converterInfo, Type argument=null)
Initializes a new instance of the Converter<TIn, TOut, TArg> class.
Definition: Converter_3T.cs:98
TOut Convert(TIn valueTyped, TOut defaultValueTyped=default(TOut))
The converter function that needs to be overwritten as part of the IConverter interface support...
Converter(Func< TIn, TArg, TOut > converterAny, Type argument=null)
Initializes a new instance of the Converter<TIn, TOut, TArg> class.
Definition: Converter_3T.cs:76
Converter(Func< TIn, TOut, TOut > converterDefault)
Initializes a new instance of the Converter<TIn, TOut, TArg> class.
Definition: Converter_3T.cs:55
override void CheckConvertTypes(object value, object defaultValue)
Checks the types being in the correct source and target format, if not exceptions are thrown...
ConverterCause
Contains the reasons for a ConverterException to be raised.
override object Convert(object value, object defaultValue=null)
The Converter convert function as part of the IConverter interface support.
The Converter base class, providing a simple container for conversion types, ConverterAttribute and c...
Definition: Converter.cs:22