internal static IGraphClient SharedWithAnnotations <TContext, TResolver, TConverter>
            (this IGraphClient graphClient, EntityService entityService, out TContext context, bool useConverter)
            where TContext : AnnotationsContext
            where TResolver : EntityResolver, new()
            where TConverter : EntityConverter, new()
        {
            if (graphClient == null)
            {
                throw new ArgumentNullException(nameof(graphClient));
            }

            context = graphClient.GetAnnotationsContext() as TContext;

            if (context != null &&
                (!useConverter
                    ? context.EntityResolver?.GetType() == typeof(TResolver)
                    : context.EntityConverter?.GetType() == typeof(TConverter)) &&
                (entityService == null || context.EntityService.GetType() == entityService.GetType()))
            {
                //already attached
                return(graphClient);
            }

            TResolver  resolver  = null;
            TConverter converter = null;

            if (!useConverter)
            {
                resolver = new TResolver();
            }
            else
            {
                converter = new TConverter();
            }

            var resolverConverterObj = resolver ?? (object)converter;

            //find best constructor
            var parameters = new[] { graphClient, resolverConverterObj, entityService }.Where(p => p != null).ToArray();

            var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

            var orderedConstructors = typeof(TContext).GetConstructors(flags)
                                      .OrderByDescending(c => c.GetParameters().Length)
                                      .Select(c => new
            {
                ctor        = c,
                validParams = c.GetParameters().Select(p => parameters.FirstOrDefault
                                                           (ip => p.ParameterType.IsAssignableFrom(ip.GetType())))
                              .ToArray()
            })
                                      .OrderBy(nc => nc.validParams.Count(p => p == null))
                                      .ToArray();

            if (orderedConstructors?.Length > 0)
            {
                //find a constructor willing to create a valid instance with the available parameters
                foreach (var octor in orderedConstructors)
                {
                    try
                    {
                        context = octor.ctor.Invoke(octor.validParams) as TContext;
                        break;
                    }
                    catch
                    {
                    }
                }
            }

            if (context == null)
            {
                throw new InvalidOperationException(string.Format(Messages.NoValidConstructorError,
                                                                  typeof(TContext).Name));
            }

            return(graphClient);
        }