public static T CreateProxy <T>(this HubConnection connection) { var impl = new Implementer <T>(); bool isIProxy = typeof(IProxy).IsAssignableFrom(typeof(T)); if (isIProxy) { impl.Member(o => ((IProxy)o).Connection).Returns(connection); } foreach (var method in impl.Methods.Where(o => (typeof(T).IsInterface || o.IsVirtual) && !o.IsSpecialName && o.IsPublic && typeof(Task).IsAssignableFrom(o.ReturnType))) { var invokeMethod = ResolveInvokeMethod(method); int invokeMethodParamCount = invokeMethod.GetParameters().Length; impl.Member <object>(method).Callback(args => { var invokeArgs = new object[invokeMethodParamCount]; invokeArgs[0] = connection; invokeArgs[1] = method.Name; for (int i = 0; i < args.Count; i++) { invokeArgs[i + 2] = args.Values.ElementAt(i); } return(invokeMethod.Invoke(null, invokeArgs)); }); } return(impl.Finish()); }
internal static TData GenerateDataObject(object dataObject) { if (!typeof(TData).IsInterface) { throw new Exception($"{nameof(TData)} must be an interface type"); } if (ImplDataCache == null) { var impl = new Implementer <TData>(dataObject.GetType()); foreach (var prop in impl.Properties) { if (prop.GetMethod != null) { impl.Getter(prop).Callback(o => { var file = o["__data"] as ReadableDataFile; return(file.GetNonGeneric( type: prop.PropertyType, key: prop.Name )); }); } if (prop.SetMethod != null) { impl.Setter(prop, (value, data) => { var file = (ReadableWritableDataFile)data; file?.SetNonGeneric( type: prop.PropertyType, key: prop.Name, value); }); } } ImplDataCache = impl.Finish(); } return(ClassUtils.Copy(ImplDataCache, dataObject)); }
/// <summary> /// Creates a proxy type for this queue. If <typeparamref name="T"/> is an interface, every method /// will be overriden to call <see cref="Call(string, Type, object[])"/>. If it isn't an interface, /// all of its virtual or abstract methods will be overriden instead. /// </summary> /// <typeparam name="T">The type of the proxy to create</typeparam> public T CreateProxy <T>() { CheckDisposed(); var impl = new Implementer <T>(); foreach (var item in impl.Methods.Where(o => o.DeclaringType == typeof(T))) { var returnType = item.ReturnType; if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task <>)) { returnType = returnType.GenericTypeArguments[0]; } impl.Member(item).Callback(args => { if (typeof(Task).IsAssignableFrom(item.ReturnType)) { var callMethod = this .GetType() #if NETSTANDARD2_1 || NETCOREAPP3_0 .GetMethod("Call", 1, new[] { typeof(string), typeof(object[]) }) #else .GetMethods() .Single(o => o.ContainsGenericParameters && o .GetParameters() .Select(o => o.ParameterType) .SequenceEqual(new[] { typeof(string), typeof(object[]) })) #endif .MakeGenericMethod(returnType); return(callMethod.Invoke(this, new object[] { item.Name, args.Values.ToArray() })); } else { return(Call(item.Name, returnType, args.Values.ToArray()).Result); } }); } return(impl.Finish()); }