public static DevicePayload Create <T>(T device) where T : Device { var payload = new DevicePayload(); payload.Properties = Serializer.Serialize(device); payload.Allowed = device.Allowed; payload.Transitions = device.Transitions; payload.Prepare = async(dynamic input) => { return(await Task.Run(async() => { await device.Prepare(); return Create(device); })); }; payload.SetCreateReadStream = async(dynamic input) => { var func = (Func <object, Task <object> >)input.fn; device.SetCreateReadStreamFunction(async(name) => { var stream = new ObjectStream(); Func <object, Task <object> > onDataFn = async(data) => { stream.Publish((string)data); return(await Task.FromResult(0)); }; var fnInput = new { name = name, onData = onDataFn }; await func.Invoke(fnInput); return(stream); }); return(await Task.FromResult(0)); }; payload.SetAvailableFunction = async(dynamic input) => { var func = (Func <object, Task <object> >)input.fn; device.SetAvailableFunction(async(transition) => { return((bool)await func.Invoke(new { transition = transition })); }); return(await Task.FromResult(0)); }; payload.SetCallFunction = async(dynamic input) => { var func = (Func <object, Task <object> >)input.fn; device.SetCallFunction(async(transition) => { try { //Console.WriteLine("Invoking transition: {0}", transition); await func.Invoke(new { transition = transition }); } catch (Exception ex) { if (ex.Message.StartsWith("Error: Machine cannot use transition")) { throw new InvalidOperationException(ex.Message); } } }); return(await Task.FromResult(0)); }; var type = typeof(T); if (!_monitorsCache.ContainsKey(type)) { _monitorsCache[type] = type.GetProperties().Where((info) => { return(info.GetCustomAttributes(true) .Where((attribute) => attribute is MonitorAttribute).Any()); }).Select((info) => info.Name) .Select((name) => Serializer.Resolver.GetResolvedPropertyName(name)).ToList(); } payload.Monitors = _monitorsCache[type]; return(payload); }