Inheritance: ILogicalTypeRegistry
        public static LogicalTypeRegistry Build()
        {
            var registry = new LogicalTypeRegistry();

            registry.AddMapping(new LogicalType("sys", "Guid"), typeof(Guid));
            registry.AddMapping(new LogicalType("sys", "StringToStringDictionary"), typeof(Dictionary<String, String>));

            registry.AddMapping(new LogicalType("tst", "ServiceCaseId"), typeof(ServiceCaseId));

            registry.AddMapping(new LogicalType("tst", "AggregateMemento.ServiceCaseId"), typeof(AggregateMemento<ServiceCaseId>));
            registry.AddMapping(new LogicalType("tst", "AggregateMemento.RoleIdentifier"), typeof(AggregateMemento<RoleIdentifier>));

            registry.AddMapping(new LogicalType("tst", "CustomerRoleIdentifier"), typeof(CustomerRoleIdentifier));
            registry.AddMapping(new LogicalType("tst", "CustomerServiceRepresentativeRoleIdentifier"), typeof(CustomerServiceRepresentativeRoleIdentifier));
            registry.AddMapping(new LogicalType("tst", "CustomerAgentRoleIdentifier"), typeof(CustomerAgentRoleIdentifier));

            registry.AddMapping(new LogicalType("tst", "CustomerRole"), typeof(HomogeneousRole<CustomerRoleIdentifier>));
            registry.AddMapping(new LogicalType("tst", "CustomerServiceRepresentativeRole"), typeof(HomogeneousRole<CustomerServiceRepresentativeRoleIdentifier>));
            registry.AddMapping(new LogicalType("tst", "CustomerAgentRole"), typeof(HomogeneousRole<CustomerAgentRoleIdentifier>));

            registry.AddMapping(new LogicalType("tst", "CustomerRole.Registered"), typeof(HomogeneousRole<CustomerRoleIdentifier>.Registered));
            registry.AddMapping(new LogicalType("tst", "CustomerServiceRepresentativeRole.Registered"), typeof(HomogeneousRole<CustomerServiceRepresentativeRoleIdentifier>.Registered));
            registry.AddMapping(new LogicalType("tst", "CustomerAgentRole.Registered"), typeof(HomogeneousRole<CustomerAgentRoleIdentifier>.Registered));

            registry.AddMapping(new LogicalType("tst", "ServiceCase"), typeof(ServiceCase));
            registry.AddMapping(new LogicalType("tst", "ServiceCase.Opened"), typeof(ServiceCase.Opened));
            registry.AddMapping(new LogicalType("tst", "ServiceCase.Snapshot"), typeof(ServiceCase.Snapshot));
            registry.AddMapping(new LogicalType("tst", "ServiceCase.CommunicationThreadStarted"), typeof(ServiceCase.CommunicationThreadStarted));
            registry.AddMapping(new LogicalType("tst", "ServiceCase.CaseDescription"), typeof(ServiceCase.CaseDescription));
            registry.AddMapping(new LogicalType("tst", "CommunicationThreadSnapshot"), typeof(CommunicationThreadSnapshot));
            registry.AddMapping(new LogicalType("tst", "ServiceCase.CommunicationRecorded"), typeof(ServiceCase.CommunicationRecorded));

            return registry;
        }
        public void CannotMapClosedLogicalTypeToOpenActualType()
        {
            var logicalType = LogicalType.Parse("syn:Maybe<sys:Int32>");
            var actualType = typeof(Maybe<>);

            var registry = new LogicalTypeRegistry();
            registry.Invoking(x => x.AddMapping(logicalType, actualType))
                .ShouldThrow<ArgumentException>();
        }
        public void CannotMapOpenTypesWithMismatchedArity()
        {
            var registry = new LogicalTypeRegistry();

            registry.Invoking(x => x.AddMapping(LogicalType.Parse("syn:Maybe"), typeof(Maybe<>)))
                .ShouldThrow<ArgumentException>();

            registry.Invoking(x => x.AddMapping(LogicalType.Parse("syn:Maybe`2"), typeof(Maybe<>)))
                .ShouldThrow<ArgumentException>();
        }
        public void OpenTypes_MapCorrectly()
        {
            var logicalType = LogicalType.Parse("syn:Maybe`1");
            var actualType = typeof(Maybe<>);

            var registry = new LogicalTypeRegistry();
            registry.AddMapping(logicalType, actualType);

            registry.LookupActualType(logicalType).Should().Be(actualType);
            registry.LookupLogicalType(actualType).Should().Be(logicalType);
        }
        public void ClosedTypes_MapCorrectly()
        {
            var logicalType = LogicalType.Parse("syn:Maybe<sys:Int32>");
            var actualType = typeof(Maybe<int>);

            var registry = new LogicalTypeRegistry();
            registry.AddMapping(logicalType, actualType);

            registry.LookupActualType(logicalType).Should().Be(actualType);
            registry.LookupLogicalType(actualType).Should().Be(logicalType);
        }
        public void SimpleMapping_BehavesCorrectly()
        {
            var logicalType = LogicalType.Parse("sys:String");
            var actualType = typeof(string);

            var registry = new LogicalTypeRegistry();
            registry.AddMapping(logicalType, actualType);

            registry.LookupActualType(logicalType).Should().Be(actualType);
            registry.LookupLogicalType(actualType).Should().Be(logicalType);
        }
        public void CannotAddDuplicateMappings()
        {
            var registry = new LogicalTypeRegistry();
            registry.AddMapping(LogicalType.Parse("sys:String"), typeof(string));

            registry.Invoking(x => x.AddMapping(LogicalType.Parse("sys:String"), typeof(int)))
                .ShouldThrow<ArgumentException>();

            registry.Invoking(x => x.AddMapping(LogicalType.Parse("tst:Description"), typeof(string)))
                .ShouldThrow<ArgumentException>();
        }
        public void LookupLogicalTypeUsingClosedActualType_ViaOpenMapping()
        {
            var registry = new LogicalTypeRegistry();
            registry.AddMapping(LogicalType.Parse("syn:Result`2"), typeof(Result<,>));
            registry.AddMapping(LogicalType.Parse("sys:Int32"), typeof(int));
            registry.AddMapping(LogicalType.Parse("sys:String"), typeof(string));

            registry.LookupLogicalType(typeof(Result<int, string>))
                .Should().Be(LogicalType.Parse("syn:Result<sys:Int32, sys:String>"));
        }