상속: IComponentCodeGenerator
        static void generateComponentExtensions(Type[] components)
        {
            var generator  = new ComponentExtensionsGenerator();
            var extensions = generator.GenerateComponentExtensions(components);

            writeFiles(extensions);
        }
    void when_generating()
    {
        it["component without fields"] = () => generates(typeof(MovableComponent), MovableComponent.extensions);
        it["component with fields"] = () => generates(typeof(PersonComponent), PersonComponent.extensions);
        it["single singleton component"] = () => generates(typeof(AnimatingComponent), AnimatingComponent.extensions);
        it["single component with fields"] = () => generates(typeof(UserComponent), UserComponent.extensions);
        it["component for custom pool"] = () => generates(typeof(OtherPoolComponent), OtherPoolComponent.extensions);
        it["ignores [DontGenerate]"] = () => {
            var type = typeof(DontGenerateComponent);
            var files = new ComponentExtensionsGenerator().Generate(new[] { type });
            files.Length.should_be(0);
        };

        it["works with namespaces"] = () => generates(typeof(NamespaceComponent), NamespaceComponent.extensions);
    }
    void generates(Type type, string code)
    {
        var files = new ComponentExtensionsGenerator().Generate(new[] { type });
        var filePath = type + classSuffix;

        files.Length.should_be(1);
        files.Any(f => f.fileName == filePath).should_be_true();

        var file = files.First(f => f.fileName == filePath);
        if (logResults) {
            Console.WriteLine("should:\n" + code);
            Console.WriteLine("was:\n" + file.fileContent);
        }
        file.fileContent.should_be(code);
    }
    void generates(Type type, string expectedFileContent) {
        expectedFileContent = expectedFileContent.ToUnixLineEndings();
        var files = new ComponentExtensionsGenerator().Generate(new[] { type });
        var expectedFilePath = type + classSuffix;

        files.Length.should_be(1);
        var file = files[0];

        if (logResults) {
            Console.WriteLine("should:\n" + expectedFileContent);
            Console.WriteLine("was:\n" + file.fileContent);
        }

        file.fileName.should_be(expectedFilePath);
        file.fileContent.should_be(expectedFileContent);
    }
    void generates(ComponentInfo componentInfo, string expectedFileContent)
    {
        expectedFileContent = expectedFileContent.ToUnixLineEndings();
        var files = new ComponentExtensionsGenerator().Generate(new[] { componentInfo });
        var expectedFilePath = componentInfo.fullTypeName + classSuffix;

        files.Length.should_be(1);
        var file = files[0];

        #pragma warning disable
        if (logResults) {
            Console.WriteLine("should:\n" + expectedFileContent);
            Console.WriteLine("was:\n" + file.fileContent);
        }

        file.fileName.should_be(expectedFilePath);
        file.fileContent.should_be(expectedFileContent);
    }
    void when_generating()
    {
        it["component without fields"] = () => generates(MovableComponent.componentInfo, MovableComponent.extensions);
        it["component with fields"] = () => generates(PersonComponent.componentInfo, PersonComponent.extensions);
        it["single component without fields"] = () => generates(AnimatingComponent.componentInfo, AnimatingComponent.extensions);
        it["single component with fields"] = () => generates(UserComponent.componentInfo, UserComponent.extensions);
        it["component for custom pool"] = () => generates(OtherPoolComponent.componentInfo, OtherPoolComponent.extensions);
        it["supports properties"] = () => generates(ComponentWithFieldsAndProperties.componentInfo, ComponentWithFieldsAndProperties.extensions);
        it["ignores [DontGenerate]"] = () => {
            var componentInfo = DontGenerateComponent.componentInfo;
            var files = new ComponentExtensionsGenerator().Generate(new[] { componentInfo });
            files.Length.should_be(0);
        };

        it["works with namespaces"] = () => generates(NamespaceComponent.componentInfo, NamespaceComponent.extensions);
        it["generates matchers for each pool"] = () => generates(CComponent.componentInfo, CComponent.extensions);
        it["generates custom prefix"] = () => generates(CustomPrefixComponent.componentInfo, CustomPrefixComponent.extensions);
        it["generates component with default pool"] = () => generates(DefaultPoolComponent.componentInfo, DefaultPoolComponent.extensions);
        it["generates component with default pool and others"] = () => generates(MultiplePoolAndDefaultPoolComponent.componentInfo, MultiplePoolAndDefaultPoolComponent.extensions);

        it["generates component for class"] = () => generates(SomeClass.componentInfo, SomeClass.extensions);
        it["generates component for struct"] = () => generates(SomeStruct.componentInfo, SomeStruct.extensions);
    }