//private static Type GetCodeGeneratorTypeForAttribute(this INamedTypeSymbol attributeType, AttributeAssemblyLoaderCallback loader) private static Type GetCodeGeneratorTypeForAttribute <TSymbol>(this TSymbol attributeType, LoadAssemblyCallback loader) where TSymbol : ISymbol { Requires.NotNull(loader, nameof(loader)); Type LoadGeneratorTypeFromAssembly(string fullTypeName, string assemblyName) { var generatorType = assemblyName != null ? loader(new AssemblyName(assemblyName))?.GetType(fullTypeName) : null; if (generatorType == null) { Verify.FailOperation($"Unable to find code generator `{fullTypeName}´ in `{assemblyName}´."); } return(generatorType); } // ReSharper disable once InvertIf if (attributeType != null) { var codeGenerationAttributeType = typeof(CodeGenerationAttributeAttribute); foreach (var generatorCandidateAttribute in attributeType.GetAttributes() .Where(x => x.AttributeClass.Name == codeGenerationAttributeType.Name)) { var firstArg = generatorCandidateAttribute.ConstructorArguments.Single(); switch (firstArg.Value) { case INamedTypeSymbol typeOfValue: // This was a typeof(T) expression return(LoadGeneratorTypeFromAssembly( typeOfValue.GetFullTypeName() , typeOfValue.ContainingAssembly.Name)); case string typeName: // This string is the full name of the type, which MAY be assembly-qualified. var commaIndex = typeName.IndexOf(Comma); var isAssemblyQualified = commaIndex >= 0; if (isAssemblyQualified) { return(LoadGeneratorTypeFromAssembly( typeName.Substring(0, commaIndex) , typeName.Substring(commaIndex + 1).Trim())); } else { return(LoadGeneratorTypeFromAssembly( typeName , generatorCandidateAttribute.AttributeClass.ContainingAssembly.Name)); } } } } // Nothing found, but should short-circuit, i.e. "fail", i.e. throw, before reaching this moment. return(null); }
public static IEnumerable <TGenerator> LoadCodeGenerators <TGenerator>(this ImmutableArray <AttributeData> attributeData, LoadAssemblyCallback loader) where TGenerator : class, ICodeGenerator { Requires.NotNull(loader, nameof(loader)); TGenerator CreateCodeGenerator(GeneratorTuple tuple) { var(generatorType, datum) = tuple; var generator = Activator.CreateInstance(generatorType, datum); Requires.NotNull(generator, nameof(generator)); // TODO: TBD: might be better if .Is<T> actually returned T... i.e. could simple `return Assumes.Is<ICodeGenerator>(generator);´ Assumes.Is <TGenerator>(generator); return((TGenerator)generator); } return(attributeData .Select(x => GeneratorTuple.Create(x.AttributeClass.GetCodeGeneratorTypeForAttribute(loader), x)) .Where(tuple => tuple.GeneratorType != null).Select(CreateCodeGenerator)); }