File: ObjectFactoryCodeDomTreeGenerator.cs

package info (click to toggle)
mono 6.8.0.105%2Bdfsg-3.3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,284,512 kB
  • sloc: cs: 11,172,132; xml: 2,850,069; ansic: 671,653; cpp: 122,091; perl: 59,366; javascript: 30,841; asm: 22,168; makefile: 20,093; sh: 15,020; python: 4,827; pascal: 925; sql: 859; sed: 16; php: 1
file content (128 lines) | stat: -rw-r--r-- 5,068 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//------------------------------------------------------------------------------
// <copyright file="ObjectFactoryCodeDomTreeGenerator.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------

// This code is used to optimize the instantiation of generated types.


namespace System.Web.Compilation {

using System;
using System.Collections;
using System.Reflection;
using System.Security.Permissions;
using System.Globalization;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Web.Util;
using Util = System.Web.UI.Util;


internal delegate object InstantiateObject();

internal class ObjectFactoryCodeDomTreeGenerator {

    private CodeCompileUnit _codeCompileUnit;
    private CodeTypeDeclaration _factoryClass;

    private const string factoryClassNameBase = "FastObjectFactory_";
    private const string factoryFullClassNameBase = BaseCodeDomTreeGenerator.internalAspNamespace +
        "." + factoryClassNameBase;

    internal ObjectFactoryCodeDomTreeGenerator(string outputAssemblyName) {

        _codeCompileUnit = new CodeCompileUnit();

        CodeNamespace sourceDataNamespace = new CodeNamespace(
            BaseCodeDomTreeGenerator.internalAspNamespace);
        _codeCompileUnit.Namespaces.Add(sourceDataNamespace);

        // Make the class name vary based on the assembly (VSWhidbey 363214)
        string factoryClassName = factoryClassNameBase +
            Util.MakeValidTypeNameFromString(outputAssemblyName).ToLower(CultureInfo.InvariantCulture);

        // Create a single class, in which a method will be added for each
        // type that needs to be fast created in this assembly
        _factoryClass = new CodeTypeDeclaration(factoryClassName);

        // Make the class internal (VSWhidbey 363214)
        _factoryClass.TypeAttributes &= ~TypeAttributes.Public;

        // We generate a dummy line pragma, just so it will end with a '#line hidden'
        // and prevent the following generated code from ever being treated as user
        // code.  We need to use this hack because CodeDOM doesn't allow simply generating
        // a '#line hidden'. (VSWhidbey 199384)
        CodeSnippetTypeMember dummySnippet = new CodeSnippetTypeMember(String.Empty);
#if !PLATFORM_UNIX /// Unix file system
        // CORIOLISTODO: Unix file system
        dummySnippet.LinePragma = new CodeLinePragma(@"c:\\dummy.txt", 1);
#else // !PLATFORM_UNIX
        dummySnippet.LinePragma = new CodeLinePragma(@"/dummy.txt", 1);
#endif // !PLATFORM_UNIX
        _factoryClass.Members.Add(dummySnippet);

        // Add a private default ctor to make the class non-instantiatable (VSWhidbey 340829)
        CodeConstructor ctor = new CodeConstructor();
        ctor.Attributes |= MemberAttributes.Private;
        _factoryClass.Members.Add(ctor);

        sourceDataNamespace.Types.Add(_factoryClass);
    }

    internal void AddFactoryMethod(string typeToCreate) {

        // Generate a simple factory method for this type.  e.g.
        // static object Create_Acme_Foo() {
        //     return new ASP.foo_aspx();
        // }

        CodeMemberMethod method = new CodeMemberMethod();
        method.Name = GetCreateMethodNameForType(typeToCreate);
        method.ReturnType = new CodeTypeReference(typeof(object));
        method.Attributes = MemberAttributes.Static;

        CodeMethodReturnStatement cmrs = new CodeMethodReturnStatement(
            new CodeObjectCreateExpression(typeToCreate));
        method.Statements.Add(cmrs);

        _factoryClass.Members.Add(method);
    }

    private static string GetCreateMethodNameForType(string typeToCreate) {
        return "Create_" + Util.MakeValidTypeNameFromString(typeToCreate);
    }

    internal CodeCompileUnit CodeCompileUnit {
        get { return _codeCompileUnit; }
    }

    // Get the factory delegate for this type
    // Could be called with user code on the stack, so need to assert here 
    // e.g. This can happen during a Server.Transfer, or a LoadControl.
    [ReflectionPermission(SecurityAction.Assert, Flags = ReflectionPermissionFlag.MemberAccess)]
    internal static InstantiateObject GetFastObjectCreationDelegate(Type t) {
        // Look for the factory class in the same assembly
        Assembly a = t.Assembly;

        string shortAssemblyName = Util.GetAssemblyShortName(t.Assembly);
        shortAssemblyName = shortAssemblyName.ToLower(CultureInfo.InvariantCulture);
        Type factoryType = a.GetType(factoryFullClassNameBase + Util.MakeValidTypeNameFromString(shortAssemblyName));
        if (factoryType == null)
            return null;

        string methodName = GetCreateMethodNameForType(t.FullName);

        try {
            return (InstantiateObject) Delegate.CreateDelegate(
                typeof(InstantiateObject), factoryType, methodName);
        }
        catch {
            return null;
        }
    }
}

}