예제 #1
0
        public static bool TryCreate
        (
            GeneratorContext context,
            MemberAccessExpressionSyntax expressionSyntax,
            ITypeSymbol interfaceType,
            ITypeSymbol implementationType,
            string mode,
            [NotNullWhen(true)] out MemoizerCall?call)
        {
            var interfaceAttributes = interfaceType.GetAttributes();

            if (!context.TryGetInterfaceContext(interfaceType, out var interfaceContext))
            {
                // The Interface could exist in a referenced project which we dont have the interfacesyntax for.. lets check that
                var memoizeAttribute2 = interfaceAttributes.FirstOrDefault(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, context.CreateMemoizedAttribute));

                if (memoizeAttribute2 == null)
                {
                    context.CreateError("Missing Memoized Attribute", "Interface must have the [CreateMemoizedImplementation] attribute attached", expressionSyntax.Name.GetLocation());
                    call = null;
                    return(false);
                }

                interfaceContext = CreateMemoizeInterfaceContext.CreateFromType(interfaceType, memoizeAttribute2, expressionSyntax.GetLocation());
            }

            var memoizeAttribute = interfaceContext.CreateMemoizedAttributeData;

            if (!TryGetClassName(memoizeAttribute, interfaceType, out var className, out var humanId))
            {
                call = null;
                return(false);
            }

            var memoizerFactory = memoizeAttribute.NamedArguments.FirstOrDefault(x => x.Key == nameof(CreateMemoizedImplementationAttribute.MemoizerFactory)).Value;
            INamedTypeSymbol?memoizerFactoryTypeSymbol = null;

            if (!memoizerFactory.IsNull)
            {
                memoizerFactoryTypeSymbol = memoizerFactory.Value as INamedTypeSymbol;
            }

            if (memoizerFactoryTypeSymbol != null)
            {
                if (!memoizerFactoryTypeSymbol.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, context.MemoizerFactoryInterface)))
                {
                    context.CreateError($"Wrong {nameof(CreateMemoizedImplementationAttribute.MemoizerFactory)} type", $"MemoizerFactory type must implement {nameof(IMemoizerFactory)}", interfaceContext.InterfaceWithAttribute?.GetLocation() ?? expressionSyntax.Name.GetLocation());
                    call = null;
                    return(false);
                }
            }

            var slidingCache = SlidingCache.MaybeCreate(context, interfaceAttributes);

            var members       = interfaceType.GetMembers();
            var methods       = new List <MemoizedMethodMember>(members.Length);
            var methodSymbols = members.OfType <IMethodSymbol>().ToList();

            // TODO Create different ArgKey class name implementations
            // then Check names to see what ArgKey_ class name algo we can use

            foreach (var interfaceMethod in methodSymbols)
            {
                if (MemoizedMethodMember.TryCreate(context, interfaceContext, interfaceMethod, out var methodMember))
                {
                    methods.Add(methodMember);
                }
                else
                {
                    call = null;
                    return(false);
                }
            }

            var @namespace = GetNamespaceFrom(expressionSyntax);

            call = new MemoizerCall(interfaceType, implementationType, className, methods, slidingCache, memoizerFactoryTypeSymbol, humanId, @namespace, mode);

            return(true);
        }