예제 #1
0
        protected virtual CodeTypeDeclaration GenerateClass(CodeNamespace @namespace)
        {
            var generator = typeof(ResourceTypeBuilder);
            var version   = generator.Assembly.GetName( ).Version;
            var type      = Declare.Class(settings.ClassName)
                            .Modifiers(settings.AccessModifiers)
                            .IsPartial(CodeDomProvider.Supports(GeneratorSupport.PartialTypes))
                            .AddSummary(ClassSummary)
                            .AddTo(@namespace);

            if (settings.CustomToolType != null)
            {
                type.AddRemarks(ClassRemarksFormat, generator.FullName, settings.CustomToolType.Name);
            }
            else
            {
                type.AddRemarks(ClassRemarksToollessFormat, generator.FullName);
            }

            if (string.Equals(@namespace.Name.Split('.').Last( ), settings.ClassName, StringComparison.OrdinalIgnoreCase))
            {
                type.Attributed(Declare.Attribute <SuppressMessageAttribute> ("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces"));
            }

            return(type.Attributed(Declare.Attribute <GeneratedCodeAttribute> (generator.FullName, version.ToString( )),
                                   Declare.Attribute <DebuggerNonUserCodeAttribute> ( ),
                                   Declare.Attribute <ObfuscationAttribute> ( )
                                   .WithArgument(nameof(ObfuscationAttribute.Exclude), true)
                                   .WithArgument(nameof(ObfuscationAttribute.ApplyToMembers), true)));
        }
        static void AddToStringHelper(CodeTypeDeclaration type, CodeDomProvider provider)
        {
            var helperClass = Declare.Class("ToStringInstanceHelper")
                              .AsNestedPublic()
                              .WithReference(out var helperClassType);

            helperClass.AddField <IFormatProvider> ("formatProvider",
                                                    TypeReference <System.Globalization.CultureInfo> .Global.Property("InvariantCulture"))
            .WithReference(out var formatProvider);

            helperClass.AddProperty <IFormatProvider> ("FormatProvider")
            .WithGet(formatProvider)
            .WithSetIgnoresNull(formatProvider);

            helperClass.AddMethod("ToStringWithCulture")
            .Returns <string> ()
            .WithParameter <object> ("objectToConvert", out var objectToConvert)
            .WithStatements(
                objectToConvert.ThrowIfNull(),
                Declare.Variable <Type> ("type", objectToConvert.InvokeMethod("GetType"), out var objType),
                Declare.Variable <Type> ("iConvertibleType", Expression.TypeOf <IConvertible> (), out var iConvertibleType),
                Statement.If(iConvertibleType.InvokeMethod("IsAssignableFrom", objType),
                             Then: Statement.Return(objectToConvert.Cast <IConvertible> ().InvokeMethod("ToString", formatProvider))),
                Declare.Variable <System.Reflection.MethodInfo> ("methInfo",
                                                                 objType.InvokeMethod("GetMethod", Expression.Primitive("ToString"), Expression.Array <Type> (iConvertibleType)),
                                                                 out var methInfoLocalRef),
                Statement.If(methInfoLocalRef.IsNotNull(),
                             Then: Statement.Return(Expression.Cast <string> (
                                                        methInfoLocalRef.InvokeMethod("Invoke", objectToConvert, Expression.Array <object> (formatProvider))))),
                Statement.Return(objectToConvert.InvokeMethod("ToString"))
                );

            var helperFieldName = provider.CreateValidIdentifier("_toStringHelper");

            type.AddPropertyGetOnly("ToStringHelper",
                                    type.AddField(helperFieldName, helperClassType, Expression.New(helperClassType)));

            type.AddMember(helperClass);
        }
