public void CanCompileAssembly()
        {
            //-- arrange

            var backendUnderTest = new RoslynTypeFactoryBackend();

            var key1  = new TypeKey(this.GetType(), typeof(int), typeof(int), typeof(int), typeof(int), 1, 2, 3);
            var type1 = new TypeMember(new TypeGeneratorInfo(this.GetType(), key1));

            type1.Namespace  = "NS1";
            type1.Visibility = MemberVisibility.Public;
            type1.TypeKind   = TypeMemberKind.Class;
            type1.Name       = "ClassOne";

            //-- act

            var result = backendUnderTest.Compile(new[] { type1 });

            //-- assert

            result.Success.Should().BeTrue();
            result.Succeeded.Count.Should().Be(1);
            result.Succeeded[0].Type.Should().BeSameAs(type1);
            result.Failed.Count.Should().Be(0);
        }
        public void CanInstantiateCompiledProducts()
        {
            //-- arrange

            var backendUnderTest  = new RoslynTypeFactoryBackend();
            var compiledArtifacts = new Dictionary <TypeKey, IRuntimeTypeFactoryArtifact <object> >();

            backendUnderTest.ProductsLoaded += (products) => {
                foreach (var product in products)
                {
                    compiledArtifacts.Add(product.Key, (IRuntimeTypeFactoryArtifact <object>)product.Artifact);
                }
            };

            var key1  = new TypeKey(this.GetType(), typeof(int));
            var type1 = new TypeMember(new TypeGeneratorInfo(this.GetType(), key1), "NS1", MemberVisibility.Public, TypeMemberKind.Class, "ClassInt");

            var key2  = new TypeKey(this.GetType(), typeof(string));
            var type2 = new TypeMember(new TypeGeneratorInfo(this.GetType(), key2), "NS2", MemberVisibility.Public, TypeMemberKind.Class, "ClassString");

            //-- act

            var result      = backendUnderTest.Compile(new[] { type1, type2 });
            var classInt    = compiledArtifacts[key1].Constructor().NewInstance();
            var classString = compiledArtifacts[key2].Constructor().NewInstance();

            //-- assert

            result.Success.Should().BeTrue();
            compiledArtifacts.Count.Should().Be(2);
            classInt.GetType().FullName.Should().Be("NS1.ClassInt");
            classString.GetType().FullName.Should().Be("NS2.ClassString");
        }
        //-----------------------------------------------------------------------------------------------------------------------------------------------------

        private EqualityComparerTypeFactory CreateFactoryUnderTest()
        {
            var backend          = new RoslynTypeFactoryBackend();
            var mechanism        = new TypeLibrary <IRuntimeTypeFactoryArtifact>(backend);
            var factoryUnderTest = new EqualityComparerTypeFactory(mechanism);

            return(factoryUnderTest);
        }
        public void CanLoadPrecompiledAssembly()
        {
            //-- arrange

            TypeFactoryProduct <IRuntimeTypeFactoryArtifact>[] loadedProducts = null;
            int productsLoadedInvocationCount = 0;

            var backendUnderTest = new RoslynTypeFactoryBackend();

            backendUnderTest.ProductsLoaded += (products) => {
                loadedProducts = products;
                productsLoadedInvocationCount++;
            };

            //-- act

            backendUnderTest.LoadPrecompiledAssembly(this.GetType().GetTypeInfo().Assembly.Location);

            //-- assert

            var expectedKey1 = new TypeKey(typeof(TestFactory), typeof(IFirstContract));
            var expectedKey2 = new TypeKey(typeof(TestFactory), typeof(ISecondContract));

            productsLoadedInvocationCount.Should().Be(1);
            loadedProducts.Should().NotBeNull();
            loadedProducts.Length.Should().Be(2);

            loadedProducts[0].Key.Should().Be(expectedKey1);
            loadedProducts[0].Artifact.TypeKey.Should().Be(expectedKey1);
            loadedProducts[0].Artifact.RunTimeType.Should().BeSameAs(typeof(FirstContractImplementation));

            var instance1 = loadedProducts[0].Artifact.For <IFirstContract>().Constructor().NewInstance();

            instance1.Should().BeOfType <FirstContractImplementation>();

            loadedProducts[1].Key.Should().Be(expectedKey2);
            loadedProducts[1].Artifact.TypeKey.Should().Be(expectedKey2);
            loadedProducts[1].Artifact.RunTimeType.Should().BeSameAs(typeof(SecondContractImplementation));

            var instance2 = loadedProducts[1].Artifact.For <ISecondContract>().Constructor <int, string>().NewInstance(123, "ABC");

            instance2.Should().BeOfType <SecondContractImplementation>();
            instance2.IntValue.Should().Be(123);
            instance2.StringValue.Should().Be("ABC");
        }
        public void CanReportCompilationIssuesPerTypeMember()
        {
            //-- arrange

            var backendUnderTest = new RoslynTypeFactoryBackend();

            var type1 = new TypeMember("NS1", MemberVisibility.Public, TypeMemberKind.Class, "ClassOne");
            var type2 = new TypeMember("NS1", MemberVisibility.Private, TypeMemberKind.Class, "ClassTwo");
            var type3 = new TypeMember("NS1", MemberVisibility.Public, TypeMemberKind.Class, "ClassThree");
            var type4 = new TypeMember("NS1", MemberVisibility.Private, TypeMemberKind.Class, "ClassFour");

            //-- act

            var result = backendUnderTest.Compile(new[] { type1, type2, type3, type4 });

            //-- assert

            result.Success.Should().BeFalse();
            result.Succeeded.Count.Should().Be(0);

            result.Failed.Count.Should().Be(4);

            result.Failed[0].Success.Should().BeTrue();
            result.Failed[0].Diagnostics.Count.Should().Be(0);

            result.Failed[1].Success.Should().BeFalse();
            result.Failed[1].Diagnostics.Count.Should().Be(1);
            result.Failed[1].Diagnostics[0].Severity.Should().Be(CompilationDiagnosticSeverity.Error);
            result.Failed[1].Diagnostics[0].Code.Should().Be("CS1527");
            result.Failed[1].Diagnostics[0].Message.Should().NotBeNullOrEmpty();
            result.Failed[1].Diagnostics[0].SourceLocation.Should().NotBeNullOrEmpty();

            result.Failed[2].Success.Should().BeTrue();
            result.Failed[2].Diagnostics.Count.Should().Be(0);

            result.Failed[3].Success.Should().BeFalse();
            result.Failed[3].Diagnostics.Count.Should().Be(1);
            result.Failed[3].Diagnostics[0].Severity.Should().Be(CompilationDiagnosticSeverity.Error);
            result.Failed[3].Diagnostics[0].Code.Should().Be("CS1527");
            result.Failed[3].Diagnostics[0].Message.Should().NotBeNullOrEmpty();
            result.Failed[3].Diagnostics[0].SourceLocation.Should().NotBeNullOrEmpty();
        }
        public void CanPersistMethodInfoInTypeKey()
        {
            //-- arrange

            var method = this.GetType().GetMethods().First();

            var backendUnderTest = new RoslynTypeFactoryBackend();

            var sourceKey  = new TypeKey(this.GetType(), typeof(string), method.MetadataToken);
            var sourceType = new TypeMember(
                new TypeGeneratorInfo(this.GetType(), sourceKey),
                "NS1",
                MemberVisibility.Public,
                TypeMemberKind.Class,
                "ClassOne");

            TypeKey loadedKey = new TypeKey();

            backendUnderTest.ProductsLoaded += (products) => {
                var artifact  = products[0].Artifact;
                var attribute = artifact.RunTimeType.GetTypeInfo().GetCustomAttribute <TypeKeyAttribute>();
                loadedKey = attribute.ToTypeKey();
            };

            backendUnderTest.Compile(new[] { sourceType });

            //TypeBuilder builder

            ////-- act

            //var methodToken = loadedKey.ExtensionValue1;
            //MethodInfo loadedMethod = MethodInfo.GetMethodFromHandle(new RuntimeMethodHandle().)

            ////-- assert

            //result.Success.Should().BeTrue();
            //result.Succeeded.Count.Should().Be(1);
            //result.Succeeded[0].Type.Should().BeSameAs(sourceType);
            //result.Failed.Count.Should().Be(0);
        }
        public void CanGetCompiledProductSingleton()
        {
            //-- arrange

            var backendUnderTest  = new RoslynTypeFactoryBackend();
            var compiledArtifacts = new Dictionary <TypeKey, IRuntimeTypeFactoryArtifact <object> >();

            backendUnderTest.ProductsLoaded += (products) => {
                foreach (var product in products)
                {
                    compiledArtifacts.Add(product.Key, (IRuntimeTypeFactoryArtifact <object>)product.Artifact);
                }
            };

            var        key1  = new TypeKey(this.GetType(), typeof(int));
            TypeMember type1 = BuildClassWithIntAndStringProperties(key1);

            backendUnderTest.Compile(new[] { type1 });

            //-- act

            var obj1 = compiledArtifacts[key1].Constructor <int, string>().GetOrCreateSingleton(123, "ABC");
            var obj2 = compiledArtifacts[key1].Constructor <int, string>().GetOrCreateSingleton(456, "DEF");

            //-- assert

            obj1.Should().NotBeNull();
            obj2.Should().BeSameAs(obj1);

            dynamic dynamicObj2 = obj2;

            int    initializedIntValue    = dynamicObj2.IntValue;
            string initializedStringValue = dynamicObj2.StringValue;

            initializedIntValue.Should().Be(123);
            initializedStringValue.Should().Be("ABC");
        }
        public void CanInstantiateCompiledProductWithNonDefaultConstructor()
        {
            //-- arrange

            var backendUnderTest  = new RoslynTypeFactoryBackend();
            var compiledArtifacts = new Dictionary <TypeKey, IRuntimeTypeFactoryArtifact <object> >();

            backendUnderTest.ProductsLoaded += (products) => {
                foreach (var product in products)
                {
                    compiledArtifacts.Add(product.Key, (IRuntimeTypeFactoryArtifact <object>)product.Artifact);
                }
            };

            var        key1  = new TypeKey(this.GetType(), typeof(int));
            TypeMember type1 = BuildClassWithIntAndStringProperties(key1);

            //-- act

            var result = backendUnderTest.Compile(new[] { type1 });
            var obj    = compiledArtifacts[key1].Constructor <int, string>().NewInstance(123, "ABC");

            //-- assert

            result.Success.Should().BeTrue();
            compiledArtifacts.Count.Should().Be(1);
            obj.GetType().FullName.Should().Be("NS1.ClassOne");

            dynamic dynamicObj = obj;

            int    initializedIntValue    = dynamicObj.IntValue;
            string initializedStringValue = dynamicObj.StringValue;

            initializedIntValue.Should().Be(123);
            initializedStringValue.Should().Be("ABC");
        }