public Command(Type typeOfCommandOptions)
        {
            originalTypeOfCommandOptions = typeOfCommandOptions;
            Type proxyTypeOfParametersAndOptions = CommandTypeBuilder.CreateProxyType(typeOfCommandOptions);

            ParametersAndOptionsProxy        = Activator.CreateInstance(proxyTypeOfParametersAndOptions);
            propertiesOfParametersAndOptions = new List <PropertyInfo>(proxyTypeOfParametersAndOptions.GetProperties());
            propertiesOfParametersAndOptions.Sort(ComparePropertyOrder);

            commandLineManagerAttribute = PlossumAttributesHelper.GetCommandLineManagerAttribute(typeOfCommandOptions);

            ResetParameters();

            assignment = commandLineManagerAttribute.Assignment;

            const string template = @"\s*{0}(?<OptionName>\w*[\+|\-]?)";

            optionSeparator   = commandLineManagerAttribute.OptionSeparator;
            optionNamePattern = String.Format(template, optionSeparator);

            allGroupAttributesDic = PlossumAttributesHelper.GetCommandLineOptionGroupAttributesDic(proxyTypeOfParametersAndOptions);

            Parser = new CommandLineParser(ParametersAndOptionsProxy);
        }
Beispiel #2
0
        /// <summary>
        /// Merge optionsType into parametersType to create a new type with both, and translate CommandLineOptionAttribute to BCL attributes.
        /// </summary>
        /// <param name="optionsType">For options.</param>
        /// <returns>New type</returns>
        /// <remarks>Actually CLR seems to allow multiple dyanmic assemblies having the same name since the dynamic types are generated and instantiated through reflection,
        /// however to make them look beautiful in Process Explorer, they are given different names.</remarks>
        internal static Type CreateProxyType(Type optionsType)
        {
            var             namespaceSuffix = GetNamespaceSuffix(optionsType.Namespace);
            AssemblyBuilder assemblyBuilder = System.Threading.Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("Fonlow.CommandLineGui.DynamicTypes" + namespaceSuffix), AssemblyBuilderAccess.Run); //build assembly at runtime.
            ModuleBuilder   moduleBuilder   = assemblyBuilder.DefineDynamicModule("Fonlow.CommandLineGui.DynamicModule");                                                                                     //build module of the assembly
            TypeBuilder     typeBuilder     = moduleBuilder.DefineType("Fonlow.CommandLineGui.DynamicTypes." + optionsType.Name + "Proxy",                                                                    // to build a new type with suffix Proxy
                                                                       TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.BeforeFieldInit);

            var propertiesOfOptions = optionsType.GetProperties();
            var fieldsOfOptions     = optionsType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);

            var groupNamesDic = PlossumAttributesHelper.GetCommandLineOptionGroupAttributesDic(optionsType);

            typeBuilder.SetParent(typeof(object));//parametersType has to be the parent since its attributes don't need to be changed.

            CopyCommandLineOptionGroupAttributes(typeBuilder, optionsType);
            CopyCommandLineManagerAttribute(typeBuilder, PlossumAttributesHelper.GetCommandLineManagerAttribute(optionsType));

            foreach (var fieldInfo in fieldsOfOptions)
            {
                FieldBuilder fieldBuilder = typeBuilder.DefineField(fieldInfo.Name, fieldInfo.FieldType, fieldInfo.Attributes);
            }

            foreach (var propertyItem in propertiesOfOptions)
            {
                var propertyBuilder = typeBuilder.DefineProperty(propertyItem.Name, PropertyAttributes.None, propertyItem.PropertyType, null);

                FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyItem.Name.ToLower(), propertyItem.PropertyType, FieldAttributes.Public);

                // copy the "get" accessor
                MethodInfo    getterInfo      = propertyItem.GetGetMethod();
                var           parametersTypes = getterInfo.GetParameters().Select(d => d.ParameterType).ToArray();
                MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod(getterInfo.Name, getterInfo.Attributes, getterInfo.CallingConvention, getterInfo.ReturnType, Type.EmptyTypes);
                getPropMthdBldr.DefineParameter(0, ParameterAttributes.Retval, null);

                ILGenerator propertyGetIL = getPropMthdBldr.GetILGenerator();
                propertyGetIL.Emit(OpCodes.Ldarg_0);
                propertyGetIL.Emit(OpCodes.Ldfld, fieldBuilder);
                propertyGetIL.Emit(OpCodes.Ret);

                propertyBuilder.SetGetMethod(getPropMthdBldr);

                // copy the "set" accessor
                MethodInfo setterInfo       = propertyItem.GetSetMethod();
                var        setterParameters = setterInfo.GetParameters();
                parametersTypes = setterParameters.Select(d => d.ParameterType).ToArray();
                MethodBuilder setPropMthdBldr = typeBuilder.DefineMethod(setterInfo.Name, setterInfo.Attributes, setterInfo.CallingConvention, setterInfo.ReturnType, parametersTypes);// new Type[] { propertyItem.PropertyType });
                setPropMthdBldr.DefineParameter(1, ParameterAttributes.In, setterParameters[0].Name);
                setPropMthdBldr.DefineParameter(0, ParameterAttributes.Retval, null);

                ILGenerator propertySetIL = setPropMthdBldr.GetILGenerator();
                propertySetIL.Emit(OpCodes.Ldarg_0);
                propertySetIL.Emit(OpCodes.Ldarg_1);
                propertySetIL.Emit(OpCodes.Stfld, fieldBuilder);
                propertySetIL.Emit(OpCodes.Ret);

                propertyBuilder.SetSetMethod(setPropMthdBldr);

                var optionAttribute = PlossumAttributesHelper.GetCommandLineOptionAttribute(propertyItem);
                if (optionAttribute == null)//for fixed parameters
                {
                    var fixedParameterAttribute = PropertyHelper.ReadAttribute <FixedParameterAttribute>(propertyItem);

                    if (fixedParameterAttribute != null)
                    {
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DisplayNameAttribute), typeof(string), fixedParameterAttribute.DisplayName);
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DescriptionAttribute), typeof(string), fixedParameterAttribute.Description);
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(CategoryAttribute), typeof(string), fixedParameterAttribute.Category);
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(ParameterOrderAttribute), typeof(int), fixedParameterAttribute.Order);

                        if (fixedParameterAttribute.DefaultValue != null)
                        {
                            CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DefaultValueAttribute), propertyItem.PropertyType, fixedParameterAttribute.DefaultValue);
                        }
                    }

                    var editorAttribute = ReadEditorAttribute(propertyItem);
                    if (editorAttribute != null)
                    {
                        CreateEditorAttributeOfProperty(propertyBuilder, Type.GetType(editorAttribute.EditorTypeName));
                    }
                }
                else
                {
                    #region Create PropertyGrid friendly attributes

                    if (optionAttribute.DefaultAssignmentValue != null)
                    {
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DefaultValueAttribute), propertyItem.PropertyType, optionAttribute.DefaultAssignmentValue);
                    }

                    string displayName = optionAttribute.Name;
                    if (String.IsNullOrEmpty(displayName))
                    {
                        if (String.IsNullOrEmpty(displayName))
                        {
                            displayName          = propertyItem.Name;
                            optionAttribute.Name = displayName;
                        }
                    }

                    string category = null;

                    if (optionAttribute.GroupId != null)
                    {
                        Plossum.CommandLine.CommandLineOptionGroupAttribute groupAttribute;
                        bool foundGroupAttribute = groupNamesDic.TryGetValue(optionAttribute.GroupId, out groupAttribute);
                        if (foundGroupAttribute)
                        {
                            category = String.IsNullOrEmpty(groupAttribute.Name) ? groupAttribute.Id : groupAttribute.Name;
                        }
                    }

                    CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DisplayNameAttribute), typeof(string), displayName);
                    if (!String.IsNullOrEmpty(optionAttribute.Description))
                    {
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DescriptionAttribute), typeof(string), optionAttribute.Description);
                    }

                    if (category != null)
                    {
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(CategoryAttribute), typeof(string), category);
                    }


                    if (optionAttribute.DefaultAssignmentValue != null)
                    {
                        CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DefaultValueAttribute), propertyItem.PropertyType, optionAttribute.DefaultAssignmentValue);
                    }
                    else
                    {
                        var defaultValueOfType = PropertyHelper.GetDefaultValueOfType(propertyItem.PropertyType);
                        if (defaultValueOfType != null)
                        {
                            CreateCustomAttributeWith1ParameterCtorOfProperty(propertyBuilder, typeof(DefaultValueAttribute), propertyItem.PropertyType, defaultValueOfType);
                        }
                    }


                    var editorAttribute = ReadEditorAttribute(propertyItem);
                    if (editorAttribute != null)
                    {
                        CreateEditorAttributeOfProperty(propertyBuilder, Type.GetType(editorAttribute.EditorTypeName));
                    }

                    CopyCommandLineOptionAttributeOfProperty(propertyBuilder, optionAttribute);


                    #endregion
                }
            }

            return(typeBuilder.CreateType());
        }