using System.Runtime.CompilerServices;
using System.Globalization;
public static void Main(string[] args)
var test1 = Transfer<(int? Result, string? Error)>(new () { Result = "10101", Error = null });
var test2 = Transfer<(bool? Result, string? Error)>(new () { Result = "true", Error = null });
var test3 = Transfer<(object? Result, string? Error)>(new () { Result = "Hello", Error = null });
var test4 = Transfer<Tuple<string, string>>(new () { Result = "Hello", Error = null });
Assert.AreEqual(test1.Result, 10101);
Assert.AreEqual(test2.Result, true);
Assert.AreEqual(test3.Result, "Hello");
Assert.Throws<ArgumentException>(() => Transfer<(object? Result, string? Error, string? dummy)>(new () { Result = "Hello", Error = null }));
public static U Transfer<U>(MessageBundle bundle)
if (!typeof(ITuple).IsAssignableFrom(typeof(U))
|| !(typeof(U).IsGenericType && typeof(U).GetGenericArguments() is var arguments && arguments.Length == 2)
|| arguments[1] != typeof(string))
throw new ArgumentException(string.Format("Unexpected type {0}", typeof(U)));
var tuple = (U)Activator.CreateInstance(typeof(U),
bundle.Result == null ? null : Convert.ChangeType(bundle.Result, Nullable.GetUnderlyingType(arguments[0]) ?? arguments[0]),
public class MessageBundle
public string? Error { get; set; }
public object? Result { get; set; }