public T GetInstance <T>(ObjectPath path, string interfaceName, string serviceName, out IDBusObjectProxy <T> container) { IClientObjectProvider preferred = null; IClientObjectProvider first = null; foreach (var prov in proxyProviders) { var pref = prov.TypePreference <T>(); if (preferred == null) { if (pref == ProviderPreferences.Preferred) { preferred = prov; break; } } if (first == null && pref != ProviderPreferences.UnableToGet) { first = prov; } } if (preferred == null) { preferred = first; } if (preferred == null) { throw new ArgumentException($"Unable to find proxy provider to create instance for {typeof(T)}"); } return(preferred.GetInstance <T>(path, interfaceName, serviceName, out container)); }
public EndpointsController(ICatalogClientProvider catalogClientProvider, IClientObjectProvider clientObjectProvider, ILookupProvider lookupProvider) { _catalogClientProvider = catalogClientProvider; _clientObjectProvider = clientObjectProvider; _lookupProvider = lookupProvider; }
public static T GetInstance <T>(this IClientObjectProvider provider, ObjectPath path, string interfaceName, string serviceName) { return(provider.GetInstance(path, interfaceName, serviceName, out IDBusObjectProxy <T> _)); }
public object Intercept(IClientObjectProvider parent, MethodInfo method, object[] arguments) { if (signals == null) { if (TypeDescriptor.PropertiesForNames.Count > 0) { propertyGetter = parent.DBusConnection.GetInstance <IProperties>(proxyInfo.ObjectPath, proxyInfo.Service); } signals = TypeDescriptor.Signals.ToDictionary(s => s.Name, s => new SignalEntry()); } object returnValue = null; if (method.Name == nameof(IDisposable.Dispose)) { Dispose(); return(returnValue); } CheckDisposed(); if (method.IsSpecialName) { var methodName = method.Name; bool isGet = methodName.StartsWith("get_", StringComparison.Ordinal); if (isGet || methodName.StartsWith("set_", StringComparison.Ordinal)) { var propName = methodName.Substring(4); if (!TypeDescriptor.PropertiesForNames.TryGetValue(propName, out TypeDescription.PropertyDef propEntry)) { ThrowEx($"Property \"{propName}\" not found. Internal bug!"); } if (isGet) { var getTask = propertyGetter.Get(proxyInfo.InterfaceName, propName); if (propEntry.IsAsync) { returnValue = getTask.CastResultAs(propEntry.Type.Type); } else { getTask.Wait(); returnValue = getTask.Result; } } else // set { var setTask = propertyGetter.Set(proxyInfo.InterfaceName, propName, arguments[0]); setTask.Wait(); } } else { ThrowArgumentEx("Unknown/unexpected special method: " + method.Name); } } else { if (TypeDescriptor.MethodsForInfos.TryGetValue(method, out TypeDescription.MethodDef m)) { try { var transaction = new ProxyTransaction(); TaskCompletionSourceGeneric ret = null; if (m.IsAsync || m.HasReturnValue) { ret = TaskCompletionSourceGeneric.Create(m.HasReturnValue ? m.ReturnType : typeof(bool), transaction); returnValue = ret.Task; } else { returnValue = null; } var reqMsg = new Message(new Header(MessageType.MethodCall) { Path = proxyInfo.ObjectPath, Interface = proxyInfo.InterfaceName, Member = m.Name, Destination = proxyInfo.Service, }); reqMsg.WriteObjs(arguments, m.ArgTypes); parent.DBusConnection.CallMethodAsync(reqMsg, checkConnected: false) .ContinueWith(reply => { if (reply.IsFaulted) { var ex = (reply.Exception.InnerExceptions.Count == 1) ? reply.Exception.InnerExceptions[0] : reply.Exception; if (ex is DBusException dbusEx) { ExceptionHook?.Invoke(dbusEx); } ret.SetException(ex); } else { var replyRes = reply.Result; transaction.RequestSendTime = reply.Result.RequestSendTime; transaction.ReplyReceivedTime = reply.Result.ReplyReceivedTime; Message replyMsg = replyRes; // Check returned signature bool returnSigGood = false; bool wrapInTuple = false; if (m.ReturnSignature == Signature.Empty) { returnSigGood = !replyMsg.Header.Signature.HasValue || (replyMsg.Header.Signature.Value == Signature.Empty); } else if (replyMsg.Header.Signature.HasValue) { var replySig = replyMsg.Header.Signature.Value; returnSigGood = replySig == m.ReturnSignature; if (!returnSigGood) { if (!replySig.IsSingleCompleteType && m.ReturnSignature.IsSingleCompleteType) { // Possibly need to wrap multiple return args in tuple (struct) wrapInTuple = returnSigGood = m.ReturnSignature == Signature.MakeStruct(replySig); } } } if (!returnSigGood) { ret.SetException(new ReplyArgumentsDifferentFromExpectedException(m.MethodInfo, m.ReturnSignature, replyMsg)); } else { if (m.ReturnSignature == Signature.Empty) { ret.SetResult(true); } else { object[] objs; if (wrapInTuple) { objs = replyMsg.GetObjs(m.ReturnType.GenericTypeArguments).ToArray(); // ValueTuple<> individual arguments objs = new object[] { m.ReturnType.GenericTypeArguments.AsValueTupleCreator()(objs) }; } else { objs = replyMsg.GetObjs(new[] { m.ReturnType }).ToArray(); } if (objs.Length == 0) { ret.SetResult(null); } else if (objs.Length == 1) { ret.SetResult(objs[0]); } else { ret.SetResult(objs); } } } } }); if (!m.IsAsync) { ret.Task.Wait(); // Exceptions caught below if (m.HasReturnValue) { returnValue = ret.Task.TryGetAsGenericTask().Result; } } } catch (Exception ex) { bool isAex = false; if (ex is AggregateException aex && aex.InnerExceptions.Count == 1) { isAex = true; ex = aex.InnerExceptions[0]; } if (ex is DBusException dbusEx) { ExceptionHook?.Invoke(dbusEx); } if (m.IsAsync) { returnValue = m.HasReturnValue ? ex.AsGenericTaskException(m.ReturnType) : Task.FromException(ex); } else if (isAex) { throw ex; } else { throw; } } } else { string sigName; if (method.Name.StartsWith("Watch", StringComparison.Ordinal) && ((sigName = method.Name.Substring(5)).Length > 0) && TypeDescriptor.SignalsForNames.TryGetValue(sigName, out TypeDescription.SignalDef s)) { var sigCont = signals[sigName]; var ret = new SigDisposable(); var delArg = (Delegate)arguments[0]; var target = delArg.Target; var cb = delArg.Method.DelegateForMethod(); void CBUnsync(object[] objs, ProxyContext ctx) { if (ret.IsDisposed) { return; } ObjectContext objCtx = target as ObjectContext; objCtx?.SetContext(ctx); try { cb(target, objs); } finally { objCtx?.SetContext(null); } } var syncCtx = SynchronizationContext.Current; var callback = (syncCtx != null) ? new Action <object[], ProxyContext>(((objs, ctx) => syncCtx.Post(_ => CBUnsync(objs, ctx), null))) : CBUnsync; bool doSubscribe = sigCont.Callbacks == null; sigCont.Callbacks += callback; ret.Set(() => { if (sigCont.Callbacks != null) { sigCont.Callbacks -= callback; if (sigCont.Callbacks == null && sigCont.Disposer != null) { sigCont.Disposer(); } } }); if (doSubscribe) { var tcs = new TaskCompletionSource <IDisposable>(); void handler(Message msg) { if (proxyInfo == null) { if (sigCont.Callbacks == null && sigCont.Disposer != null) { sigCont.Disposer(); } return; } bool senderMatches = string.IsNullOrEmpty(msg.Header.Sender) || string.IsNullOrEmpty(proxyInfo.Service) || (proxyInfo.Service[0] != ':' && msg.Header.Sender[0] == ':') || proxyInfo.Service == msg.Header.Sender; if (!senderMatches) { return; } if (sigCont.Callbacks != null) { var objs = (s.ArgTypes.Length > 0) ? msg.GetObjs(s.ArgTypes) : Enumerable.Empty <object>(); if (s.LastParamIsPath) { objs = objs.Concat(new object[] { msg.Header.Path ?? ObjectPath.Root }); } sigCont.Callbacks(s.ArgsAreInTuple ? new object[] { s.ArgTypes.AsValueTupleCreator()(objs.ToArray()) } : objs.ToArray(), new ProxyContext(parent.Connection, msg.Header.Path, msg)); } } try { parent.DBusConnection.WatchSignalAsync(handler, proxyInfo.InterfaceName, s.Name, proxyInfo.Service, proxyInfo.ObjectPath) .ContinueWith(t => { if (t.IsFaulted) { try { ret.Dispose(); } catch { } var ex = (t.Exception.InnerExceptions.Count == 1) ? t.Exception.InnerException : t.Exception; if (ex is DBusException dbusEx) { ExceptionHook?.Invoke(dbusEx); } tcs.SetException(ex); } else { var res = t.Result; sigCont.Disposer = () => res.Dispose(); tcs.SetResult(ret); } }); } catch (Exception ex) { if (ex is DBusException dbusEx) { ExceptionHook?.Invoke(dbusEx); } tcs.SetException(ex); } returnValue = tcs.Task; } else { returnValue = Task.FromResult <IDisposable>(ret); } } else { ThrowEx($"Method \"{method.Name}\" not found. Internal bug!"); } } } return(returnValue); }