public void ClientCodeGenerationDispatcher_Throws_Exception_Fully_Qualified_Name() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#", ClientProjectPath = "SampleProject.csproj" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { // Disable MEF for this test string[] compositionAssemblies = new string[0]; // And use FQN instead string codeGeneratorName = typeof(MockCodeGenerator).AssemblyQualifiedName; // Ask our mock to throw MockCodeGenerator.ThrowException = true; dispatcher.GenerateCode(host, options, Enumerable.Empty <Type>(), compositionAssemblies, codeGeneratorName); string error = string.Format(CultureInfo.CurrentCulture, Resource.CodeGenerator_Threw_Exception, codeGeneratorName, options.ClientProjectPath, MockCodeGenerator.Exception.Message); TestHelper.AssertContainsErrors(logger, error); } }
public void ClientCodeGenerationDispatcher_Custom_By_AssemblyQualifiedName() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[0]; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, typeof(T4DomainServiceClientCodeGenerator).AssemblyQualifiedName); Assert.IsNotNull(generator, "the dispatcher did not find the code generator"); Assert.AreEqual(generator.GetType(), typeof(T4DomainServiceClientCodeGenerator), "dispatcher found " + generator.GetType() + " but should have found T4DomainServiceClientProxyGenerator"); string generatedCode = generator.GenerateCode(host, Enumerable.Empty <DomainServiceDescription>(), options); Assert.IsFalse(string.IsNullOrEmpty(generatedCode), "expected T4 generator to generate code"); TestHelper.AssertGeneratedCodeContains(generatedCode, T4DomainServiceClientCodeGenerator.GeneratedBoilerPlate); TestHelper.AssertNoErrorsOrWarnings(logger); } }
public void ClientCodeGenerationDispatcher_Custom_Warns_Full() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, MockCodeGenerator.GeneratorName); Assert.IsNotNull(generator, "the dispatcher did not find any code generator"); Assert.AreEqual(generator.GetType(), typeof(MockCodeGenerator), "dispatcher found " + generator.GetType() + " but should have found MockCodeGenerator"); // Setting this option makes our custom code generator emit the packet below to test LogWarning MockCodeGenerator.LogWarningsFull = true; string generatedCode = generator.GenerateCode(host, Enumerable.Empty <DomainServiceDescription>(), options); Assert.AreEqual(MockCodeGenerator.FakeGeneratedCode, generatedCode, "test code generator did not generate expected code."); TestHelper.AssertContainsWarningPackets(logger, MockCodeGenerator.WarningPacket); } }
public void ClientCodeGenerationDispatcher_Finds_Derived_Custom() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "G#" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, MockGSharpCodeGeneratorDerived.GeneratorName); Assert.IsNotNull(generator, "the dispatcher did not find any code generator"); Assert.AreEqual(generator.GetType(), typeof(MockGSharpCodeGeneratorDerived), "dispatcher found " + generator.GetType() + " but should have found MockGSharpCodeGeneratorDerived"); string generatedCode = generator.GenerateCode(host, Enumerable.Empty <DomainServiceDescription>(), options); Assert.AreEqual(MockGSharpCodeGeneratorDerived.DerivedGeneratedCode, generatedCode, "test code generator did not generate expected code."); } }
/// <summary> /// This method is part of the <see cref="IDomainServiceClientCodeGenerator" /> interface. The RIA Services Code Generation process uses this method as the entry point into the code generator. /// </summary> /// <param name="codeGenerationHost">The code generation host for this instance.</param> /// <param name="domainServiceDescriptions">The list of all the DomainServiceDescription objects.</param> /// <param name="options">The code generation objects.</param> /// <returns>The generated code.</returns> public string GenerateCode(ICodeGenerationHost codeGenerationHost, IEnumerable <DomainServiceDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { this._codeGenerationHost = codeGenerationHost; this._domainServiceDescriptions = domainServiceDescriptions; this._options = options; this._enumTypesToGenerate = new HashSet <Type>(); if (this.EntityGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.EntityGeneratorNotFound)); } if (this.ComplexObjectGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.ComplexObjectGeneratorNotFound)); } if (this.DomainContextGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.DomainContextGeneratorNotFound)); } if (this.WebContextGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.WebContextGeneratorNotFound)); } if (this.EnumGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.EnumGeneratorNotFound)); } if (!this.CodeGenerationHost.HasLoggedErrors) { return(this.GenerateCode()); } return(null); }
internal static string GenerateCode(string language, IEnumerable <Type> entityTypes, ILoggingService logger, ISharedCodeService typeService) { ClientCodeGenerationOptions options = CreateMockCodeGenContext(language, false); ICodeGenerationHost host = CreateMockCodeGenerationHost(logger, typeService); return(GenerateCode(host, options, entityTypes)); }
public void ClientCodeGenerationDispatcher_Generate_Using_T4_Custom() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { typeof(T4DomainServiceClientCodeGenerator).Assembly.Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, null); Assert.IsNotNull(generator, "the dispatcher did not find any code generator"); Assert.AreEqual(generator.GetType(), typeof(T4DomainServiceClientCodeGenerator), "dispatcher found " + generator.GetType() + " but should have found T4DomainServiceClientProxyGenerator"); DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(DispatcherDomainService)); string generatedCode = generator.GenerateCode(host, new DomainServiceDescription[] { dsd }, options); Assert.IsFalse(string.IsNullOrEmpty(generatedCode), "expected T4 generator to generate code"); TestHelper.AssertGeneratedCodeContains(generatedCode, T4DomainServiceClientCodeGenerator.GeneratedBoilerPlate); TestHelper.AssertGeneratedCodeContains(generatedCode, "public class DispatcherEntity : Entity"); TestHelper.AssertNoErrorsOrWarnings(logger); } }
internal static string GenerateCode(string language, Type entityType, ILoggingService logger) { ClientCodeGenerationOptions options = CreateMockCodeGenContext(language, false); ICodeGenerationHost host = CreateMockCodeGenerationHost(logger, null); return(GenerateCode(host, options, new Type[] { entityType })); }
public void ClientCodeGenerationDispatcher_Finds_Solitary_Custom() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location, typeof(TextTemplate::OpenRiaServices.DomainServices.Tools.TextTemplate.ClientCodeGenerator).Assembly.Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, /*generatorName*/ null); Assert.IsNotNull(generator, "the dispatcher did not find any code generator"); Assert.AreEqual(generator.GetType(), typeof(MockCodeGenerator), "dispatcher found " + generator.GetType() + " but should have found MockCodeGenerator"); string generatedCode = generator.GenerateCode(host, Enumerable.Empty <DomainServiceDescription>(), options); Assert.AreEqual(MockCodeGenerator.FakeGeneratedCode, generatedCode, "test code generator did not generate expected code."); // Expect informational message string message = string.Format(CultureInfo.CurrentCulture, Resource.Using_Custom_Code_Generator, MockCodeGenerator.GeneratorName); TestHelper.AssertContainsMessages(logger, message); } }
public void ClientCodeGenerationDispatcher_Finds_Default_By_Name() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location, typeof(T4DomainServiceClientCodeGenerator).Assembly.Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, CodeDomClientCodeGenerator.GeneratorName); Assert.IsNotNull(generator, "the dispatcher did not find any code generator"); Assert.IsTrue(typeof(CodeDomClientCodeGenerator).IsAssignableFrom(generator.GetType()), "dispatcher found " + generator.GetType() + " but should have found CodeDomClientCodeGenerator"); DomainServiceDescription dsd = DomainServiceDescription.GetDescription(typeof(DispatcherDomainService)); string generatedCode = generator.GenerateCode(host, new DomainServiceDescription[] { dsd }, options); Assert.IsFalse(string.IsNullOrEmpty(generatedCode), "expected code to have been generated"); Assert.IsTrue(generatedCode.Contains("public sealed partial class DispatcherDomainContext : DomainContext"), "Expected generated code to contain public sealed partial class DispatcherDomainContext : DomainContext"); } }
// Invokes the code generator discovered via the host and options internal static string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <Type> domainServiceTypes) { IDomainServiceClientCodeGenerator generator = CreateCodeGenerator(host, options); DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, host as ILogger); return(generator.GenerateCode(host, catalog.DomainServiceDescriptions, options)); }
public void ClientCodeGenerationDispatcher_Error_Missing_Custom() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#", ClientProjectPath = "ClientProject", ServerProjectPath = "ServerProject" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, "NotAGenerator"); Assert.IsNull(generator, "the dispatcher should not find any code generator"); string error = string.Format(CultureInfo.CurrentCulture, Resource.Code_Generator_Not_Found, "NotAGenerator", options.Language, options.ServerProjectPath, options.ClientProjectPath, CodeDomClientCodeGenerator.GeneratorName); TestHelper.AssertContainsErrors(logger, error); } }
// Invokes the code generator discovered via the host and options internal static string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <Type> entityTypes) { IClientCodeGenerator generator = CreateCodeGenerator(host, options); EntityCatalog catalog = new EntityCatalog(entityTypes, host as ILogger); return(generator.GenerateCode(host, catalog.EntityDescriptions, options)); }
public void ClientCodeGenerationDispatcher_Error_Multiple_Generators() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#", ClientProjectPath = "ClientProject" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location, typeof(T4DomainServiceClientCodeGenerator).Assembly.Location }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, /*generatorName*/ null); Assert.IsNotNull(generator, "the dispatcher did not pick a generator"); Assert.IsTrue(generator is CodeDomClientCodeGenerator, "the dispatcher did not pick the default code generator"); string errorParam = " " + MockCodeGenerator.GeneratorName + Environment.NewLine + " " + T4DomainServiceClientCodeGenerator.GeneratorName + Environment.NewLine; string error = (string.Format(CultureInfo.CurrentCulture, Resource.Multiple_Custom_Code_Generators_Using_Default, options.Language, errorParam, options.ClientProjectPath, MockCodeGenerator.GeneratorName, CodeDomClientCodeGenerator.GeneratorName)); TestHelper.AssertContainsWarnings(logger, error); } }
public void ClientCodeGenerationDispatcher_Throws_Exception_Logical_Name() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#", ClientProjectPath = "SampleProject.csproj" }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { string[] compositionAssemblies = new string[] { Assembly.GetExecutingAssembly().Location }; string codeGeneratorName = MockCodeGenerator.GeneratorName; // Ask our mock to throw MockCodeGenerator.ThrowException = true; dispatcher.GenerateCode(host, options, Enumerable.Empty <Type>(), compositionAssemblies, codeGeneratorName); string error = string.Format(CultureInfo.CurrentCulture, Resource.CodeGenerator_Threw_Exception, codeGeneratorName, options.ClientProjectPath, MockCodeGenerator.Exception.Message); TestHelper.AssertContainsErrors(logger, error); } }
// Locates the code generator registered to work with the language for the given options internal static IClientCodeGenerator CreateCodeGenerator(ICodeGenerationHost host, ClientCodeGenerationOptions options) { using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { IClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, /*compositionAssemblies*/ null, /*codeGeneratorName*/ null); return(generator); } }
public string GenerateCode(ICodeGenerationHost host, IEnumerable<OpenRiaServices.DomainServices.Server.DomainServiceDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { this._codeGenerationHost = host; this._options = options; this._domainServiceDescriptions = domainServiceDescriptions.ToList(); return this.TransformText(); }
public string GenerateCode(ICodeGenerationHost host, IEnumerable <EntityDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { this._codeGenerationHost = host; this._options = options; this._domainServiceDescriptions = domainServiceDescriptions.ToList(); return(this.TransformText()); }
internal static void GenerateCodeAssertFailure(string language, IEnumerable <Type> domainServiceTypes, params string[] errors) { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = CreateMockCodeGenContext(language, false); ICodeGenerationHost host = CreateMockCodeGenerationHost(logger, null); string generatedCode = GenerateCode(host, options, domainServiceTypes); TestHelper.AssertCodeGenFailure(generatedCode, logger, errors); }
internal static string GenerateCodeAssertSuccess(string language, IEnumerable <Type> entityTypes, ConsoleLogger logger, ISharedCodeService typeService, bool useFullNames) { ClientCodeGenerationOptions options = CreateMockCodeGenContext(language, useFullNames); ICodeGenerationHost host = CreateMockCodeGenerationHost(logger, typeService); string generatedCode = GenerateCode(host, options, entityTypes); TestHelper.AssertCodeGenSuccess(generatedCode, ((MockCodeGenerationHost)host).LoggingService as ConsoleLogger); return(generatedCode); }
public void ClientCodeGenerationDispatcher_Null_Language_Throws() { ClientCodeGenerationOptions options = new ClientCodeGenerationOptions(); ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(null, null); ExceptionHelper.ExpectArgumentException(() => { new ClientCodeGenerationDispatcher().FindCodeGenerator(host, options, /*compositionAssemblies*/ null, /*codeGeneratorName*/ null); }, Resource.Null_Language_Property, "options"); }
internal static string GenerateCodeAssertSuccess(string language, Type entityType) { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = CreateMockCodeGenContext(language, false); ICodeGenerationHost host = CreateMockCodeGenerationHost(logger, null); string generatedCode = GenerateCode(host, options, new Type[] { entityType }); TestHelper.AssertCodeGenSuccess(generatedCode, logger); return(generatedCode); }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="entityTypes">The set of <see cref="Luma.Client.Entity"/> types for which to generate code.</param> /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> public string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <Type> entityTypes, IEnumerable <string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(entityTypes != null, "entityTypes cannot be null"); ILogger logger = host as ILogger; var catalog = new EntityCatalog(entityTypes, logger); return(this.GenerateCode(host, options, catalog, compositionAssemblies, codeGeneratorName)); }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="domainServiceTypes">The set of <see cref="OpenRiaServices.DomainServices.Server.DomainService"/> types for which to generate code.</param> /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> internal string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <Type> domainServiceTypes, IEnumerable <string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(domainServiceTypes != null, "domainServiceTypes cannot be null"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, logger); return(this.GenerateCode(host, options, catalog, compositionAssemblies, codeGeneratorName)); }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="assembliesToLoad">The set of server assemblies to use for analysis and composition.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> internal string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable <string> assembliesToLoad, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(assembliesToLoad != null, "assembliesToLoad cannot be null"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(assembliesToLoad, logger); return(this.GenerateCode(host, options, catalog, assembliesToLoad, codeGeneratorName)); }
internal static string GenerateCodeAssertWarnings(string language, Type domainServiceType, params string[] warnings) { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = CreateMockCodeGenContext(language, false); ICodeGenerationHost host = CreateMockCodeGenerationHost(logger, null); string generatedCode = GenerateCode(host, options, new Type[] { domainServiceType }); TestHelper.AssertContainsWarnings(logger, warnings); Assert.IsFalse(string.IsNullOrEmpty(generatedCode), "Expected code to generate with warnings"); return(generatedCode); }
public string GenerateCode(ICodeGenerationHost host, IEnumerable <DomainServiceDescription> descriptions, ClientCodeGenerationOptions options) { try { // Initialize all instance state this.Initialize(host, descriptions, options); // Generate the code return(this.GenerateProxyClass()); } finally { // Dispose and release all instance state this.Cleanup(); } }
public string GenerateCode(ICodeGenerationHost host, IEnumerable<DomainServiceDescription> descriptions, ClientCodeGenerationOptions options) { try { // Initialize all instance state this.Initialize(host, descriptions, options); // Generate the code return this.GenerateProxyClass(); } finally { // Dispose and release all instance state this.Cleanup(); } }
internal void Initialize(ICodeGenerationHost host, IEnumerable <DomainServiceDescription> descriptions, ClientCodeGenerationOptions options) { if (host == null) { throw new ArgumentNullException(nameof(host)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } if (descriptions == null) { throw new ArgumentNullException(nameof(descriptions)); } // Initialize all the instance variables this._host = host; this._clientProxyCodeGenerationOptions = options; this._domainServiceDescriptions = descriptions.ToList(); this._compileUnit = new CodeCompileUnit(); this._namespaces = new Dictionary <string, CodeNamespace>(); this._enumTypesToGenerate = new HashSet <Type>(); CodeDomClientCodeGenerator.ValidateOptions(this._clientProxyCodeGenerationOptions); // Unconditionally initialize some options CodeGeneratorOptions cgo = new CodeGeneratorOptions(); cgo.IndentString = " "; cgo.VerbatimOrder = false; cgo.BlankLinesBetweenMembers = true; cgo.BracingStyle = "C"; this._options = cgo; // Choose the provider for the language. C# is the default if unspecified. string language = this.ClientProxyCodeGenerationOptions.Language; bool isCSharp = String.IsNullOrEmpty(language) || String.Equals(language, "C#", StringComparison.OrdinalIgnoreCase); this._provider = isCSharp ? (CodeDomProvider) new CSharpCodeProvider() : (CodeDomProvider) new VBCodeProvider(); // Configure our code gen utility package CodeGenUtilities.Initialize(!this.IsCSharp, this.ClientProxyCodeGenerationOptions.UseFullTypeNames, this.ClientProxyCodeGenerationOptions.ClientRootNamespace); }
public void ClientCodeGenerationDispatcher_Error_TypeLoadException() { ConsoleLogger logger = new ConsoleLogger(); ClientCodeGenerationOptions options = new ClientCodeGenerationOptions() { Language = "C#", }; ICodeGenerationHost host = TestHelper.CreateMockCodeGenerationHost(logger, /*sharedTypeService*/ null); // Create a new dispatcher and call an internal extensibility point to add ourselves // into the MEF composition container using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { // We want to include into the MEF container an assembly that will throw TypeLoadException // when MEF tries to analyze it. This is to test our own recovery, which should consist // of logging an error making a default container containing only Tools. string unitTestAssemblyLocation = Assembly.GetExecutingAssembly().Location; string typeLoadExceptionProjectLocation = Path.Combine(Path.GetDirectoryName(unitTestAssemblyLocation), "TypeLoadExceptionProject.dll"); Assert.IsTrue(File.Exists(typeLoadExceptionProjectLocation), "Expected TypeLoadExceptionProject.dll to coreside with this assembly in test folder"); // Do what MEF does to load the types so we can capture the exception Exception expectedException = null; try { Assembly assembly = Assembly.LoadFrom(typeLoadExceptionProjectLocation); assembly.GetTypes(); } catch (Exception ex) { expectedException = ex; } Assert.IsNotNull(expectedException, "We did not generate the type load exception we expected"); string[] compositionAssemblies = new string[] { unitTestAssemblyLocation, typeLoadExceptionProjectLocation }; IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, compositionAssemblies, /*generatorName*/ null); Assert.IsNotNull(generator, "the dispatcher did not pick default generator"); Assert.IsTrue(generator is CodeDomClientCodeGenerator, "the dispatcher did not pick the default code generator"); string error = (string.Format(CultureInfo.CurrentCulture, Resource.Failed_To_Create_Composition_Container, expectedException.Message)); TestHelper.AssertContainsWarnings(logger, error); } }
internal void Initialize(ICodeGenerationHost host, IEnumerable<DomainServiceDescription> descriptions, ClientCodeGenerationOptions options) { if (host == null) { throw new ArgumentNullException("host"); } if (options == null) { throw new ArgumentNullException("options"); } if (descriptions == null) { throw new ArgumentNullException("descriptions"); } // Initialize all the instance variables this._host = host; this._clientProxyCodeGenerationOptions = options; this._domainServiceDescriptions = descriptions.ToList(); this._compileUnit = new CodeCompileUnit(); this._namespaces = new Dictionary<string, CodeNamespace>(); this._enumTypesToGenerate = new HashSet<Type>(); CodeDomClientCodeGenerator.ValidateOptions(this._clientProxyCodeGenerationOptions); // Unconditionally initialize some options CodeGeneratorOptions cgo = new CodeGeneratorOptions(); cgo.IndentString = " "; cgo.VerbatimOrder = false; cgo.BlankLinesBetweenMembers = true; cgo.BracingStyle = "C"; this._options = cgo; // Choose the provider for the language. C# is the default if unspecified. string language = this.ClientProxyCodeGenerationOptions.Language; bool isCSharp = String.IsNullOrEmpty(language) || String.Equals(language, "C#", StringComparison.OrdinalIgnoreCase); this._provider = isCSharp ? (CodeDomProvider)new CSharpCodeProvider() : (CodeDomProvider)new VBCodeProvider(); // Configure our code gen utility package CodeGenUtilities.Initialize(!this.IsCSharp, this.ClientProxyCodeGenerationOptions.UseFullTypeNames, this.ClientProxyCodeGenerationOptions.ClientRootNamespace); }
private void Cleanup() { // Dispose and release all instance variables CodeDomProvider provider = this._provider; this._provider = null; if (provider != null) { provider.Dispose(); } this._compileUnit = null; this._namespaces = null; this._enumTypesToGenerate = null; this._domainServiceDescriptions = null; this._host = null; this._options = null; this._clientProxyCodeGenerationOptions = null; }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="catalog">The catalog containing the <see cref="OpenRiaServices.DomainServices.Server.DomainService"/> types.</param> /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> private string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, DomainServiceCatalog catalog, IEnumerable <string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(catalog != null, "catalog cannot be null"); IEnumerable <DomainServiceDescription> domainServiceDescriptions = catalog.DomainServiceDescriptions; IDomainServiceClientCodeGenerator proxyGenerator = this.FindCodeGenerator(host, options, compositionAssemblies, codeGeneratorName); string generatedCode = null; if (proxyGenerator != null) { try { generatedCode = proxyGenerator.GenerateCode(host, domainServiceDescriptions, options); } catch (Exception ex) { // Fatal exceptions are never swallowed or processed if (ex.IsFatal()) { throw; } // Any exception from the code generator is caught and reported, otherwise it will // hit the MSBuild backstop and report failure of the custom build task. // It is acceptable to report this exception and "ignore" it because we // are running in a separate AppDomain which will be torn down immediately // after our return. host.LogError(string.Format(CultureInfo.CurrentCulture, Resource.CodeGenerator_Threw_Exception, string.IsNullOrEmpty(codeGeneratorName) ? proxyGenerator.GetType().FullName : codeGeneratorName, options.ClientProjectPath, ex.Message)); } } return(generatedCode); }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="assembliesToLoad">The set of server assemblies to use for analysis and composition.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> internal string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable<string> assembliesToLoad, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(assembliesToLoad != null, "assembliesToLoad cannot be null"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(assembliesToLoad, logger); return this.GenerateCode(host, options, catalog, assembliesToLoad, codeGeneratorName); }
/// <summary> /// Locates and returns the <see cref="IDomainServiceClientCodeGenerator"/> to use to generate client proxies /// for the specified <paramref name="options"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The code generator to use, or <c>null</c> if a matching one could not be found.</returns> internal IDomainServiceClientCodeGenerator FindCodeGenerator(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable<string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); if (string.IsNullOrEmpty(options.Language)) { throw new ArgumentException(Resource.Null_Language_Property, "options"); } IDomainServiceClientCodeGenerator generator = null; // Try to load the code generator directly if given an assembly qualified name. // We insist on at least one comma in the name to know this is an assembly qualified name. // Otherwise, we might succeed in loading a dotted name that happens to be in our assembly, // such as the default CodeDom generator. if (!string.IsNullOrEmpty(codeGeneratorName) && codeGeneratorName.Contains(',')) { Type codeGeneratorType = Type.GetType(codeGeneratorName, /*throwOnError*/ false); if (codeGeneratorType != null) { if (!typeof(IDomainServiceClientCodeGenerator).IsAssignableFrom(codeGeneratorType)) { // If generator is of the incorrect type, we will still allow the MEF approach below // to find a better one. This path could be exercised by inadvertantly using a name // that happened to load some random type that was not a code generator. host.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Code_Generator_Incorrect_Type, codeGeneratorName)); } else { try { generator = Activator.CreateInstance(codeGeneratorType) as IDomainServiceClientCodeGenerator; } catch (Exception e) { // The open catch of Exception is acceptable because we unconditionally report // the error and are running in a separate AppDomain. if (e.IsFatal()) { throw; } host.LogError(string.Format(CultureInfo.CurrentCulture, Resource.Code_Generator_Instantiation_Error, codeGeneratorName, e.Message)); } } } } if (generator == null) { // Create the MEF composition container (once only) from the assemblies we are analyzing this.CreateCompositionContainer(compositionAssemblies, host as ILogger); // The following property is filled by MEF by the line above. if (this.DomainServiceClientCodeGenerators != null && this.DomainServiceClientCodeGenerators.Any()) { // Select only those registered for the required language IEnumerable<Lazy<IDomainServiceClientCodeGenerator, ICodeGeneratorMetadata>> allImportsForLanguage = this.DomainServiceClientCodeGenerators.Where(i => string.Equals(options.Language, i.Metadata.Language, StringComparison.OrdinalIgnoreCase)); Lazy<IDomainServiceClientCodeGenerator, ICodeGeneratorMetadata> lazyImport = null; // If client specified a specific generator, use that one. // If it cannot be found, log an error to explain the problem. // If multiple with that name are found, log an error and explain the problem. // We consider this an error because the user has explicitly named a generator, // meaning they would not expect the default to be used. if (!string.IsNullOrEmpty(codeGeneratorName)) { IEnumerable<Lazy<IDomainServiceClientCodeGenerator, ICodeGeneratorMetadata>> allImportsForLanguageAndName = allImportsForLanguage.Where(i => string.Equals(i.Metadata.GeneratorName, codeGeneratorName, StringComparison.OrdinalIgnoreCase)); int numberOfMatchingGenerators = allImportsForLanguageAndName.Count(); // No generator with that name was found. Log an error and explain how to register one. if (numberOfMatchingGenerators == 0) { host.LogError(string.Format(CultureInfo.CurrentCulture, Resource.Code_Generator_Not_Found, codeGeneratorName, options.Language, options.ServerProjectPath, options.ClientProjectPath, CodeDomClientCodeGenerator.GeneratorName)); } else if (numberOfMatchingGenerators == 1) { // Exactly one was found -- take it lazyImport = allImportsForLanguageAndName.First(); } else { // Multiple with that name were found. Explain how to remove some of them or // explicitly name one. StringBuilder sb = new StringBuilder(); foreach (var import in allImportsForLanguageAndName.OrderBy(i => i.Value.GetType().FullName)) { sb.AppendLine(" " + import.Value.GetType().FullName); } host.LogError(string.Format(CultureInfo.CurrentCulture, Resource.Multiple_Named_Code_Generators, codeGeneratorName, options.Language, sb.ToString(), options.ServerProjectPath, options.ClientProjectPath, allImportsForLanguageAndName.First().Value.GetType().AssemblyQualifiedName)); } } else { // We are here if no generator name was specified. // If only one import matched the language, we have it. // This is the most common path to discovery of our own CodeDom generator // but will work equally well when it replaced. if (allImportsForLanguage.Count() == 1) { lazyImport = allImportsForLanguage.First(); } else { // Multiple custom generators exist, but a specific generator name was not provided. // Look for any custom generators other than our default CodeDom one. // If we find there is only one custom generator registered, we use that one rather than the default IEnumerable<Lazy<IDomainServiceClientCodeGenerator, ICodeGeneratorMetadata>> customGeneratorImports = allImportsForLanguage.Where(i => !string.Equals(CodeDomClientCodeGenerator.GeneratorName, i.Metadata.GeneratorName, StringComparison.OrdinalIgnoreCase)); int generatorCount = customGeneratorImports.Count(); // Exactly 1 custom generator that is not the default -- take it if (generatorCount == 1) { lazyImport = customGeneratorImports.First(); host.LogMessage(string.Format(CultureInfo.CurrentCulture, Resource.Using_Custom_Code_Generator, lazyImport.Metadata.GeneratorName)); } else if (generatorCount != 0) { // Multiple generators are available but we have insufficient information // to choose one. Log an warning and use the default StringBuilder sb = new StringBuilder(); // Sort for unit test predictability IEnumerable<Lazy<IDomainServiceClientCodeGenerator, ICodeGeneratorMetadata>> orderedCustomGenerators = customGeneratorImports.OrderBy(i => i.Metadata.GeneratorName); foreach (var import in orderedCustomGenerators) { sb.AppendLine(" " + import.Metadata.GeneratorName); } host.LogWarning(string.Format(CultureInfo.CurrentCulture, Resource.Multiple_Custom_Code_Generators_Using_Default, options.Language, sb.ToString(), options.ClientProjectPath, orderedCustomGenerators.First().Metadata.GeneratorName, CodeDomClientCodeGenerator.GeneratorName)); // Pick the default. There should be one, but if not, the calling methods will detect and report a problem. lazyImport = allImportsForLanguage.FirstOrDefault(i => string.Equals(CodeDomClientCodeGenerator.GeneratorName, i.Metadata.GeneratorName, StringComparison.OrdinalIgnoreCase)); } } } generator = lazyImport == null ? null : lazyImport.Value; } } return generator; }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="catalog">The catalog containing the <see cref="OpenRiaServices.DomainServices.Server.DomainService"/> types.</param> /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> private string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, DomainServiceCatalog catalog, IEnumerable<string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(catalog != null, "catalog cannot be null"); IEnumerable<DomainServiceDescription> domainServiceDescriptions = catalog.DomainServiceDescriptions; IDomainServiceClientCodeGenerator proxyGenerator = this.FindCodeGenerator(host, options, compositionAssemblies, codeGeneratorName); string generatedCode = null; if (proxyGenerator != null) { try { generatedCode = proxyGenerator.GenerateCode(host, domainServiceDescriptions, options); } catch (Exception ex) { // Fatal exceptions are never swallowed or processed if (ex.IsFatal()) { throw; } // Any exception from the code generator is caught and reported, otherwise it will // hit the MSBuild backstop and report failure of the custom build task. // It is acceptable to report this exception and "ignore" it because we // are running in a separate AppDomain which will be torn down immediately // after our return. host.LogError(string.Format(CultureInfo.CurrentCulture, Resource.CodeGenerator_Threw_Exception, string.IsNullOrEmpty(codeGeneratorName) ? proxyGenerator.GetType().FullName : codeGeneratorName, options.ClientProjectPath, ex.Message)); } } return generatedCode; }
// Locates the code generator registered to work with the language for the given options internal static IDomainServiceClientCodeGenerator CreateCodeGenerator(ICodeGenerationHost host, ClientCodeGenerationOptions options) { using (ClientCodeGenerationDispatcher dispatcher = new ClientCodeGenerationDispatcher()) { IDomainServiceClientCodeGenerator generator = dispatcher.FindCodeGenerator(host, options, /*compositionAssemblies*/ null, /*codeGeneratorName*/ null); return generator; } }
public string GenerateCode(ICodeGenerationHost host, IEnumerable<DomainServiceDescription> descriptions, ClientCodeGenerationOptions options) { Assert.IsNotNull(host, "host cannot be null when code generator is called"); Assert.IsNotNull(options, "options cannot be null when code generator is called"); Assert.IsNotNull(descriptions, "descriptions cannot be null when code generator is called"); // These 2 test helpers reset each time they are read bool logWarningsFull = MockCodeGenerator.LogWarningsFull; MockCodeGenerator.LogWarningsFull = false; bool logErrorsFull = MockCodeGenerator.LogErrorsFull; MockCodeGenerator.LogErrorsFull = false; bool throwException = MockCodeGenerator.ThrowException; MockCodeGenerator.ThrowException = false; if (throwException) { throw MockCodeGenerator.Exception; } if (logWarningsFull) { ConsoleLogger.LogPacket p = MockCodeGenerator.WarningPacket; host.LogWarning(p.Message, p.Subcategory, p.ErrorCode, p.HelpString, p.File, p.LineNumber, p.ColumnNumber, p.EndLineNumber, p.EndColumnNumber); } if (logErrorsFull) { ConsoleLogger.LogPacket p = MockCodeGenerator.ErrorPacket; host.LogError(p.Message, p.Subcategory, p.ErrorCode, p.HelpString, p.File, p.LineNumber, p.ColumnNumber, p.EndLineNumber, p.EndColumnNumber); } return MockCodeGenerator.FakeGeneratedCode; }
// Invokes the code generator discovered via the host and options internal static string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable<Type> domainServiceTypes) { IDomainServiceClientCodeGenerator generator = CreateCodeGenerator(host, options); DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, host as ILogger); return generator.GenerateCode(host, catalog.DomainServiceDescriptions, options); }
public string GenerateCode(ICodeGenerationHost codeGenerationHost, IEnumerable<DomainServiceDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { throw new NotImplementedException(); }
public virtual string GenerateCode(ICodeGenerationHost codeGenerationHost, IEnumerable<DomainServiceDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { return MockGSharpCodeGeneratorBase.GeneratedCode; }
public override string GenerateCode(ICodeGenerationHost codeGenerationHost, IEnumerable<DomainServiceDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { return MockGSharpCodeGeneratorDerived.DerivedGeneratedCode; }
/// <summary> /// This method is part of the <see cref="IDomainServiceClientCodeGenerator" /> interface. The RIA Services Code Generation process uses this method as the entry point into the code generator. /// </summary> /// <param name="codeGenerationHost">The code generation host for this instance.</param> /// <param name="domainServiceDescriptions">The list of all the DomainServiceDescription objects.</param> /// <param name="options">The code generation objects.</param> /// <returns>The generated code.</returns> public string GenerateCode(ICodeGenerationHost codeGenerationHost, IEnumerable<DomainServiceDescription> domainServiceDescriptions, ClientCodeGenerationOptions options) { this._codeGenerationHost = codeGenerationHost; this._domainServiceDescriptions = domainServiceDescriptions; this._options = options; this._enumTypesToGenerate = new HashSet<Type>(); if (this.EntityGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.EntityGeneratorNotFound)); } if (this.ComplexObjectGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.ComplexObjectGeneratorNotFound)); } if (this.DomainContextGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.DomainContextGeneratorNotFound)); } if (this.WebContextGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.WebContextGeneratorNotFound)); } if (this.EnumGenerator == null) { this.CodeGenerationHost.LogError(string.Format(CultureInfo.CurrentCulture, TextTemplateResource.EnumGeneratorNotFound)); } if (!this.CodeGenerationHost.HasLoggedErrors) { return this.GenerateCode(); } return null; }
/// <summary> /// Generates client proxy source code using the specified <paramref name="codeGeneratorName"/> in the context /// of the specified <paramref name="host"/>. /// </summary> /// <param name="host">The host for code generation.</param> /// <param name="options">The options to use for code generation.</param> /// <param name="domainServiceTypes">The set of <see cref="OpenRiaServices.DomainServices.Server.DomainService"/> types for which to generate code.</param> /// <param name="compositionAssemblies">The optional set of assemblies to use to create the MEF composition container.</param> /// <param name="codeGeneratorName">Optional generator name. A <c>null</c> or empty value will select the default generator.</param> /// <returns>The generated source code or <c>null</c> if none was generated.</returns> internal string GenerateCode(ICodeGenerationHost host, ClientCodeGenerationOptions options, IEnumerable<Type> domainServiceTypes, IEnumerable<string> compositionAssemblies, string codeGeneratorName) { Debug.Assert(host != null, "host cannot be null"); Debug.Assert(options != null, "options cannot be null"); Debug.Assert(domainServiceTypes != null, "domainServiceTypes cannot be null"); ILogger logger = host as ILogger; DomainServiceCatalog catalog = new DomainServiceCatalog(domainServiceTypes, logger); return this.GenerateCode(host, options, catalog, compositionAssemblies, codeGeneratorName); }