public LambdaExpression CreateLambda(Type from, Type to)
{
var toParameters = to.GetTypeInfo().GenericTypeArguments;
var tupa = toParameters.Length;
var input = Ex.Parameter(from, "input");
var converters = toParameters.Select(p => Ref.GetLambda(typeof(string), p)).ToArray();
var res = toParameters.Select(p => Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(p))).ToArray();
var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end");
var indexer = typeof(string[]).GetTypeInfo().GetDeclaredProperty("Item");
var split = Ex.Parameter(typeof(string[]), "split");
var conversion = Ex.Block(converters.Select((c, i) =>
Ex.Block(
Ex.Assign(res[i],
c.ApplyTo(Ex.MakeIndex(split, indexer, new[] { Ex.MakeBinary(Et.Add, Ex.Constant(i), Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))) }))),
Ex.IfThen(Ex.Not(Ex.Property(res[i], nameof(IConversionResult.IsSuccessful))),
Ex.Goto(end, NoResult(to))))));
var block = Ex.Block(new[] { split },
Ex.Assign(split, Ex.Call(input, nameof(string.Split), Type.EmptyTypes, _separator)),
Ex.Condition(Ex.MakeBinary(Et.LessThan, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa)),
NoResult(to),
Ex.Block(res,
Ex.IfThen(Ex.MakeBinary(Et.GreaterThan, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa)),
Ex.Assign(Ex.ArrayAccess(split, Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))),
Ex.Call(typeof(string), nameof(string.Join), Type.EmptyTypes, _separatorString,
Ex.Call(typeof(Enumerable), nameof(Enumerable.Take), new[] { typeof(string) }, split,
Ex.MakeBinary(Et.Add, Ex.Constant(1), Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))))))),
conversion,
Ex.Label(end, Result(to, Ex.Call(Creator(to), res.Select(r => Ex.Property(r, nameof(IConversionResult.Result)))))))));
var lambda = Ex.Lambda(block, input);
return(lambda);
}