private void crsTransformationAdapterSubtypesCode()
        {
            // The below used code is implemented with F#
            // which normally uses explicit interfaces.
            // The F# code requires some additional coding
            // to make the implicit interfaces work as below
            // i.e. the methods can be invoked not only with
            // an interface typed object but also with
            // an object typed with some subtype (class)

            var c = new CrsTransformationAdapterDotSpatial();
            CrsTransformationAdapterBase     b = c;
            CrsTransformationAdapterBaseLeaf l = c;

            c.Transform(null, 123);
            c.TransformToCoordinate(null, 123);
            b.Transform(null, 123);
            b.TransformToCoordinate(null, 123);
            l.Transform(null, 123);
            l.TransformToCoordinate(null, 123);

            // Previously (before the git commit when this comment was added)
            // the above methods could not be compiled i.e.
            // the Transform methods were only available
            // when assigning the subtypes to the interface
            // i.e. the code below worked before but not
            // the transform method calls above before these lines with comments
            ICrsTransformationAdapter i = c;

            i.Transform(null, 123);
            i.TransformToCoordinate(null, 123);
        }
 private void VerifyExpectedEnumWhenNotRepresentingThirdPartLibrary(
     CrsTransformationAdapterBase crsTransformationAdapter,
     CrsTransformationAdapteeType expectedAdaptee
     )
 {
     VerifyExpectedEnumAndAssemblyVersion(
         crsTransformationAdapter,
         FileInfoVersion.FileInfoVersionNOTrepresentingThirdPartLibrary,
         expectedAdaptee
         );
 }
        public void test()
        {
            // The following method should NOT be possible to compile from this project
            // CrsTransformationResult._CreateCrsTransformationResult(null,null,null,true,null,null);

            // However, the exact same code above DOES indeed work
            // from the test project's
            // method 'CrsTransformationResultTest.internalMethodShouldBeAvailableFromTestProject'

            // Just for verifying that the following
            // does NOT compile from this project,
            // because it is an "internal" method.
            // However, it does work from the test project because
            // of this configuration of the proj file in the F# core project:
            //<ItemGroup>
            //  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
            //    <_Parameter1>Programmerare.CrsTransformations.Test</_Parameter1>
            //  </AssemblyAttribute>
            //</ItemGroup>


            CrsTransformationAdapterBase c = null;
            // the below methods was previously exposed
            // but should NOT be so anymore
            //c._GetFileInfoVersion();
            //var res = c._TransformHook(null, null);
            //var coord = c._TransformToCoordinateHook(null, null);
            // Actually the above methods have now been renamed
            // to "Strategy" instead of "Hook" because of the
            // design pattern being used now after some refactoring
            // that prevented exposing of methods considering
            // the fact that "protected" can not be used in F#
            // and "internal" was not appropriate since
            // other assemblies are implemening the base type.

            CrsTransformationAdapterBaseLeaf cc = null;
            // the below method was previously exposed
            // but should NOT be so anymore i.e. should no longer even be possible to compile:
            //var coordinate = cc._TransformToCoordinateHookLeaf(null, null);

            // The below types was previously exposed as result types for the Create methods
            //CrsTransformationAdapterLeafFactoryWithHardcodedImplementations c1 = CrsTransformationAdapterLeafFactory.Create();
            //CrsTransformationAdapterLeafFactoryWithConfiguredImplementations c2 = CrsTransformationAdapterLeafFactory.Create(new List<ICrsTransformationAdapter>());
            // Now instead both types are instead only exposed through the base type as below
            CrsTransformationAdapterLeafFactory c1 = CrsTransformationAdapterLeafFactory.Create();
            CrsTransformationAdapterLeafFactory c2 = CrsTransformationAdapterLeafFactory.Create(new List <ICrsTransformationAdapter>());
        }
 public void TransformToCoordinate_ShouldBePossibleToInvokeAndProduceTheSameResult_WhenTheInstanceIsTypedWithTheClassOrTheInterfaceSubTypes() {
     // Before the git commit when this test method 
     // and this comment was added, only the below a4 object
     // could invoke the method 'TransformToCoordinate'.
     // (because of F# explicit interfaces)
     // The other objects a1, a2 and a3 now also can invoke
     // the same method because of the "implicit interfaces"
     // implementation which was added in the same git commit as 
     // this comment and test method
     CrsTransformationAdapterMightyLittleGeodesy a1 = new CrsTransformationAdapterMightyLittleGeodesy();
     CrsTransformationAdapterBaseLeaf a2 = a1;
     CrsTransformationAdapterBase a3     = a1;
     ICrsTransformationAdapter a4        = a1;
     CrsCoordinate c1, c2, c3, c4;
     c1 = a1.TransformToCoordinate(validInputCoordinate, epsgNumberForSweref99TM);
     c2 = a2.TransformToCoordinate(validInputCoordinate, epsgNumberForSweref99TM);
     c3 = a3.TransformToCoordinate(validInputCoordinate, epsgNumberForSweref99TM);
     c4 = a4.TransformToCoordinate(validInputCoordinate, epsgNumberForSweref99TM);
     Assert.AreEqual(c1, c2);
     Assert.AreEqual(c1, c3);
     Assert.AreEqual(c1, c4);
 }
        private void VerifyExpectedEnumAndAssemblyVersion(
            CrsTransformationAdapterBase crsTransformationAdapter,
            FileInfoVersion expectedFileInfoVersion,
            CrsTransformationAdapteeType expectedEnumWithMatchingNameInlcudingVersionNumber
            )
        {
            Assert.AreEqual(
                expectedEnumWithMatchingNameInlcudingVersionNumber,
                crsTransformationAdapter.AdapteeType
                );
            FileInfoVersion fileInfoVersion = crsTransformationAdapter._GetFileInfoVersion();

            if (expectedFileInfoVersion.IsRepresentingThirdPartLibrary())
            {
                Assert.That(
                    fileInfoVersion.FileName, Does.EndWith(expectedFileInfoVersion.FileName),
                    "Likely failure reason: You have upgraded a version. If so, then upgrade both the enum value and the filename"
                    );
                Assert.AreEqual(
                    // This test is actually quite fragile for example
                    // regarding the .NET version
                    // (e.g. "net45" or "netstandard2.0")
                    // but remember that the purpose is to detect
                    // that a library (i.e. the binary file e.g. file size)
                    // has been modified and then maybe the enum specifying
                    // the version should be updated
                    expectedFileInfoVersion.FileSize,
                    fileInfoVersion.FileSize
                    );

                Assert.AreEqual(
                    expectedFileInfoVersion.Version,
                    fileInfoVersion.Version
                    );
            }
        }