Пример #1
0
        static void Main(string[] args)
        {
            // parse this command line:

            /* fluent HumanResources.dll --types Person,Employee -f HumanResources.Fluent.dll
             * --overwrite --prefix Magic --suffix Cloned --property-name Target
             */

            var app = new CommandLineApplication
            {
                Name        = "fluent",
                Description = "Fluent API Assembly Generator"
            };

            app.HelpOption("-?|-h|--help");

            var asmArg              = app.Argument("assembly", "The fully-qualified path to the source assembly to scan.");
            var scanTypesOption     = app.Option("-t|--types <types>", "The types for which to generate fluent APIs.", CommandOptionType.SingleValue);
            var targetAsmFileOption = app.Option("-f|--file <file>", "The file name of the target output assembly to generate.", CommandOptionType.SingleValue);
            var overwriteOption     = app.Option("-d|--overwrite", "Instructs to delete any previously-built existing assembly.", CommandOptionType.NoValue);
            var prefixOption        = app.Option("-b|--prefix <prefix>", "The string to prepend to an output type.", CommandOptionType.SingleValue);
            var suffixOption        = app.Option("-e|--suffix <suffix>", "The string to append to an output type.", CommandOptionType.SingleValue);
            var propertyNameOption  = app.Option("-p|--property-name <property>", "The name of the property that returns a reference to the underlying type.", CommandOptionType.SingleValue);

            app.OnExecute(() =>
            {
                var console       = PowerConsole.SmartConsole.Default;
                var sourceAsmPath = asmArg.Value;

                if (string.IsNullOrWhiteSpace(sourceAsmPath))
                {
                    console.WriteError("You must specify the fully-qualified path to the assembly to scan.");
                    return(1);
                }

                try
                {
                    Assembly asm;
                    try
                    {
                        asm = Assembly.LoadFile(sourceAsmPath);
                    }
                    catch (FileNotFoundException)
                    {
                        console.WriteError($"The system cannot find the specified assembly:\n{sourceAsmPath}\n");
                        return(3);
                    }

                    var scanTypes = scanTypesOption.HasValue() ? scanTypesOption.Value().Split(',') : null;
                    var typeList  = new List <Type>();

                    if (scanTypes?.Length > 0)
                    {
                        typeList.AddRange(asm.GetTypes().Where(t => scanTypes.Contains(t.Name)));
                    }

                    using (var config = FluentApiFactory.Configure(overwriteOption.HasValue()))
                    {
                        config
                        .OnError(error => Console.WriteLine($"A critical error occured: {error}"))
                        .OnDeleteError((error, builder, file) =>
                                       Console.WriteLine($"Could not delete the file '{file}'. Reason for failure: {error.Message}"))
                        .WithOptions()
                        .SetFluentTypeNamePrefix(prefixOption.HasValue() ? prefixOption.Value() : "Fluent")
                        .SetProxyClassNameSuffix(suffixOption.HasValue() ? suffixOption.Value() : "Proxy")
                        .SetWrappedObjectPropertyName(propertyNameOption.HasValue() ? propertyNameOption.Value() : "Object")
                        .WithConfig();

                        if (typeList.Count > 0)
                        {
                            config.Scan(typeList.ToArray());
                        }
                        else
                        {
                            config.ScanAssembly(asm, false);
                        }

                        var fileName = targetAsmFileOption.Value();
                        var dirName  = string.IsNullOrWhiteSpace(fileName) ? Environment.CurrentDirectory : Path.GetDirectoryName(fileName);

                        if (string.IsNullOrWhiteSpace(dirName))
                        {
                            dirName = Path.GetDirectoryName(sourceAsmPath) ?? Environment.CurrentDirectory;
                        }

                        // build the assembly and get the result
                        var result = config.Build(fileName).Result();

                        if (true == result?.Succeeded)
                        {
                            console.WriteSuccess("Success!\n")
                            .WriteLine("The generated assembly is:")
                            .WriteLine(Path.Combine(dirName, result.AssemblyFileName));
                        }
                        else
                        {
                            console.WriteError($"Could not create the assembly! {result?.Error?.Message}");
                        }
                    }

                    return(0);
                }
                catch (Exception ex)
                {
                    console.WriteError(ex);
                }

                return(2);
            });

            app.Execute(args);
        }
        public static void Build()
        {
            var console = SmartConsole.Default;

            try
            {
                // generate a dynamic assembly for the single Person class (very unlikely)
                // minimalistic approach:
                var result = FluentApiFactory.Configure(overwrite: true)
                             .Scan(typeof(Person), typeof(Employee))
                             .Build()
                             .ReleaseResources()
                             .Result();

                WriteAssemblyLocation(result);

                /*
                 * // or if you want to scan the whole HumanResources assembly
                 * // you have to be explicit; the ScanAssembly(Assembly) and
                 * // ScanAssemblyFrom(Type) methods retrieve only types marked
                 * // with the custom attribute FluentApiTargetAttribute
                 * var types = typeof(Person).Assembly.GetTypes();
                 *
                 * result = FluentApiFactory.Configure(overwrite: true).Scan(types).Build().ReleaseResources().Result();
                 *
                 * WriteAssemblyLocation(result);
                 *
                 * // you can even generate multiple dynamic assemblies
                 * // with this full-blown approach:
                 * using (var config = FluentApiFactory.Configure(true))
                 * {
                 *  FluentApiFactoryExecutionResult result1 = null;
                 *  result = config
                 *      .OnError(error => console.WriteLine($"A critical error occured: {error}"))
                 *      .OnDeleteError((error, builder, file) =>
                 *          console.WriteLine($"Could not delete the file '{file}'. Reason for failure: {error.Message}")
                 *      )
                 *      .WithOverwriteOptions()
                 *      // these 'Set...' methods modify the default prefix and suffix values
                 *      // public interface IPerson {...}
                 *      // internal sealed class PersonCloned : IPerson {...}
                 *      .SetProxyClassNameSuffix("Cloned")
                 *      .SetFluentTypeNamePrefix("Magic")
                 *      // public class MagicPerson { ... public virtual IPerson Target { get; } }
                 *      .SetWrappedObjectPropertyName("Target")
                 *      .WithConfig()
                 *      .ScanAssemblyFrom(typeof(Person))
                 *      .Build()
                 *      .Result();
                 *
                 *  WriteAssemblyLocation(result);
                 *  WriteAssemblyLocation(result1);
                 * }
                 *
                 * if (result.Succeeded)
                 * {
                 *  console.WriteLines("What's next? Grab that file and a reference to it in your project.",
                 *      "You'll be able to use your fluent wrapper as shown in the next demo.",
                 *      "The assemblies' names are similar to: HumanResources.DynamicFluentApis.abcdef.dll ",
                 *      "and HumanResources.Web.Mvc.DynamicFluentApis.fedcba.dll",
                 *      "Where 'abcdef' and 'fedcba' are (for instance) the hash codes generated ",
                 *      "for the dynamic fluent API assemblies.");
                 * }
                 */
            }
            catch (Exception ex)
            {
                console.WriteError($"An unexpected error occured: {ex.Message}");
            }

            void WriteAssemblyLocation(FluentApiFactoryExecutionResult result)
            {
                if (true == result?.Succeeded)
                {
                    console.WriteLine($"The generated assembly is {Environment.CurrentDirectory}\\{result.AssemblyFileName}!");
                }
                else
                {
                    console.WriteError("Could not create the assembly! " + result?.Error?.Message);
                }
            }
        }