예제 #3
0
        private static CodeTypeDeclaration Build(string className, MemberAttributes memberAttributes, IList <ResourceMapping> map, string extensionType, bool generateConstructors, string bindingType, CodeAttributeDeclaration bindingTypeConverter)
        {
            var type = Declare.Class(className + "Extension")
                       .Modifiers(memberAttributes);
            var keyEnum = Declare.NestedEnum(ResourceKeyEnumName)
                          .Modifiers(memberAttributes)
                          .AddSummary(ResourceKeyEnumNameSummary)
                          .AddTo(type);
            var keyEnumType = Code.Type(ResourceKeyEnumName).Local( );
            var objectType  = Code.Type <object> ( );

            type.BaseTypes.Add(Code.Type(extensionType, Code.NestedType(type.Name, ResourceKeyEnumName).Local( )));

            if (generateConstructors)
            {
                var distinctNumberOfArguments = map.Select(mapping => mapping.NumberOfArguments)
                                                .DefaultIfEmpty(0)
                                                .Distinct( )
                                                .OrderBy(numberOfArguments => numberOfArguments);

                foreach (var numberOfArguments in distinctNumberOfArguments)
                {
                    var ctor = new CodeConstructor( )
                    {
                        Attributes = memberAttributes
                    }.AddTo(type);

                    for (var argument = 0; argument < numberOfArguments; argument++)
                    {
                        var parameterName = Format(CultureInfo.InvariantCulture, FormatMethodParameterName, argument);

                        ctor.Parameters.Add(objectType.Parameter(parameterName));
                        ctor.BaseConstructorArgs.Add(Code.Variable(parameterName));
                    }
                }
            }

            var keyPathType = Code.Type(bindingType);

            var _key     = Code.This( ).Field("_key");
            var _keyPath = Code.This( ).Field("_keyPath");
            var _type    = Code.This( ).Field("_type");

            Declare.Field(keyEnumType, _key.FieldName).AddTo(type);
            Declare.Property(keyEnumType, "Key").Public( ).Override( )
            .Get(get => get.Return(_key))
            .Set((set, value) => set.Add(Code.Assign(_key, value)))
            .AddTo(type);


            Declare.Field(keyPathType, _keyPath.FieldName).AddTo(type);
            Declare.Property(keyPathType, "KeyPath").Public( ).Override( )
            .Get(get => get.Return(_keyPath))
            .Set((set, value) => set.Add(Code.Assign(_keyPath, value)))
            .Attributed(bindingTypeConverter)
            .AddTo(type);

            Declare.Field <Type> (_type.FieldName).AddTo(type);
            Declare.Property <Type> ("Type").Public( ).Override( )
            .Get(get => get.Return(_type))
            .Set((set, value) => set.Add(Code.Assign(_type, value)))
            .AddTo(type);

            Declare.Property(Code.Type <ILocalizer> ( ), "Localizer").Protected( ).Override( )
            .Get(get => get.Return(Code.Type(className).Local( ).Static( ).Property(LocalizerPropertyName)))
            .AddTo(type);

            var translation = new CodeArrayCreateExpression(Code.Type <string> ( ));
            var index       = 0;

            foreach (var mapping in map)
            {
                Declare.Field(keyEnumType, mapping.Property).Const( )
                .Modifiers(memberAttributes)
                .Initialize(Code.Constant(index++))
                .AddSummary(ResourceKeyFieldSummaryFormat, mapping.Resource.Name)
                .AddTo(keyEnum);

                translation.Initializers.Add(Code.Constant(mapping.Resource.Name));
            }

            var translator = Declare.Field <string []> (ResourceKeyTranslatorFieldName).Static( )
                             .Initialize(translation)
                             .AddTo(type);

            var translate = Declare.Method <string> ("KeyToName",
                                                     MemberAttributes.Family | MemberAttributes.Override)
                            .AddTo(type);

            var key   = Code.Variable(ResourceKeyParameterName);
            var first = keyEnumType.Static( ).Field(map [0].Property);
            var last  = keyEnumType.Static( ).Field(map [index - 1].Property);

            translate.Parameters.Add(keyEnumType.Parameter(ResourceKeyParameterName));
            translate.Statements.Add(Code.If(key.IsLessThan(first).Or(
                                                 key.IsGreaterThan(last)))
                                     .Then(Code.Throw <ArgumentOutOfRangeException> (Code.Constant(ResourceKeyParameterName))));
            translate.Statements.Return(Code.Static( )
                                        .Field(ResourceKeyTranslatorFieldName)
                                        .Indexer(Code.Variable(ResourceKeyParameterName).Cast <int> ( )));

            return(type);
        }
예제 #4
0
 public static CodeTypeDeclaration AddClass(this CodeNamespace ns, string className) => ns.AddType(Declare.Class(className));