├── .editorconfig ├── .github └── workflows │ ├── ci-build.yml │ └── ci-publish.yml ├── .gitignore ├── CSharpExt.Benchmark ├── BinaryMemoryReadStream.cs ├── BinaryTests.cs ├── CSharpExt.Benchmark.csproj ├── Program.cs └── Results │ ├── CSharpExt.Benchmark.BinaryMemoryReadStream-report-github.md │ └── CSharpExt.Benchmark.BinaryTests-report-github.md ├── CSharpExt.UnitTests ├── AutoFixture │ ├── ContainerAutoDataTests.cs │ ├── ErrorResponseBuilderTests.cs │ ├── ErrorResponseParameterBuilderTests.cs │ ├── ExtendedListBuilderTests.cs │ ├── GetResponseBuilderTests.cs │ ├── GetResponseParameterBuilderTests.cs │ ├── MakeFileExistTests.cs │ ├── ObservableSpecimenCommand.cs │ ├── PathBuilderTests.cs │ └── SplitEnumerableIntoSubtypesTests.cs ├── Autofac │ ├── CheckIsDelegateFactoryTests.cs │ ├── FillUsagesTests.cs │ ├── Integration │ │ ├── Circular.cs │ │ ├── ConcreteInsteadOfInterface.cs │ │ ├── DelegateFactoryReturn.cs │ │ ├── DependencyMissingDependency.cs │ │ ├── Pass.cs │ │ ├── Self.cs │ │ ├── TopLevelValidation.cs │ │ └── UnregisteredFactoryParameter.cs │ ├── IsAllowableEnumerableTests.cs │ ├── IsAllowableFuncTests.cs │ ├── IsAllowableLazyTests.cs │ ├── RegistrationsTests.cs │ ├── ValidateAllRegistrationsTests.cs │ ├── ValidateTypeCtorTests.cs │ ├── ValidateTypeTests.cs │ └── ValidatorTests.cs ├── BasicSubstitutionRangeStreamTests.cs ├── BinaryMemoryStreamTests.cs ├── BinaryReadStreamTests.cs ├── CSharpExt.UnitTests.csproj ├── DictionaryExtTests.cs ├── DotNetCli │ └── QueryNugetListingTests.cs ├── Enum │ ├── ConvertTests.cs │ ├── EnumerateContainedFlagsTests.cs │ ├── FlagTests.cs │ ├── IsDefinedTests.cs │ ├── NumEntriesTests.cs │ ├── TestEnums.cs │ ├── ToStringFastTests.cs │ ├── TryGetEnumTypeTests.cs │ ├── TryGetNthTests.cs │ └── ValuesTests.cs ├── EnumerableExtTests.cs ├── FileNameTests.cs ├── FramedStreamTests.cs ├── IBinaryStreamTests.cs ├── IFileSystemExtTests.cs ├── IO │ ├── DirectoryPathJsonConverterTests.cs │ ├── FilePathJsonConverterTests.cs │ ├── Files │ │ ├── ConverterDirectoryPathSerialization.json │ │ ├── ConverterFilePathSerialization.json │ │ ├── NakedDirectoryPathSerialization.json │ │ ├── NakedFilePathSerialization.json │ │ ├── OldDirectoryPathSerialization.json │ │ └── OldFilePathSerialization.json │ └── SingleApplicationEnforcerTests.cs ├── ListExtTests.cs ├── ModuleInitializer.cs ├── ObservableExtTests.cs ├── P2DoubleTests.cs ├── P2FloatTests.cs ├── P2Int16Tests.cs ├── P2IntTests.cs ├── P2UInt8Tests.cs ├── P3DoubleTests.cs ├── P3FloatTests.cs ├── P3Int16Tests.cs ├── P3IntTests.cs ├── P3UInt16Tests.cs ├── P3UInt8Tests.cs ├── PreSortedListExtTests.cs ├── Processes │ └── ProcessRunnerTests.cs ├── RangeCollectionTests.cs ├── RangeInt64Tests.cs ├── ShouldlyExtTests.cs ├── SortedListExtTests.cs ├── SortingListDictionaryTests.cs ├── SortingListTests.cs ├── SourceGenerators │ ├── AssemblyVersionGeneratorTests.BasicGeneration#AssemblyVersions.g.verified.cs │ ├── AssemblyVersionGeneratorTests.BasicUsage#AssemblyVersions.g.verified.cs │ ├── AssemblyVersionGeneratorTests.GenericPassed#AssemblyVersions.g.verified.cs │ ├── AssemblyVersionGeneratorTests.GenericPassed.verified.txt │ ├── AssemblyVersionGeneratorTests.NamespaceSpecified#AssemblyVersions.g.verified.cs │ └── AssemblyVersionGeneratorTests.cs ├── StreamExtTests.cs ├── Structs │ ├── FileSystems │ │ ├── DirectoryPathTests.cs │ │ └── FilePathTests.cs │ └── MemorySliceTests.cs ├── StructuredStrings │ ├── CommentTests.cs │ └── StructuredStringBuilderTests.cs ├── TempFileFolderTests.cs ├── TestDataAttribute.cs ├── TestHelper.cs ├── TypeExtTests.cs ├── Utility.cs ├── WrappedInt.cs └── XmlExtTests.cs ├── Directory.Build.props ├── Directory.Build.targets ├── Directory.Packages.props ├── LICENSE.txt ├── Noggog.Autofac ├── ContainerBuilderExt.cs ├── Modules │ └── NoggogModule.cs ├── Noggog.Autofac.csproj ├── RegistrationBuilderExt.cs ├── TestingPermissions.cs ├── Validation │ ├── AutofacValidationException.cs │ ├── CircularReferenceChecker.cs │ ├── ConcreteTypeToDependenciesProvider.cs │ ├── GetUsages.cs │ ├── IsAutofacType.cs │ ├── Registrations.cs │ ├── Rules │ │ ├── CheckIsDelegateFactory.cs │ │ ├── IValidationRule.cs │ │ ├── IsAllowableEnumerable.cs │ │ ├── IsAllowableFunc.cs │ │ ├── IsAllowableLazy.cs │ │ └── SkipLoggerRule.cs │ ├── TypeToDependenciesProvider.cs │ ├── ValidateTracker.cs │ ├── ValidateType.cs │ ├── ValidateTypeCtor.cs │ ├── ValidateTypes.cs │ ├── ValidationFixture.cs │ ├── ValidationModule.cs │ └── Validator.cs └── ValidationMixIn.cs ├── Noggog.CSharpExt.Json ├── IO │ ├── DirectoryPathJsonConverter.cs │ └── FilePathJsonConverter.cs ├── JsonConvertersMixIn.cs └── Noggog.CSharpExt.Json.csproj ├── Noggog.CSharpExt.Windows ├── IO │ ├── FileAssociations.cs │ └── SingleApplicationEnforcer.cs └── Noggog.CSharpExt.Windows.csproj ├── Noggog.CSharpExt.sln ├── Noggog.CSharpExt ├── Comparers │ ├── FuncEqualityComparer.cs │ ├── ReferenceEqualityComparer.cs │ └── WeakReferenceEquatable.cs ├── CompatibilitySuppressions.xml ├── Containers │ ├── Array2d.cs │ ├── Cache.cs │ ├── Common │ │ ├── ICollectionGetter.cs │ │ └── IDictionaryGetter.cs │ ├── DictionaryCovariantWrapper.cs │ ├── ExtendedList.cs │ ├── Interfaces │ │ ├── IArray2d.cs │ │ ├── ICache.cs │ │ ├── IExtendedList.cs │ │ ├── IKeyValue.cs │ │ ├── IReadOnlyCache.cs │ │ ├── ISortedList.cs │ │ └── ISortingListDictionary.cs │ ├── SingleCollection.cs │ ├── SliceList.cs │ ├── SortingList.cs │ └── SortingListDictionary.cs ├── Disposables │ └── DisposableBucket.cs ├── DotNetCli │ └── DI │ │ ├── DotNetCommandPathProvider.cs │ │ ├── DotNetCommandStartConstructor.cs │ │ ├── IQueryNugetListing.cs │ │ ├── NugetListingParser.cs │ │ ├── NugetListingQuery.cs │ │ └── ProcessNugetQueryResults.cs ├── Enums │ ├── Enums.cs │ └── SetTo.cs ├── Extensions │ ├── ActionExt.cs │ ├── ArrayExt.cs │ ├── AsyncEnumerableExt.cs │ ├── BitVector32Ext.cs │ ├── ByteExt.cs │ ├── CacheExt.cs │ ├── CancellationExt.cs │ ├── ChangeSetExt.cs │ ├── CollectionExt.cs │ ├── ColorExt.cs │ ├── CompositeDisposableExt.cs │ ├── DictionaryExt.cs │ ├── DirectoryInfoExt.cs │ ├── DoubleExt.cs │ ├── EnumExt.cs │ ├── EnumerableExt.cs │ ├── ExceptionExt.cs │ ├── FloatExt.cs │ ├── HashCodeExt.cs │ ├── HashSetExt.cs │ ├── ICollectionExt.cs │ ├── IDisposableExt.cs │ ├── IFileSystemExt.cs │ ├── Int16Ext.cs │ ├── Int32Ext.cs │ ├── Int64Ext.cs │ ├── Int8Ext.cs │ ├── ListExt.cs │ ├── MathExt.cs │ ├── MemberInfoExt.cs │ ├── ObjectExt.cs │ ├── ObservableExt.cs │ ├── ParallelQueryExt.cs │ ├── PathExt.cs │ ├── PreSortedListExt.cs │ ├── QueueExt.cs │ ├── RangeDoubleExt.cs │ ├── RangeIntExt.cs │ ├── SortedListExt.cs │ ├── SourceCacheExt.cs │ ├── SourceListExt.cs │ ├── SpanExt.cs │ ├── StackExt.cs │ ├── StreamExt.cs │ ├── StringExt.cs │ ├── SymbolExtensions.cs │ ├── TaskExt.cs │ ├── TypeExt.cs │ ├── UInt16Ext.cs │ ├── UInt32Ext.cs │ ├── UInt64Ext.cs │ └── XmlExt.cs ├── IO │ ├── CurrentDirectoryProvider.cs │ ├── DeepCopyDirectory.cs │ ├── DeleteEntireDirectory.cs │ ├── EnvironmentTemporaryDirectoryProvider.cs │ ├── ExportStringToFile.cs │ ├── ICreateStream.cs │ ├── TempFile.cs │ ├── TempFileProvider.cs │ ├── TempFolder.cs │ └── TempFolderProvider.cs ├── Interfaces │ ├── IClearable.cs │ ├── ISelectable.cs │ └── IShallowCloneable.cs ├── IsExternalInit.cs ├── Noggog.CSharpExt.csproj ├── NullableAttributes.cs ├── Processes │ ├── DI │ │ ├── ProcessFactory.cs │ │ └── ProcessRunner.cs │ ├── ProcessResult.cs │ └── ProcessWrapper.cs ├── Properties │ └── AssemblyInfo.cs ├── Reactive │ ├── ISchedulerProvider.cs │ ├── WatchDirectory.cs │ └── WatchFile.cs ├── Streams │ ├── Binary │ │ ├── BasicSubstitutionRangeStream.cs │ │ ├── BigEndianBinaryMemoryReadStream.cs │ │ ├── BigEndianBinaryMemoryWriteStream.cs │ │ ├── BinaryMemoryReadStream.cs │ │ ├── BinaryMemoryWriteStream.cs │ │ ├── BinaryReadStream.cs │ │ ├── BinaryWriteStream.cs │ │ ├── BinaryWriteWrapper.cs │ │ ├── ByteMemorySliceStream.cs │ │ ├── IBinaryMemoryWriteStream.cs │ │ ├── IBinaryReadStream.cs │ │ ├── IBinaryWriteStream.cs │ │ ├── LittleEndianBinaryMemoryReadStream.cs │ │ ├── LittleEndianBinaryMemoryWriteStream.cs │ │ └── MemoryTributary.cs │ └── FramedStream.cs ├── Structs │ ├── ErrorResponse.cs │ ├── FileSystems │ │ ├── DirectoryPath.cs │ │ ├── FileName.cs │ │ ├── FilePath.cs │ │ └── IPath.cs │ ├── GetResponse.cs │ ├── HashableDecimal.cs │ ├── IndexedItem.cs │ ├── KeyValue.cs │ ├── LastMarkedItem.cs │ ├── LifecycleActions.cs │ ├── MemberAccessor.cs │ ├── MemorySlice.cs │ ├── Numbers │ │ ├── Percent.cs │ │ └── UDouble.cs │ ├── Points │ │ ├── P2Double.cs │ │ ├── P2Float.cs │ │ ├── P2Int.cs │ │ ├── P2Int16.cs │ │ ├── P2IntValue.cs │ │ ├── P2UInt8.cs │ │ ├── P3Double.cs │ │ ├── P3Float.cs │ │ ├── P3Int.cs │ │ ├── P3Int16.cs │ │ ├── P3IntValue.cs │ │ ├── P3UInt16.cs │ │ └── P3UInt8.cs │ ├── Ranges │ │ ├── Basic Primitives │ │ │ ├── RangeDouble.cs │ │ │ ├── RangeFloat.cs │ │ │ ├── RangeInt16.cs │ │ │ ├── RangeInt32.cs │ │ │ ├── RangeInt64.cs │ │ │ ├── RangeInt8.cs │ │ │ ├── RangeUDouble.cs │ │ │ ├── RangeUInt16.cs │ │ │ ├── RangeUInt32.cs │ │ │ ├── RangeUInt64.cs │ │ │ └── RangeUInt8.cs │ │ └── RangeCollection.cs │ ├── StringCaseAgnostic.cs │ └── TryGet.cs ├── StructuredStrings │ ├── Brace.cs │ ├── CSharp │ │ ├── AccessModifier.cs │ │ ├── CSharpStructuredStringBuilderMixIn.cs │ │ ├── Call.cs │ │ ├── Class.cs │ │ ├── CurlyBrace.cs │ │ ├── Function.cs │ │ ├── If.cs │ │ ├── Namespace.cs │ │ ├── ObjectType.cs │ │ ├── PropertyCtor.cs │ │ └── Region.cs │ ├── CommaCollection.cs │ ├── Comment.cs │ ├── Depth.cs │ ├── IPrintable.cs │ ├── Line.cs │ ├── StructuredStringBuilder.cs │ └── StructuredStringsMixIn.cs ├── Time │ └── NowProvider.cs ├── Utility │ ├── AssemblyLoading.cs │ ├── AsyncLazy.cs │ ├── AsyncLock.cs │ ├── ChildProcessTracker.cs │ ├── ConsoleThrottler.cs │ ├── DelegateBuilder.cs │ ├── FileComparison.cs │ ├── FolderCleaner.cs │ ├── RandomSource.cs │ ├── ShowSelectedInExplorer.cs │ └── TaskCompletionSource.cs ├── WorkEngine │ ├── INumWorkThreadsController.cs │ ├── IWorkDropoff.cs │ ├── IWorkQueue.cs │ ├── InlineWorkDropoff.cs │ ├── NoPreferenceWorkDropoff.cs │ ├── ParallelWorkDropoff.cs │ ├── ToDo.cs │ ├── WorkConsumer.cs │ └── WorkDropoff.cs └── XML │ ├── DocumentWrapper.cs │ └── ElementWrapper.cs ├── Noggog.Nuget.Tests ├── AnalyzeNugetConfigTests.cs ├── CorruptErrorTests.cs ├── MissingNugetOrgErrorTests.cs ├── Noggog.Nuget.Tests.csproj └── NotExistsErrorTests.cs ├── Noggog.Nuget ├── Errors │ ├── CorruptError.cs │ ├── INugetErrorSolution.cs │ ├── MissingNugetOrgError.cs │ └── NotExistsError.cs ├── Noggog.Nuget.csproj └── Services │ └── Singleton │ ├── AnalyzeNugetConfig.cs │ └── NugetConfigPathProvider.cs ├── Noggog.SourceGenerators ├── AssemblyVersion │ └── AssemblyVersionGenerator.cs └── Noggog.SourceGenerators.csproj ├── Noggog.Testing ├── AutoFixture │ ├── Array2dBuilder.cs │ ├── CancellationBuilder.cs │ ├── ContainerAutoData.cs │ ├── ContainerAutoDataCustomization.cs │ ├── CurrentDirectoryPathProviderBuilder.cs │ ├── DefaultAutoData.cs │ ├── DefaultCustomization.cs │ ├── ErrorResponseBuilder.cs │ ├── ErrorResponseParameterBuilder.cs │ ├── ExtendedListBuilder.cs │ ├── FileSystemBuilder.cs │ ├── GetResponseBuilder.cs │ ├── GetResponseParameterBuilder.cs │ ├── IFileSystemEnvironmentInstructions.cs │ ├── LazyBuilder.cs │ ├── MakeFileExist.cs │ ├── MemberAutoDataImprovedAttribute.cs │ ├── ObservableEmptyBehavior.cs │ ├── ObservableSpecimenCommand.cs │ ├── PathBuilder.cs │ ├── ProcessBuilder.cs │ ├── SchedulerBuilder.cs │ ├── SpecimenBuilderFor.cs │ ├── SplitEnumerableIntoSubtypes.cs │ ├── TargetFileSystem.cs │ └── Testing │ │ └── SpecimenContextSubstituteExt.cs ├── Extensions │ ├── ContainerBuilderExt.cs │ ├── NSubstituteExtensions.cs │ ├── ShouldlyExt.cs │ ├── TestableObservableExt.cs │ └── TestableObserverExt.cs ├── FileSystem │ ├── MockFileSystemWatcher.cs │ ├── NoggogMockFileSystem.cs │ └── TestingFileSystem.cs ├── IO │ ├── DisposeTesterStream.cs │ ├── DisposeTesterWrapStream.cs │ ├── LengthLiarStream.cs │ └── PathingUtil.cs ├── Noggog.Testing.csproj ├── Noggog.Testing.csproj.DotSettings ├── TestClassData │ ├── ErrorResponseSuccessFailData.cs │ └── MemberData.cs └── TestingPermissions.cs ├── Noggog.WPF ├── Behaviors │ └── ScrollViewCorrector.cs ├── Constants │ ├── Brushes.cs │ └── Colors.cs ├── Containers │ ├── DerivativeSelectedCollection.cs │ └── SourceListUiFunnel.cs ├── Controls │ ├── Controls.xaml │ ├── EditableTextBlock.xaml │ ├── EditableTextBlock.xaml.cs │ ├── ErroredTextBox.cs │ ├── Helpers │ │ └── ControlsHelper.cs │ ├── PathPicker.xaml │ ├── PathPicker.xaml.cs │ └── StatusIndicator.cs ├── Converters │ ├── Converters.xaml │ ├── DirectoryPathConverter.cs │ ├── EnumDescriptionConverter.cs │ ├── EnumToIntConverter.cs │ ├── FilePathConverter.cs │ ├── InverseBooleanConverter.cs │ ├── IsNotEmptyVisibilityConverter.cs │ ├── IsNotNullVisibilityConverter.cs │ ├── StringIsWhitespaceBooleanConverter.cs │ ├── VisibilityConverter.cs │ └── VisibilityHiddenConverter.cs ├── Drag │ ├── Drag.cs │ ├── DragEventParams.cs │ ├── DragSources.cs │ └── DragTargets.cs ├── DragAdorner.cs ├── Enums │ └── StatusIndicatorState.cs ├── Everything.xaml ├── Extensions │ ├── CommandExt.cs │ ├── DependencyObjectExt.cs │ ├── ListBoxExt.cs │ ├── ObservableExt.cs │ ├── ReactiveObjectExt.cs │ ├── RxUIWhenAnyFallbackExperiment.cs │ ├── TextBoxExt.cs │ ├── TextEditorExtensions.cs │ └── WindowExt.cs ├── FodyWeavers.xml ├── FodyWeavers.xsd ├── ImageUtility.cs ├── Noggog.WPF.csproj ├── NoggogCommand.cs ├── NoggogControl.cs ├── NoggogUserControl.cs ├── SchedulerProvider.cs ├── TypicalTheming.xaml ├── UserControlRx.cs ├── VMs │ ├── CommandVM.cs │ ├── PathPickerVM.cs │ └── SelectedVm.cs └── ViewModel.cs ├── README.md ├── Settings.XamlStyler └── Snippets ├── RxOAPH.snippet ├── guiprop.snippet ├── guipropdp.snippet ├── guipropdpro.snippet └── guipropdprx.snippet /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | end_of_line = crlf 4 | 5 | [*.cs] 6 | 7 | # CS4014: Task not awaited 8 | dotnet_diagnostic.CS4014.severity = error 9 | 10 | # CS1998: Async function does not contain await 11 | dotnet_diagnostic.CS1998.severity = silent 12 | 13 | # CS1591: Missing XML comment for publicly visible type or member 14 | dotnet_diagnostic.CS1591.severity = silent 15 | 16 | # CLASS0001: Seal classes that do not have any virtual or abstract methods, properties, events, or indexers 17 | dotnet_diagnostic.CLASS0001.severity = silent -------------------------------------------------------------------------------- /CSharpExt.Benchmark/CSharpExt.Benchmark.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0;net7.0;net8.0 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /CSharpExt.Benchmark/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace CSharpExt.Benchmark; 4 | 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | BenchmarkRunner.Run(); 10 | BenchmarkRunner.Run(); 11 | } 12 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/AutoFixture/ContainerAutoDataTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | using Autofac; 3 | using Noggog.Testing.AutoFixture; 4 | using Shouldly; 5 | 6 | namespace CSharpExt.UnitTests.AutoFixture; 7 | 8 | public class ContainerAutoDataTests 9 | { 10 | public class TypicalModule : Module 11 | { 12 | protected override void Load(ContainerBuilder builder) 13 | { 14 | builder.RegisterType() 15 | .AsImplementedInterfaces().SingleInstance(); 16 | builder.RegisterType() 17 | .AsImplementedInterfaces().SingleInstance(); 18 | } 19 | } 20 | 21 | public interface ISomething 22 | { 23 | } 24 | 25 | public class Something : ISomething 26 | { 27 | } 28 | 29 | public interface IMissing 30 | { 31 | } 32 | 33 | public interface ITargetMissing 34 | { 35 | } 36 | 37 | public class TargetMissing : ITargetMissing 38 | { 39 | public TargetMissing(IMissing missing) 40 | { 41 | 42 | } 43 | } 44 | 45 | [Theory, ContainerAutoData(typeof(TypicalModule))] 46 | public void Typical(ISomething something, ISomething something2, int i) 47 | { 48 | something.ShouldBeOfType(); 49 | something.ShouldBeSameAs(something2); 50 | } 51 | 52 | [Theory, ContainerAutoData(typeof(TypicalModule))] 53 | public void Unrelated(IFileSystem missing, int i) 54 | { 55 | } 56 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/AutoFixture/ExtendedListBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests.AutoFixture; 6 | 7 | public class ExtendedListBuilderTests 8 | { 9 | [Theory, DefaultAutoData] 10 | public void ExtendedListTest( 11 | ExtendedList list, 12 | IExtendedList listInterf) 13 | { 14 | list.Count.ShouldNotBe(0); 15 | list.ShouldBeUnique(); 16 | listInterf.Count.ShouldNotBe(0); 17 | listInterf.ShouldBeUnique(); 18 | } 19 | 20 | [Theory, DefaultAutoData] 21 | public void ExtendedListClassTest( 22 | ExtendedList list, 23 | IExtendedList listInterf) 24 | { 25 | list.Count.ShouldNotBe(0); 26 | list.ShouldBeUnique(); 27 | listInterf.Count.ShouldNotBe(0); 28 | listInterf.ShouldBeUnique(); 29 | } 30 | 31 | public record TestClass(int Int, string String); 32 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/AutoFixture/MakeFileExistTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions.TestingHelpers; 2 | using AutoFixture.Kernel; 3 | using Noggog; 4 | using Noggog.Testing.AutoFixture; 5 | using Noggog.Testing.AutoFixture.Testing; 6 | 7 | namespace CSharpExt.UnitTests.AutoFixture; 8 | 9 | public class MakeFileExistTests 10 | { 11 | [Theory, DefaultAutoData] 12 | public void FileMadeInFileSystem( 13 | FilePath path, 14 | MockFileSystem mockFileSystem, 15 | ISpecimenContext context, 16 | MakeFileExist sut) 17 | { 18 | context.MockToReturn(mockFileSystem); 19 | sut.MakeExist(path, context); 20 | mockFileSystem.File.Exists(path); 21 | } 22 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/FillUsagesTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.Autofac.Validation; 2 | using Noggog.Testing.Extensions; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests.Autofac; 6 | 7 | public class FillUsagesTests 8 | { 9 | class NoCtorClass 10 | { 11 | } 12 | 13 | class EmptyCtorClass 14 | { 15 | public EmptyCtorClass() 16 | { 17 | 18 | } 19 | } 20 | 21 | [Fact] 22 | public void EmptyCtors() 23 | { 24 | new GetUsages().Get( 25 | typeof(NoCtorClass), 26 | typeof(EmptyCtorClass)) 27 | .ShouldBeEmpty(); 28 | } 29 | 30 | class SomeParams 31 | { 32 | public SomeParams( 33 | NoCtorClass otherClass, 34 | SubClass subClass) 35 | { 36 | } 37 | } 38 | 39 | class SubClass 40 | { 41 | public SubClass(EmptyCtorClass otherClass) 42 | { 43 | 44 | } 45 | } 46 | 47 | [Fact] 48 | public void Typical() 49 | { 50 | new GetUsages().Get( 51 | typeof(SomeParams)) 52 | .ShouldEqualEnumerable( 53 | typeof(NoCtorClass), 54 | typeof(SubClass)); 55 | } 56 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/Integration/ConcreteInsteadOfInterface.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.Autofac.Validation; 3 | 4 | namespace CSharpExt.UnitTests.Autofac.Integration; 5 | 6 | public class ConcreteInsteadOfInterface : IClassFixture 7 | { 8 | private readonly ValidationFixture _validationFixture; 9 | 10 | public ConcreteInsteadOfInterface(ValidationFixture validationFixture) 11 | { 12 | _validationFixture = validationFixture; 13 | } 14 | 15 | interface IService {} 16 | record Service() : IService; 17 | 18 | record TopLevel(Service service); 19 | 20 | [Fact] 21 | public void Test() 22 | { 23 | var builder = new ContainerBuilder(); 24 | builder.RegisterType().AsSelf(); 25 | builder.RegisterType().As(); 26 | var cont = builder.Build(); 27 | Assert.Throws(() => 28 | { 29 | using var disp = _validationFixture.GetValidator(cont, out var validate); 30 | validate.Validate(typeof(TopLevel)); 31 | }); 32 | } 33 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/Integration/Pass.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.Autofac.Validation; 3 | 4 | namespace CSharpExt.UnitTests.Autofac.Integration; 5 | 6 | public class Pass : IClassFixture 7 | { 8 | private readonly ValidationFixture _validationFixture; 9 | 10 | public Pass(ValidationFixture validationFixture) 11 | { 12 | _validationFixture = validationFixture; 13 | } 14 | 15 | record COtherClass(); 16 | record CTopLevel(COtherClass OtherClass); 17 | 18 | interface IOtherClass {} 19 | record OtherClass() : IOtherClass; 20 | 21 | interface ITopLevel {} 22 | record TopLevel(IOtherClass OtherClass) : ITopLevel; 23 | 24 | [Fact] 25 | public void Concrete() 26 | { 27 | var builder = new ContainerBuilder(); 28 | builder.RegisterType().AsSelf(); 29 | builder.RegisterType().AsSelf(); 30 | var cont = builder.Build(); 31 | using var disp = _validationFixture.GetValidator(cont, out var validate); 32 | validate.Validate(typeof(CTopLevel)); 33 | } 34 | 35 | [Fact] 36 | public void Interface() 37 | { 38 | var builder = new ContainerBuilder(); 39 | builder.RegisterType().As(); 40 | builder.RegisterType().As(); 41 | var cont = builder.Build(); 42 | using var disp = _validationFixture.GetValidator(cont, out var validate); 43 | validate.Validate(typeof(ITopLevel)); 44 | } 45 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/Integration/Self.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.Autofac; 3 | using Noggog.Autofac.Validation; 4 | 5 | namespace CSharpExt.UnitTests.Autofac.Integration; 6 | 7 | public class Self 8 | { 9 | [Fact] 10 | public void ValidateSelf() 11 | { 12 | using var scope = ValidationMixIn.Container.BeginLifetimeScope(cfg => 13 | { 14 | var builder = new ContainerBuilder(); 15 | builder.RegisterModule(); 16 | builder.RegisterInstance(ValidationMixIn.Container).As(); 17 | cfg.RegisterInstance(builder.Build()).As(); 18 | }); 19 | scope.Resolve().Validate(typeof(IValidator)); 20 | } 21 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/Integration/TopLevelValidation.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.Autofac.Validation; 3 | 4 | namespace CSharpExt.UnitTests.Autofac.Integration; 5 | 6 | public class TopLevelValidation : IClassFixture 7 | { 8 | private readonly ValidationFixture _validationFixture; 9 | 10 | public TopLevelValidation(ValidationFixture validationFixture) 11 | { 12 | _validationFixture = validationFixture; 13 | } 14 | 15 | interface IOtherClass {} 16 | record OtherClass() : IOtherClass; 17 | 18 | interface ITopLevel {} 19 | record TopLevel(IOtherClass OtherClass) : ITopLevel; 20 | 21 | [Fact] 22 | public void Interface() 23 | { 24 | var builder = new ContainerBuilder(); 25 | builder.RegisterType().As(); 26 | var cont = builder.Build(); 27 | Assert.Throws(() => 28 | { 29 | using var disp = _validationFixture.GetValidator(cont, out var validate); 30 | validate.Validate(typeof(ITopLevel)); 31 | }); 32 | } 33 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/Integration/UnregisteredFactoryParameter.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.Autofac.Validation; 3 | 4 | namespace CSharpExt.UnitTests.Autofac.Integration; 5 | 6 | public class UnregisteredFactoryParameter: IClassFixture 7 | { 8 | private readonly ValidationFixture _validationFixture; 9 | 10 | public UnregisteredFactoryParameter(ValidationFixture validationFixture) 11 | { 12 | _validationFixture = validationFixture; 13 | } 14 | 15 | record Missing(); 16 | 17 | class OtherClass 18 | { 19 | public delegate OtherClass Factory(Missing m); 20 | 21 | public OtherClass(Missing m) 22 | { 23 | } 24 | } 25 | 26 | record TopLevel(OtherClass.Factory OtherClass); 27 | 28 | [Fact] 29 | public void Test() 30 | { 31 | var builder = new ContainerBuilder(); 32 | builder.RegisterType().AsSelf(); 33 | builder.RegisterType().AsSelf(); 34 | var cont = builder.Build(); 35 | using var disp = _validationFixture.GetValidator(cont, out var validate); 36 | validate.Validate(typeof(TopLevel)); 37 | } 38 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/IsAllowableEnumerableTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.Autofac.Validation.Rules; 2 | using Noggog.Testing.AutoFixture; 3 | using NSubstitute; 4 | using Shouldly; 5 | 6 | namespace CSharpExt.UnitTests.Autofac; 7 | 8 | public class IsAllowableEnumerableTests 9 | { 10 | [Theory, TestData] 11 | public void Typical(IsAllowableEnumerable sut) 12 | { 13 | sut.IsAllowed(typeof(IEnumerable)) 14 | .ShouldBeTrue(); 15 | 16 | sut.ValidateTypeCtor.Received(1).Validate(typeof(string), null); 17 | } 18 | 19 | [Theory, TestData] 20 | public void Array(IsAllowableEnumerable sut) 21 | { 22 | sut.IsAllowed(typeof(string[])) 23 | .ShouldBeTrue(); 24 | 25 | sut.ValidateTypeCtor.Received(1).Validate(typeof(string), null); 26 | } 27 | 28 | [Theory, TestData] 29 | public void NotEnumerable(IsAllowableEnumerable sut) 30 | { 31 | sut.IsAllowed(typeof(string)) 32 | .ShouldBeFalse(); 33 | } 34 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/IsAllowableFuncTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.Autofac.Validation.Rules; 2 | using Noggog.Testing.AutoFixture; 3 | using NSubstitute; 4 | using Shouldly; 5 | 6 | namespace CSharpExt.UnitTests.Autofac; 7 | 8 | public class IsAllowableFuncTests 9 | { 10 | [Theory, TestData] 11 | public void Typical(IsAllowableFunc sut) 12 | { 13 | sut.IsAllowed(typeof(Func)) 14 | .ShouldBeTrue(); 15 | sut.ValidateTypeCtor.Received(1).Validate(typeof(string), Arg.Any?>()); 16 | } 17 | 18 | [Theory, TestData] 19 | public void TooManyArgs(IsAllowableFunc sut) 20 | { 21 | sut.IsAllowed(typeof(Func)) 22 | .ShouldBeFalse(); 23 | } 24 | 25 | [Theory, TestData] 26 | public void NotEnumerable(IsAllowableFunc sut) 27 | { 28 | sut.IsAllowed(typeof(string)) 29 | .ShouldBeFalse(); 30 | } 31 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/IsAllowableLazyTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.Autofac.Validation.Rules; 2 | using Noggog.Testing.AutoFixture; 3 | using NSubstitute; 4 | using Shouldly; 5 | 6 | namespace CSharpExt.UnitTests.Autofac; 7 | 8 | public class IsAllowableLazyTests 9 | { 10 | [Theory, TestData] 11 | public void Typical(IsAllowableLazy sut) 12 | { 13 | sut.IsAllowed(typeof(Lazy)) 14 | .ShouldBeTrue(); 15 | sut.ValidateTypeCtor.Received(1).Validate(typeof(string), Arg.Any>()); 16 | } 17 | 18 | [Theory, TestData] 19 | public void NotLazy(IsAllowableLazy sut) 20 | { 21 | sut.IsAllowed(typeof(string)) 22 | .ShouldBeFalse(); 23 | } 24 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/ValidateAllRegistrationsTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Autofac.Validation; 3 | using Noggog.Testing.AutoFixture; 4 | using NSubstitute; 5 | 6 | namespace CSharpExt.UnitTests.Autofac; 7 | 8 | public class ValidateAllRegistrationsTests 9 | { 10 | [Theory, TestData] 11 | public void Empty(ValidateTypes sut) 12 | { 13 | sut.Registrations.Items.Returns(new Dictionary>()); 14 | sut.Validate(Enumerable.Empty()); 15 | } 16 | 17 | [Theory, TestData(ConfigureMembers: true)] 18 | public void NoImplementation(ValidateTypes sut) 19 | { 20 | sut.Registrations.Items.Returns(new Dictionary>() 21 | { 22 | { typeof(string), new List() } 23 | }); 24 | Assert.Throws(() => 25 | { 26 | sut.Validate(typeof(string).AsEnumerable()); 27 | }); 28 | } 29 | 30 | [Theory, TestData(ConfigureMembers: true)] 31 | public void TypicalValidate(ValidateTypes sut) 32 | { 33 | sut.Registrations.Items.Returns(new Dictionary>() 34 | { 35 | { typeof(string), new List() { new Registration(typeof(int), false) } } 36 | }); 37 | sut.Validate(typeof(string).AsEnumerable()); 38 | sut.TypeCtor.Received(1).Validate(typeof(int), default(HashSet?)); 39 | } 40 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Autofac/ValidateTypeTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.Autofac.Validation; 2 | using Noggog.Testing.AutoFixture; 3 | using NSubstitute; 4 | 5 | namespace CSharpExt.UnitTests.Autofac; 6 | 7 | public class ValidateTypeTests 8 | { 9 | class Class 10 | { 11 | } 12 | 13 | [Theory, TestData] 14 | public void CheckIfRegistered(ValidateType sut) 15 | { 16 | sut.Registrations.Items.Returns(new Dictionary>() 17 | { 18 | { typeof (Class), new []{ new Registration(typeof(string), true) } }, 19 | }); 20 | 21 | sut.Validate(typeof(Class)); 22 | 23 | sut.ValidateCtor.Received(1).Validate(typeof(string)); 24 | } 25 | 26 | [Theory, TestData] 27 | public void ChecksLastRegistration(ValidateType sut) 28 | { 29 | sut.Registrations.Items.Returns(new Dictionary>() 30 | { 31 | { typeof (Class), new [] 32 | { 33 | new Registration(typeof(string), true), 34 | new Registration(typeof(int), true), 35 | } }, 36 | }); 37 | 38 | sut.Validate(typeof(Class)); 39 | 40 | sut.ValidateCtor.Received(1).Validate(typeof(int)); 41 | } 42 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/BinaryMemoryStreamTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | 3 | namespace CSharpExt.UnitTests; 4 | 5 | public class BinaryMemoryStreamTests : IBinaryStreamTests 6 | { 7 | // No actual edge, but let the tests do their thing 8 | public override int EdgeLocation => 100; 9 | 10 | public override IBinaryReadStream GetStream(int length) 11 | { 12 | return BinaryMemoryReadStream.LittleEndian(GetByteArray(length)); 13 | } 14 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/BinaryReadStreamTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | 3 | namespace CSharpExt.UnitTests; 4 | 5 | public class BinaryReadStreamTests : IBinaryStreamTests 6 | { 7 | public const int BUFFER_SIZE = 100; 8 | public override int EdgeLocation => BUFFER_SIZE; 9 | 10 | public BinaryReadStream GetBinaryReadStream(int length, bool loaded = true) 11 | { 12 | var ret = new BinaryReadStream( 13 | new MemoryStream(GetByteArray(length)), 14 | bufferSize: BUFFER_SIZE); 15 | if (loaded) 16 | { 17 | ret.LoadPosition(); 18 | } 19 | return ret; 20 | } 21 | 22 | public override IBinaryReadStream GetStream(int length) => GetBinaryReadStream(length); 23 | 24 | [Fact] 25 | public void SetPositionToRightPastBuffer() 26 | { 27 | var reader = GetBinaryReadStream(EdgeLocation * 2); 28 | reader._internalMemoryStream.Position = reader._data.Length - 3; 29 | reader._streamPos = reader._data.Length; 30 | reader.Position += 4; 31 | Assert.Equal(EdgeLocation + 1, reader.Position); 32 | Assert.Equal(101, reader._data[0]); 33 | } 34 | 35 | [Fact] 36 | public void SetPositionWhileInLastBuffer() 37 | { 38 | var reader = GetBinaryReadStream(EdgeLocation * 2); 39 | reader._internalMemoryStream.Position = 0; 40 | reader._streamPos = reader._stream.Length; 41 | reader.Position += 4; 42 | Assert.Equal(EdgeLocation + 4, reader.Position); 43 | } 44 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Enum/NumEntriesTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests.Enum; 5 | 6 | public class NumEntriesTests 7 | { 8 | [Fact] 9 | public void EmptyEnum() 10 | { 11 | var e = default(EmptyTestEnum); 12 | e.NumEntries().ShouldBe(0); 13 | Enums.NumEntries.ShouldBe(0); 14 | } 15 | 16 | [Fact] 17 | public void EmptyFlagsEnum() 18 | { 19 | var e = default(EmptyFlagsTestEnum); 20 | e.NumEntries().ShouldBe(0); 21 | Enums.NumEntries.ShouldBe(0); 22 | } 23 | 24 | [Fact] 25 | public void Enum() 26 | { 27 | var e = default(TestEnum); 28 | e.NumEntries().ShouldBe(3); 29 | Enums.NumEntries.ShouldBe(3); 30 | } 31 | 32 | [Fact] 33 | public void FlagsEnum() 34 | { 35 | var e = default(FlagsTestEnum); 36 | e.NumEntries().ShouldBe(3); 37 | Enums.NumEntries.ShouldBe(3); 38 | } 39 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Enum/TestEnums.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpExt.UnitTests.Enum; 2 | 3 | public enum EmptyTestEnum 4 | { 5 | } 6 | 7 | [Flags] 8 | public enum EmptyFlagsTestEnum 9 | { 10 | } 11 | 12 | public enum TestEnum 13 | { 14 | First = 1, 15 | Second = 2, 16 | Third = 150, 17 | } 18 | 19 | [Flags] 20 | public enum FlagsTestEnum 21 | { 22 | One = 0x01, 23 | Two = 0x02, 24 | Four = 0x04, 25 | } 26 | 27 | [Flags] 28 | public enum UlongFlagsTestEnum : ulong 29 | { 30 | One = 0x01, 31 | Two = 0x02, 32 | Four = 0x04, 33 | Max = 0x8000000000000000, 34 | } 35 | 36 | [Flags] 37 | public enum LongFlagsTestEnum : long 38 | { 39 | One = 0x01, 40 | Two = 0x02, 41 | Four = 0x04, 42 | Max = 0x4000000000000000 43 | } 44 | 45 | public enum LongEnum : long 46 | { 47 | First = 1, 48 | Second = 2, 49 | Third = 150, 50 | Last = long.MaxValue, 51 | Around = long.MinValue, 52 | } 53 | 54 | public enum ULongEnum : ulong 55 | { 56 | First = 1, 57 | Second = 2, 58 | Third = 150, 59 | Last = ulong.MaxValue, 60 | } 61 | 62 | public enum ByteEnum : byte 63 | { 64 | First = 1, 65 | Second = 2, 66 | Third = 150, 67 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Enum/ToStringFastTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests.Enum; 5 | 6 | public class ToStringFastTests 7 | { 8 | [Fact] 9 | public void ToStringFast() 10 | { 11 | TestEnum.Second.ToStringFast().ShouldBe(nameof(TestEnum.Second)); 12 | ((TestEnum)17).ToStringFast().ShouldBe($"{17}"); 13 | FlagsTestEnum.Four.ToStringFast().ShouldBe(nameof(FlagsTestEnum.Four)); 14 | (FlagsTestEnum.Two | FlagsTestEnum.Four).ToStringFast().ShouldBe($"0x{6:x}"); 15 | ((FlagsTestEnum)16).ToStringFast().ShouldBe($"0x{16:x}"); 16 | } 17 | 18 | [Fact] 19 | public void ToStringFastLong() 20 | { 21 | LongEnum.Second.ToStringFast().ShouldBe(nameof(LongEnum.Second)); 22 | } 23 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Enum/TryGetEnumTypeTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests.Enum; 5 | 6 | public class TryGetEnumTypeTests 7 | { 8 | [Fact] 9 | public void TypicalLookup() 10 | { 11 | Enums.TryGetEnumType("CSharpExt.UnitTests.Enum.TestEnum", out var type) 12 | .ShouldBeTrue(); 13 | type.ShouldBe(typeof(TestEnum)); 14 | } 15 | 16 | [Fact] 17 | public void TypicalFailedLookup() 18 | { 19 | Enums.TryGetEnumType("CSharpExt.UnitTests.Enum.TestEnum2", out var type) 20 | .ShouldBeFalse(); 21 | } 22 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Enum/TryGetNthTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests.Enum; 5 | 6 | public class TryGetNthTests 7 | { 8 | [Fact] 9 | public void Typical() 10 | { 11 | Enums.GetNth(1, TestEnum.Third) 12 | .ShouldBe(TestEnum.Second); 13 | Enums.TryGetNth(1, out var item) 14 | .ShouldBe(true); 15 | item.ShouldBe(TestEnum.Second); 16 | Enums.TryGetNth(typeof(TestEnum), 1, out var item2) 17 | .ShouldBe(true); 18 | item2.ShouldBe(TestEnum.Second); 19 | } 20 | 21 | [Fact] 22 | public void Negative() 23 | { 24 | Enums.GetNth(-1, TestEnum.Third) 25 | .ShouldBe(TestEnum.Third); 26 | Enums.TryGetNth(-1, out var item) 27 | .ShouldBe(false); 28 | Enums.TryGetNth(typeof(TestEnum), -1, out var item2) 29 | .ShouldBe(false); 30 | } 31 | 32 | [Fact] 33 | public void Over() 34 | { 35 | Enums.GetNth(17, TestEnum.Third) 36 | .ShouldBe(TestEnum.Third); 37 | Enums.TryGetNth(17, out var item) 38 | .ShouldBe(false); 39 | Enums.TryGetNth(typeof(TestEnum), 17, out var item2) 40 | .ShouldBe(false); 41 | } 42 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Enum/ValuesTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.Extensions; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests.Enum; 6 | 7 | public class ValuesTests 8 | { 9 | [Fact] 10 | public void Typical() 11 | { 12 | Enums.Values.ShouldEqualEnumerable( 13 | TestEnum.First, 14 | TestEnum.Second, 15 | TestEnum.Third); 16 | } 17 | 18 | [Fact] 19 | public void Empty() 20 | { 21 | Enums.Values.ShouldBeEmpty(); 22 | } 23 | 24 | [Fact] 25 | public void TypicalFlags() 26 | { 27 | Enums.Values.ShouldEqualEnumerable( 28 | FlagsTestEnum.One, 29 | FlagsTestEnum.Two, 30 | FlagsTestEnum.Four); 31 | } 32 | 33 | [Fact] 34 | public void EmptyFlags() 35 | { 36 | Enums.Values.ShouldBeEmpty(); 37 | } 38 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/EnumerableExtTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | 3 | namespace CSharpExt.UnitTests; 4 | 5 | public class EnumerableExtTests 6 | { 7 | public IEnumerable TypicalEnumer() 8 | { 9 | yield return 5; 10 | yield return -4; 11 | yield return 94; 12 | yield return 8; 13 | } 14 | 15 | #region CountGreaterThan 16 | [Fact] 17 | public void CountGreaterThan_TypicalPass() 18 | { 19 | Assert.True(TypicalEnumer().CountGreaterThan(2)); 20 | } 21 | 22 | [Fact] 23 | public void CountGreaterThan_TypicalFail() 24 | { 25 | Assert.False(TypicalEnumer().CountGreaterThan(6)); 26 | } 27 | 28 | [Fact] 29 | public void CountGreaterThan_EdgeFail() 30 | { 31 | Assert.False(TypicalEnumer().CountGreaterThan(4)); 32 | } 33 | 34 | [Fact] 35 | public void CountGreaterThan_Zero() 36 | { 37 | Assert.True(TypicalEnumer().CountGreaterThan(0)); 38 | } 39 | 40 | [Fact] 41 | public void CountGreaterThan_EmptyTypical() 42 | { 43 | Assert.False(EnumerableExt.Empty.CountGreaterThan(2)); 44 | } 45 | 46 | [Fact] 47 | public void CountGreaterThan_EmptyZero() 48 | { 49 | Assert.False(EnumerableExt.Empty.CountGreaterThan(0)); 50 | } 51 | #endregion 52 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/FileNameTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests; 5 | 6 | public class FileNameTests 7 | { 8 | [Fact] 9 | public static void FileNameTypical() 10 | { 11 | new FileName("Test.txt"); 12 | } 13 | 14 | [Fact] 15 | public static void FileNameNoExtension() 16 | { 17 | new FileName("Test"); 18 | } 19 | 20 | [Fact] 21 | public static void FileNameHasDirectory() 22 | { 23 | Assert.Throws(() => 24 | { 25 | new FileName("Directory/Test.txt"); 26 | }); 27 | } 28 | 29 | [Fact] 30 | public static void FileNameEmpty() 31 | { 32 | new FileName(string.Empty); 33 | } 34 | 35 | [Fact] 36 | public void NullableImplicitOperator() 37 | { 38 | FilePath? fp = new FilePath("Test"); 39 | string? str = fp; 40 | str.ShouldBe("Test"); 41 | fp = null; 42 | str = fp; 43 | str.ShouldBeNull(); 44 | } 45 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/IO/Files/ConverterDirectoryPathSerialization.json: -------------------------------------------------------------------------------- 1 | { 2 | "MyDirectory": "C:\\SomeDir\\SomePath" 3 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/IO/Files/ConverterFilePathSerialization.json: -------------------------------------------------------------------------------- 1 | { 2 | "MyFile": "C:\\SomeDir\\SomeFile.txt" 3 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/IO/Files/NakedDirectoryPathSerialization.json: -------------------------------------------------------------------------------- 1 | { 2 | "MyDirectory": { 3 | "RelativePath": "C:\\SomeDir\\SomePath" 4 | } 5 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/IO/Files/NakedFilePathSerialization.json: -------------------------------------------------------------------------------- 1 | { 2 | "MyFile": { 3 | "RelativePath": "C:\\SomeDir\\SomeFile.txt" 4 | } 5 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/IO/Files/OldDirectoryPathSerialization.json: -------------------------------------------------------------------------------- 1 | { 2 | "MyDirectory": { 3 | "Directory": { 4 | "Directory": { 5 | "Directory": null, 6 | "Exists": true, 7 | "Path": "C:\\", 8 | "RelativePath": "C:\\", 9 | "Name": { 10 | "Extension": "", 11 | "NameWithoutExtension": "", 12 | "String": "" 13 | }, 14 | "Empty": false 15 | }, 16 | "Exists": false, 17 | "Path": "C:\\SomeDir", 18 | "RelativePath": "C:\\SomeDir", 19 | "Name": { 20 | "Extension": "", 21 | "NameWithoutExtension": "SomeDir", 22 | "String": "SomeDir" 23 | }, 24 | "Empty": true 25 | }, 26 | "Exists": false, 27 | "Path": "C:\\SomeDir\\SomePath", 28 | "RelativePath": "C:\\SomeDir\\SomePath", 29 | "Name": { 30 | "Extension": "", 31 | "NameWithoutExtension": "SomePath", 32 | "String": "SomePath" 33 | }, 34 | "Empty": true 35 | } 36 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/IO/Files/OldFilePathSerialization.json: -------------------------------------------------------------------------------- 1 | { 2 | "MyFile": { 3 | "Directory": { 4 | "Directory": { 5 | "Directory": null, 6 | "Exists": true, 7 | "Path": "C:\\", 8 | "RelativePath": "C:\\", 9 | "Name": { 10 | "Extension": "", 11 | "NameWithoutExtension": "", 12 | "String": "" 13 | }, 14 | "Empty": false 15 | }, 16 | "Exists": false, 17 | "Path": "C:\\SomeDir", 18 | "RelativePath": "C:\\SomeDir", 19 | "Name": { 20 | "Extension": "", 21 | "NameWithoutExtension": "SomeDir", 22 | "String": "SomeDir" 23 | }, 24 | "Empty": true 25 | }, 26 | "Path": "C:\\SomeDir\\SomeFile.txt", 27 | "RelativePath": "C:\\SomeDir\\SomeFile.txt", 28 | "Name": { 29 | "Extension": ".txt", 30 | "NameWithoutExtension": "SomeFile", 31 | "String": "SomeFile.txt" 32 | }, 33 | "Extension": ".txt", 34 | "NameWithoutExtension": "SomeFile", 35 | "Exists": false 36 | } 37 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/ModuleInitializer.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace CSharpExt.UnitTests; 4 | 5 | public static class ModuleInitializer 6 | { 7 | [ModuleInitializer] 8 | public static void Init() 9 | { 10 | VerifySourceGenerators.Initialize(); 11 | VerifyDiffPlex.Initialize(); 12 | } 13 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P2DoubleTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P2DoubleTests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP2DoubleParse(double x, double y) 12 | { 13 | var givenStr = $"{x},{y}"; 14 | var expectedPoint = new P2Double(x, y); 15 | P2Double.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P2DoubleReparse(double x, double y) 22 | { 23 | var expectedPoint = new P2Double(x, y); 24 | P2Double.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P2FloatTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P2FloatTests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP2FloatParse(float x, float y) 12 | { 13 | var givenStr = $"{x},{y}"; 14 | var expectedPoint = new P2Float(x, y); 15 | P2Float.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P2FloatReparse(float x, float y) 22 | { 23 | var expectedPoint = new P2Float(x, y); 24 | P2Float.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P2IntTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P2IntTests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP2IntParse(int x, int y) 12 | { 13 | var givenStr = $"{x},{y}"; 14 | var expectedPoint = new P2Int(x, y); 15 | P2Int.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P2IntReparse(int x, int y) 22 | { 23 | var expectedPoint = new P2Int(x, y); 24 | P2Int.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P2UInt8Tests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P2UInt8Tests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP2UInt8Parse(byte x, byte y) 12 | { 13 | var givenStr = $"{x},{y}"; 14 | var expectedPoint = new P2UInt8(x, y); 15 | P2UInt8.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P2UInt8Reparse(byte x, byte y) 22 | { 23 | var expectedPoint = new P2UInt8(x, y); 24 | P2UInt8.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P3DoubleTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P3DoubleTests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP3DoubleParse(double x, double y, double z) 12 | { 13 | var givenStr = $"{x},{y},{z}"; 14 | var expectedPoint = new P3Double(x, y, z); 15 | P3Double.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P3DoubleReparse(double x, double y, double z) 22 | { 23 | var expectedPoint = new P3Double(x, y, z); 24 | P3Double.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P3FloatTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P3FloatTests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP3FloatParse(float x, float y, float z) 12 | { 13 | var givenStr = $"{x},{y},{z}"; 14 | var expectedPoint = new P3Float(x, y, z); 15 | P3Float.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P3FloatReparse(float x, float y, float z) 22 | { 23 | var expectedPoint = new P3Float(x, y, z); 24 | P3Float.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P3Int16Tests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P3Int16Tests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP3Int16Parse(short x, short y, short z) 12 | { 13 | var givenStr = $"{x},{y},{z}"; 14 | var expectedPoint = new P3Int16(x, y, z); 15 | P3Int16.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P3Int16Reparse(short x, short y, short z) 22 | { 23 | var expectedPoint = new P3Int16(x, y, z); 24 | P3Int16.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P3IntTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P3IntTests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP3IntParse(int x, int y, int z) 12 | { 13 | var givenStr = $"{x},{y},{z}"; 14 | var expectedPoint = new P3Int(x, y, z); 15 | P3Int.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P3IntReparse(int x, int y, int z) 22 | { 23 | var expectedPoint = new P3Int(x, y, z); 24 | P3Int.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P3UInt16Tests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P3UInt16Tests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP3UInt16Parse(ushort x, ushort y, ushort z) 12 | { 13 | var givenStr = $"{x},{y},{z}"; 14 | var expectedPoint = new P3UInt16(x, y, z); 15 | P3UInt16.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P3UInt16Reparse(ushort x, ushort y, ushort z) 22 | { 23 | var expectedPoint = new P3UInt16(x, y, z); 24 | P3UInt16.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/P3UInt8Tests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Noggog.Testing.AutoFixture; 3 | using Shouldly; 4 | 5 | namespace CSharpExt.UnitTests; 6 | 7 | public class P3UInt8Tests 8 | { 9 | [Theory] 10 | [DefaultAutoData] 11 | public void TypicalP3UInt8Parse(byte x, byte y, byte z) 12 | { 13 | var givenStr = $"{x},{y},{z}"; 14 | var expectedPoint = new P3UInt8(x, y, z); 15 | P3UInt8.TryParse(givenStr, out var result).ShouldBeTrue(); 16 | result.ShouldBe(expectedPoint); 17 | } 18 | 19 | [Theory] 20 | [DefaultAutoData] 21 | public void P3UInt8Reparse(byte x, byte y, byte z) 22 | { 23 | var expectedPoint = new P3UInt8(x, y, z); 24 | P3UInt8.TryParse(expectedPoint.ToString(), out var result).ShouldBeTrue(); 25 | result.ShouldBe(expectedPoint); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/RangeInt64Tests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | 3 | namespace CSharpExt.UnitTests; 4 | 5 | public class RangeInt64Tests 6 | { 7 | #region Collision 8 | [Fact] 9 | public void CollidesTypical() 10 | { 11 | Assert.True( 12 | new RangeInt64(5, 10).Collides( 13 | new RangeInt64(6, 11))); 14 | } 15 | 16 | [Fact] 17 | public void CollidesTypical_False_TooLow() 18 | { 19 | Assert.False( 20 | new RangeInt64(2, 3).Collides( 21 | new RangeInt64(6, 11))); 22 | } 23 | 24 | [Fact] 25 | public void CollidesTypical_False_TooHigh() 26 | { 27 | Assert.False( 28 | new RangeInt64(12, 15).Collides( 29 | new RangeInt64(6, 11))); 30 | } 31 | 32 | [Fact] 33 | public void CollidesTypical_Encapsulated() 34 | { 35 | Assert.True( 36 | new RangeInt64(7, 10).Collides( 37 | new RangeInt64(6, 11))); 38 | } 39 | 40 | [Fact] 41 | public void CollidesTypical_Encapsulating() 42 | { 43 | Assert.True( 44 | new RangeInt64(6, 11).Collides( 45 | new RangeInt64(7, 10))); 46 | } 47 | 48 | [Fact] 49 | public void CollidesTypical_Equal() 50 | { 51 | Assert.True( 52 | new RangeInt64(7, 10).Collides( 53 | new RangeInt64(7, 10))); 54 | } 55 | #endregion 56 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/SourceGenerators/AssemblyVersionGeneratorTests.BasicGeneration#AssemblyVersions.g.verified.cs: -------------------------------------------------------------------------------- 1 | //HintName: AssemblyVersions.g.cs 2 | using System; 3 | using System.Diagnostics; 4 | using System.Reflection; 5 | 6 | #nullable enable 7 | 8 | /// 9 | /// Struct holding the information about an Assembly's version 10 | /// 11 | /// Name of the assembly 12 | /// Version string for the assembly 13 | public record AssemblyVersions(string PrettyName, string? ProductVersion) 14 | { 15 | 16 | /// 17 | /// Gets the assembly version information for a given type 18 | /// 19 | /// Type to get information about 20 | /// Structure containing the assembly version information 21 | public static AssemblyVersions For() 22 | { 23 | var t = typeof(TTypeFromAssembly); 24 | 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpExt.UnitTests/SourceGenerators/AssemblyVersionGeneratorTests.BasicUsage#AssemblyVersions.g.verified.cs: -------------------------------------------------------------------------------- 1 | //HintName: AssemblyVersions.g.cs 2 | using SomeNamespace; 3 | using System; 4 | using System.Diagnostics; 5 | using System.Reflection; 6 | 7 | #nullable enable 8 | 9 | /// 10 | /// Struct holding the information about an Assembly's version 11 | /// 12 | /// Name of the assembly 13 | /// Version string for the assembly 14 | public record AssemblyVersions(string PrettyName, string? ProductVersion) 15 | { 16 | private static readonly AssemblyVersions _MyClass = new("", "0.0.0.0"); 17 | 18 | /// 19 | /// Gets the assembly version information for a given type 20 | /// 21 | /// Type to get information about 22 | /// Structure containing the assembly version information 23 | public static AssemblyVersions For() 24 | { 25 | var t = typeof(TTypeFromAssembly); 26 | if (t == typeof(SomeNamespace.MyClass)) return _MyClass; 27 | 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CSharpExt.UnitTests/SourceGenerators/AssemblyVersionGeneratorTests.GenericPassed#AssemblyVersions.g.verified.cs: -------------------------------------------------------------------------------- 1 | //HintName: AssemblyVersions.g.cs 2 | using System; 3 | using System.Diagnostics; 4 | using System.Reflection; 5 | 6 | #nullable enable 7 | 8 | /// 9 | /// Struct holding the information about an Assembly's version 10 | /// 11 | /// Name of the assembly 12 | /// Version string for the assembly 13 | public record AssemblyVersions(string PrettyName, string? ProductVersion) 14 | { 15 | 16 | /// 17 | /// Gets the assembly version information for a given type 18 | /// 19 | /// Type to get information about 20 | /// Structure containing the assembly version information 21 | public static AssemblyVersions For() 22 | { 23 | var t = typeof(TTypeFromAssembly); 24 | 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /CSharpExt.UnitTests/SourceGenerators/AssemblyVersionGeneratorTests.GenericPassed.verified.txt: -------------------------------------------------------------------------------- 1 | { 2 | Diagnostics: [ 3 | { 4 | Location: /* 5 | { 6 | public AssemblyVersions Test() => AssemblyVersions.For(); 7 | ^ 8 | } 9 | */ 10 | : (5,66)-(5,67), 11 | Message: Unknown type passed to AssemblyVersions, 12 | Severity: Error, 13 | Descriptor: { 14 | Id: SY0001, 15 | Title: Unknown type passed to AssemblyVersions, 16 | Description: Need to pass a known concrete type, rather than a generic., 17 | MessageFormat: Unknown type passed to AssemblyVersions, 18 | Category: AssemblyVersions, 19 | DefaultSeverity: Error, 20 | IsEnabledByDefault: true 21 | } 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/SourceGenerators/AssemblyVersionGeneratorTests.NamespaceSpecified#AssemblyVersions.g.verified.cs: -------------------------------------------------------------------------------- 1 | //HintName: AssemblyVersions.g.cs 2 | using SomeNamespace; 3 | using System; 4 | using System.Diagnostics; 5 | using System.Reflection; 6 | 7 | #nullable enable 8 | 9 | /// 10 | /// Struct holding the information about an Assembly's version 11 | /// 12 | /// Name of the assembly 13 | /// Version string for the assembly 14 | public record AssemblyVersions(string PrettyName, string? ProductVersion) 15 | { 16 | private static readonly AssemblyVersions _MyClass = new("", "0.0.0.0"); 17 | 18 | /// 19 | /// Gets the assembly version information for a given type 20 | /// 21 | /// Type to get information about 22 | /// Structure containing the assembly version information 23 | public static AssemblyVersions For() 24 | { 25 | var t = typeof(TTypeFromAssembly); 26 | if (t == typeof(SomeNamespace.MyClass)) return _MyClass; 27 | 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Structs/MemorySliceTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests.Structs; 5 | 6 | public class MemorySliceTests 7 | { 8 | [Fact] 9 | public void DefaultToArray() 10 | { 11 | var sut = default(MemorySlice); 12 | sut.ToArray().ShouldBeEmpty(); 13 | } 14 | 15 | [Fact] 16 | public void ReadonlyDefaultToArray() 17 | { 18 | var sut = default(ReadOnlyMemorySlice); 19 | sut.ToArray().ShouldBeEmpty(); 20 | } 21 | 22 | [Fact] 23 | public void DefaultZeroLengthToArray() 24 | { 25 | var sut = new MemorySlice(new byte[6], 4, 0); 26 | sut.ToArray().ShouldBeEmpty(); 27 | } 28 | 29 | [Fact] 30 | public void ReadonlyZeroLengthDefaultToArray() 31 | { 32 | var sut = new ReadOnlyMemorySlice(new byte[6], 4, 0); 33 | sut.ToArray().ShouldBeEmpty(); 34 | } 35 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/StructuredStrings/StructuredStringBuilderTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.StructuredStrings; 2 | 3 | namespace CSharpExt.UnitTests.StructuredStrings; 4 | 5 | public class StructuredStringBuilderTests 6 | { 7 | [Fact] 8 | public void AppendWithEmbeddedNewLine() 9 | { 10 | var sb = new StructuredStringBuilder(); 11 | sb.AppendLine($"A{Environment.NewLine}B"); 12 | Assert.Equal(new string[] { "A", "B" }, sb); 13 | } 14 | 15 | [Fact] 16 | public void AppendNull() 17 | { 18 | var sb = new StructuredStringBuilder(); 19 | sb.AppendLine(null); 20 | Assert.Equal(new string[] { "" }, sb); 21 | } 22 | 23 | [Fact] 24 | public void AppendEmpty() 25 | { 26 | var sb = new StructuredStringBuilder(); 27 | sb.AppendLine(String.Empty); 28 | Assert.Equal(new string[] { "" }, sb); 29 | } 30 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/TempFileFolderTests.cs: -------------------------------------------------------------------------------- 1 | using Noggog.IO; 2 | using Shouldly; 3 | 4 | namespace CSharpExt.UnitTests; 5 | 6 | public class TempFileFolderTests 7 | { 8 | [Fact] 9 | public void TempFolder_Exists() 10 | { 11 | var filepath = Path.Combine(Path.GetTempPath(), $"CSharpEXT/Test"); 12 | using (var tmp = TempFolder.FactoryByPath(filepath, deleteAfter: true)) 13 | { 14 | Directory.Exists(filepath).ShouldBeTrue(); 15 | } 16 | Directory.Exists(filepath).ShouldBeFalse(); 17 | } 18 | 19 | [Fact] 20 | public void TempFile_DeleteAfter() 21 | { 22 | string path; 23 | using (var tmp = new TempFile(deleteAfter: true)) 24 | { 25 | path = tmp.File.Path.ToString(); 26 | } 27 | File.Exists(path).ShouldBeFalse(); 28 | } 29 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/TestDataAttribute.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using AutoFixture.AutoNSubstitute; 3 | using AutoFixture.Xunit2; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public class TestDataAttribute : AutoDataAttribute 8 | { 9 | public TestDataAttribute( 10 | bool ConfigureMembers = false, 11 | TargetFileSystem FileSystem = TargetFileSystem.Fake) 12 | : base(() => 13 | { 14 | var customization = new AutoNSubstituteCustomization() 15 | { 16 | ConfigureMembers = ConfigureMembers, 17 | GenerateDelegates = true 18 | }; 19 | 20 | return new Fixture() 21 | .Customize(customization) 22 | .Customize(new DefaultCustomization(targetFileSystem: FileSystem)); 23 | }) 24 | { 25 | } 26 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace CSharpExt.UnitTests; 4 | 5 | public static class TestHelper 6 | { 7 | private static bool AutoVerify = false; 8 | 9 | private static VerifySettings GetVerifySettings() 10 | { 11 | var verifySettings = new VerifySettings(); 12 | #if DEBUG 13 | if (AutoVerify) 14 | { 15 | verifySettings.AutoVerify(includeBuildServer: true, throwException: false); 16 | } 17 | #else 18 | verifySettings.DisableDiff(); 19 | #endif 20 | return verifySettings; 21 | } 22 | 23 | public static Task VerifyString(string str, [CallerFilePath] string sourceFile = "") 24 | { 25 | return Verifier.Verify(str, GetVerifySettings(), sourceFile); 26 | } 27 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/Utility.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpExt.UnitTests; 2 | 3 | public static class Utility 4 | { 5 | public static readonly string TempFolderPath = "CSharpExtTests"; 6 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/WrappedInt.cs: -------------------------------------------------------------------------------- 1 | namespace CSharpExt.UnitTests; 2 | 3 | public class WrappedInt : IComparable, IComparable, IEquatable 4 | { 5 | public readonly int Int; 6 | 7 | public WrappedInt(int i) 8 | { 9 | Int = i; 10 | } 11 | 12 | public int CompareTo(WrappedInt? other) 13 | { 14 | return Int.CompareTo(other!.Int); 15 | } 16 | 17 | public int CompareTo(object? obj) 18 | { 19 | if (!(obj is WrappedInt rhs)) return 0; 20 | return CompareTo(rhs); 21 | } 22 | 23 | public override bool Equals(object? obj) 24 | { 25 | if (!(obj is WrappedInt rhs)) return false; 26 | return Equals(rhs); 27 | } 28 | 29 | public override int GetHashCode() 30 | { 31 | return HashCode.Combine(Int); 32 | } 33 | 34 | public bool Equals(WrappedInt? other) 35 | { 36 | if (other == null) return false; 37 | return Int == other.Int; 38 | } 39 | 40 | public override string ToString() 41 | { 42 | return Int.ToString(); 43 | } 44 | } -------------------------------------------------------------------------------- /CSharpExt.UnitTests/XmlExtTests.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Linq; 2 | using Noggog; 3 | 4 | namespace CSharpExt.UnitTests; 5 | 6 | public class XmlExtTests 7 | { 8 | enum TestEnum 9 | { 10 | Value1, 11 | Value2 12 | } 13 | 14 | [Fact] 15 | public void TryGetAttribute() 16 | { 17 | XElement elem = new XElement("Test", new XAttribute("value", "true")); 18 | elem.TryGetAttribute("value", out var val); 19 | Assert.True(val); 20 | } 21 | 22 | [Fact] 23 | public void TryGetAttribute_Enum() 24 | { 25 | XElement elem = new XElement("Test", new XAttribute("value", "Value2")); 26 | elem.TryGetAttribute("value", out var val); 27 | Assert.Equal(TestEnum.Value2, val); 28 | } 29 | 30 | [Fact] 31 | public void GetAttribute_Nullable() 32 | { 33 | XElement elem = new XElement("Test"); 34 | var ret = elem.GetAttribute("value", default(int?)); 35 | Assert.Null(ret); 36 | elem = new XElement("Test", new XAttribute("value", "123")); 37 | ret = elem.GetAttribute("value", default(int?)); 38 | Assert.Equal(123, ret); 39 | } 40 | } -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | enable 6 | nullable 7 | true 8 | true 9 | ..\nupkg 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Noggog.Autofac/ContainerBuilderExt.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using System.IO.Abstractions; 3 | 4 | namespace Noggog.Autofac; 5 | 6 | public static class ContainerBuilderExt 7 | { 8 | public static void WithTypicalFilesystem(this ContainerBuilder builder) 9 | { 10 | builder.RegisterType().As() 11 | .SingleInstance(); 12 | } 13 | 14 | public static void TypicalSingletonFolderRegistration(this ContainerBuilder builder) 15 | { 16 | builder.RegisterAssemblyTypes(typeof(TPrototype).Assembly) 17 | .InNamespacesOf( 18 | typeof(TPrototype)) 19 | .AsImplementedInterfaces() 20 | .AsSelf() 21 | .SingleInstance(); 22 | } 23 | 24 | public static void TypicalTransientFolderRegistration(this ContainerBuilder builder) 25 | { 26 | builder.RegisterAssemblyTypes(typeof(TPrototype).Assembly) 27 | .InNamespacesOf( 28 | typeof(TPrototype)) 29 | .AsImplementedInterfaces() 30 | .AsSelf(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Noggog.Autofac/Modules/NoggogModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.DotNetCli.DI; 3 | using Noggog.IO; 4 | using Noggog.Processes.DI; 5 | using Noggog.Reactive; 6 | using Noggog.Time; 7 | using Noggog.WorkEngine; 8 | 9 | namespace Noggog.Autofac.Modules; 10 | 11 | public class NoggogModule : Module 12 | { 13 | protected override void Load(ContainerBuilder builder) 14 | { 15 | builder.RegisterAssemblyTypes(typeof(IDeepCopyDirectory).Assembly) 16 | .InNamespacesOf( 17 | typeof(IDeleteEntireDirectory), 18 | typeof(INowProvider), 19 | typeof(IProcessRunner), 20 | typeof(IQueryNugetListing), 21 | typeof(IWatchFile)) 22 | .Except() 23 | .Except() 24 | .NotInjection() 25 | .AsImplementedInterfaces() 26 | .SingleInstance(); 27 | builder.RegisterAssemblyTypes(typeof(IWorkDropoff).Assembly) 28 | .InNamespacesOf( 29 | typeof(IWorkDropoff)) 30 | .Except() 31 | .NotInjection() 32 | .AsImplementedInterfaces() 33 | .SingleInstance(); 34 | } 35 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Noggog.Autofac.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0;net9.0 5 | true 6 | Noggog.Autofac 7 | Noggog 8 | Noggog 9 | preview 10 | true 11 | portable 12 | true 13 | true 14 | true 15 | true 16 | snupkg 17 | Autofac related utility 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Noggog.Autofac/TestingPermissions.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("CSharpExt.UnitTests")] -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/AutofacValidationException.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation; 2 | 3 | public class AutofacValidationException : Exception 4 | { 5 | public AutofacValidationException(string message) 6 | : base(message) 7 | { 8 | } 9 | 10 | public AutofacValidationException(string message, Exception inner) 11 | : base(message, inner) 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/CircularReferenceChecker.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | 3 | namespace Noggog.Autofac.Validation; 4 | 5 | public interface ICircularReferenceChecker 6 | { 7 | void Check(); 8 | } 9 | 10 | public class CircularReferenceChecker : ICircularReferenceChecker 11 | { 12 | private readonly IConcreteTypeToDependenciesProvider _concreteTypeToDependenciesProvider; 13 | 14 | public CircularReferenceChecker( 15 | IConcreteTypeToDependenciesProvider concreteTypeToDependenciesProvider) 16 | { 17 | _concreteTypeToDependenciesProvider = concreteTypeToDependenciesProvider; 18 | } 19 | 20 | public void Check() 21 | { 22 | foreach (var item in _concreteTypeToDependenciesProvider.ConcreteTypeMapping) 23 | { 24 | Check(item.Key, ImmutableList.Empty); 25 | } 26 | } 27 | 28 | private void Check(Type type, ImmutableList passed) 29 | { 30 | if (passed.Contains(type)) 31 | { 32 | throw new AutofacValidationException( 33 | $"Circular dependency detected. {string.Join(" --> ", passed.SkipWhile(x => x != type).And(type).Select(x => x.Name))}"); 34 | } 35 | 36 | if (!_concreteTypeToDependenciesProvider.ConcreteTypeMapping.TryGetValue(type, out var deps)) return; 37 | 38 | passed = passed.Add(type); 39 | foreach (var dep in deps) 40 | { 41 | Check(dep, passed); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/GetUsages.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation; 2 | 3 | public interface IGetUsages 4 | { 5 | HashSet Get(params Type[] concreteTypes); 6 | } 7 | 8 | public class GetUsages : IGetUsages 9 | { 10 | public HashSet Get(params Type[] concreteTypes) 11 | { 12 | var ret = new HashSet(); 13 | foreach (var type in concreteTypes) 14 | { 15 | foreach (var ctor in type.GetConstructors()) 16 | { 17 | foreach (var param in ctor.GetParameters()) 18 | { 19 | ret.Add(param.ParameterType); 20 | } 21 | } 22 | } 23 | 24 | return ret; 25 | } 26 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/IsAutofacType.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation; 2 | 3 | public interface IShouldSkipType 4 | { 5 | bool ShouldSkip(Type type); 6 | } 7 | 8 | public class ShouldSkipType : IShouldSkipType 9 | { 10 | public bool ShouldSkip(Type type) 11 | { 12 | if (type.Namespace?.StartsWith("Castle") ?? false) return true; 13 | if (type.Namespace?.StartsWith("Autofac") ?? false) return true; 14 | return false; 15 | } 16 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Rules/CheckIsDelegateFactory.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation.Rules; 2 | 3 | public class CheckIsDelegateFactory : IValidationRule 4 | { 5 | public IRegistrations Registrations { get; } 6 | public IValidateTypeCtor ValidateTypeCtor { get; set; } = null!; 7 | public IValidateType ValidateType { get; set; } = null!; 8 | 9 | public CheckIsDelegateFactory(IRegistrations registrations) 10 | { 11 | Registrations = registrations; 12 | } 13 | 14 | public bool IsAllowed(Type type) 15 | { 16 | if (type.BaseType?.FullName != "System.MulticastDelegate") return false; 17 | var invoke = type.GetMethod("Invoke"); 18 | if (invoke == null) return false; 19 | if (invoke.ReturnType == typeof(void)) return false; 20 | 21 | var typeToCheck = invoke.ReturnType; 22 | ValidateType.Validate(typeToCheck, validateCtor: false); 23 | 24 | if (Registrations.Items.TryGetValue(typeToCheck, out var registrations)) 25 | { 26 | var register = registrations.FirstOrDefault(); 27 | if (register != null) 28 | { 29 | if (!register.NeedsValidation) return true; 30 | typeToCheck = register.Type; 31 | } 32 | } 33 | 34 | var parameterNames = new HashSet(invoke.GetParameters().Select(p => p.Name).WhereNotNull()); 35 | ValidateTypeCtor.Validate(typeToCheck, parameterNames); 36 | return true; 37 | } 38 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Rules/IValidationRule.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation.Rules; 2 | 3 | public interface IValidationRule 4 | { 5 | bool IsAllowed(Type type); 6 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Rules/IsAllowableEnumerable.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation.Rules; 2 | 3 | public class IsAllowableEnumerable : IValidationRule 4 | { 5 | public IValidateTypeCtor ValidateTypeCtor { get; set; } = null!; 6 | 7 | public bool IsAllowed(Type type) 8 | { 9 | if (type.Name.StartsWith("IEnumerable") 10 | && type.IsGenericType 11 | && type.GenericTypeArguments.Length == 1) 12 | { 13 | ValidateTypeCtor.Validate(type.GenericTypeArguments[0]); 14 | return true; 15 | } 16 | 17 | if (type.Name.EndsWith("[]")) 18 | { 19 | var elemType = type.GetElementType(); 20 | if (elemType != null) 21 | { 22 | ValidateTypeCtor.Validate(elemType); 23 | return true; 24 | } 25 | } 26 | return false; 27 | } 28 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Rules/IsAllowableFunc.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation.Rules; 2 | 3 | public class IsAllowableFunc : IValidationRule 4 | { 5 | public IValidateTypeCtor ValidateTypeCtor { get; set; } = null!; 6 | 7 | public bool IsAllowed(Type type) 8 | { 9 | if (type.Name.StartsWith("Func") 10 | && type.IsGenericType 11 | && type.GenericTypeArguments.Length == 1) 12 | { 13 | ValidateTypeCtor.Validate(type.GenericTypeArguments[0]); 14 | return true; 15 | } 16 | return false; 17 | } 18 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Rules/IsAllowableLazy.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation.Rules; 2 | 3 | public class IsAllowableLazy : IValidationRule 4 | { 5 | public IValidateTypeCtor ValidateTypeCtor { get; set; } = null!; 6 | 7 | public bool IsAllowed(Type type) 8 | { 9 | if (type.Name.StartsWith("Lazy") 10 | && type.IsGenericType 11 | && type.GenericTypeArguments.Length == 1) 12 | { 13 | ValidateTypeCtor.Validate(type.GenericTypeArguments[0]); 14 | return true; 15 | } 16 | return false; 17 | } 18 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Rules/SkipLoggerRule.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation.Rules; 2 | 3 | public class SkipLoggerRule : IValidationRule 4 | { 5 | // To Do 6 | // Find a more robust way to validate logging systems 7 | public bool IsAllowed(Type type) 8 | { 9 | if (type.Name.StartsWith("ILogger")) return true; 10 | return false; 11 | } 12 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/TypeToDependenciesProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation; 2 | 3 | public interface ITypeToDependenciesProvider 4 | { 5 | IReadOnlyDictionary> DirectTypeMapping { get; } 6 | } 7 | 8 | public class TypeToDependenciesProvider : ITypeToDependenciesProvider 9 | { 10 | private readonly Lazy>> _directTypeMapping; 11 | public IReadOnlyDictionary> DirectTypeMapping => _directTypeMapping.Value; 12 | 13 | public TypeToDependenciesProvider( 14 | IRegistrations registrations) 15 | { 16 | _directTypeMapping = new Lazy>>(() => 17 | { 18 | var dict = new Dictionary>(); 19 | foreach (var concrete in registrations.Items) 20 | { 21 | var set = dict.GetOrAdd(concrete.Key); 22 | foreach (var constructor in concrete.Value.First().Type.GetConstructors()) 23 | { 24 | foreach (var param in constructor.GetParameters()) 25 | { 26 | set.Add(param.ParameterType); 27 | } 28 | } 29 | } 30 | 31 | return dict.ToDictionary>, Type, IReadOnlySet>( 32 | keySelector: x => x.Key, 33 | elementSelector: x => x.Value); 34 | }); 35 | } 36 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/ValidateTracker.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | 3 | namespace Noggog.Autofac.Validation; 4 | 5 | public interface IValidateTracker 6 | { 7 | IDisposable Track(Type type); 8 | string State(); 9 | } 10 | 11 | public class ValidateTracker : IValidateTracker 12 | { 13 | private Stack _types = new(); 14 | 15 | public IDisposable Track(Type type) 16 | { 17 | _types.Push(type); 18 | return Disposable.Create(() => _types.Pop()); 19 | } 20 | 21 | public string State() 22 | { 23 | return string.Join($" -> {Environment.NewLine} ", _types.Reverse()); 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/ValidateTypeCtor.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation; 2 | 3 | public interface IValidateTypeCtor 4 | { 5 | void Validate(Type type, HashSet? paramSkip = null); 6 | } 7 | 8 | public class ValidateTypeCtor : IValidateTypeCtor 9 | { 10 | public IShouldSkipType ShouldSkip { get; } 11 | public IValidateType ValidateType { get; } 12 | 13 | public ValidateTypeCtor( 14 | IShouldSkipType shouldShouldSkip, 15 | IValidateType validateType) 16 | { 17 | ShouldSkip = shouldShouldSkip; 18 | ValidateType = validateType; 19 | } 20 | 21 | public void Validate(Type type, HashSet? paramSkip = null) 22 | { 23 | if (ShouldSkip.ShouldSkip(type)) return; 24 | var constr = type.GetConstructors(); 25 | if (constr.Length > 1) 26 | { 27 | throw new AutofacValidationException( 28 | $"'{type.FullName}' has more than one constructor"); 29 | } 30 | 31 | if (constr.Length == 0) return; 32 | 33 | foreach (var param in constr[0].GetParameters()) 34 | { 35 | if (param.IsOptional) continue; 36 | if (param.Name != null && (paramSkip?.Contains(param.Name) ?? false)) continue; 37 | ValidateType.Validate(param.ParameterType); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/ValidationFixture.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | 3 | namespace Noggog.Autofac.Validation; 4 | 5 | public class ValidationFixture : IDisposable 6 | { 7 | private IContainer _container; 8 | 9 | public ValidationFixture() 10 | { 11 | var builder = new ContainerBuilder(); 12 | builder.RegisterModule(); 13 | _container = builder.Build(); 14 | } 15 | 16 | public IDisposable GetValidator(IContainer container, out IValidator validator) 17 | { 18 | var scope = _container.BeginLifetimeScope(cfg => 19 | { 20 | cfg.RegisterInstance(container).As(); 21 | }); 22 | validator = scope.Resolve(); 23 | return scope; 24 | } 25 | 26 | public void Dispose() 27 | { 28 | _container.Dispose(); 29 | } 30 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/ValidationModule.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | 3 | namespace Noggog.Autofac.Validation; 4 | 5 | public class ValidationModule : Module 6 | { 7 | protected override void Load(ContainerBuilder builder) 8 | { 9 | builder.RegisterType().AsSelf(); 10 | builder.RegisterAssemblyTypes(typeof(IValidator).Assembly) 11 | .InNamespaceOf() 12 | .AsImplementedInterfaces() 13 | .InstancePerLifetimeScope() 14 | .PropertiesAutowired(PropertyWiringOptions.AllowCircularDependencies); 15 | } 16 | } -------------------------------------------------------------------------------- /Noggog.Autofac/Validation/Validator.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Autofac.Validation; 2 | 3 | public interface IValidator 4 | { 5 | void ValidateEverything(); 6 | void Validate(Type drivingType, params Type[] otherdrivingTypes); 7 | } 8 | 9 | public class Validator : IValidator 10 | { 11 | public IRegistrations Registrations { get; } 12 | public IValidateTypes ValidateTypes { get; } 13 | public IShouldSkipType ShouldSkip { get; } 14 | public ICircularReferenceChecker ReferenceChecker { get; } 15 | 16 | public Validator( 17 | IRegistrations registrations, 18 | IValidateTypes validateTypes, 19 | IShouldSkipType shouldShouldSkip, 20 | ICircularReferenceChecker circularReferenceChecker) 21 | { 22 | Registrations = registrations; 23 | ValidateTypes = validateTypes; 24 | ShouldSkip = shouldShouldSkip; 25 | ReferenceChecker = circularReferenceChecker; 26 | } 27 | 28 | private void InternalValidate(IEnumerable types) 29 | { 30 | ReferenceChecker.Check(); 31 | ValidateTypes.Validate(types); 32 | } 33 | 34 | public void ValidateEverything() 35 | { 36 | InternalValidate(Registrations.Items.Keys 37 | .Where(type => !ShouldSkip.ShouldSkip(type))); 38 | } 39 | 40 | public void Validate(Type drivingType, params Type[] otherdrivingTypes) 41 | { 42 | InternalValidate(drivingType.AsEnumerable().Concat(otherdrivingTypes)); 43 | } 44 | } -------------------------------------------------------------------------------- /Noggog.Autofac/ValidationMixIn.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Noggog.Autofac.Validation; 3 | 4 | namespace Noggog.Autofac; 5 | 6 | public static class ValidationMixIn 7 | { 8 | internal static readonly IContainer Container; 9 | 10 | static ValidationMixIn() 11 | { 12 | var builder = new ContainerBuilder(); 13 | builder.RegisterModule(); 14 | Container = builder.Build(); 15 | } 16 | 17 | public static void ValidateEverything(this IContainer container) 18 | { 19 | using var scope = Container.BeginLifetimeScope(cfg => 20 | { 21 | cfg.RegisterInstance(container).As(); 22 | }); 23 | scope.Resolve() 24 | .ValidateEverything(); 25 | } 26 | 27 | public static void Validate(this IContainer container, Type drivingType, params Type[] otherDrivingTypes) 28 | { 29 | using var scope = Container.BeginLifetimeScope(cfg => 30 | { 31 | cfg.RegisterInstance(container).As(); 32 | }); 33 | scope.Resolve() 34 | .Validate(drivingType, otherDrivingTypes); 35 | } 36 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt.Json/IO/DirectoryPathJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Noggog.Json.IO; 4 | 5 | public class DirectoryPathJsonConverter : JsonConverter 6 | { 7 | public override void WriteJson(JsonWriter writer, DirectoryPath value, JsonSerializer serializer) 8 | { 9 | writer.WriteValue(value.RelativePath); 10 | } 11 | 12 | public override DirectoryPath ReadJson(JsonReader reader, Type objectType, DirectoryPath existingValue, bool hasExistingValue, 13 | JsonSerializer serializer) 14 | { 15 | if (reader.ValueType == typeof(string)) 16 | { 17 | return new DirectoryPath((string)reader.Value!); 18 | } 19 | 20 | return JsonSerializer.Create().Deserialize(reader); 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt.Json/IO/FilePathJsonConverter.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace Noggog.Json.IO; 4 | 5 | public class FilePathJsonConverter : JsonConverter 6 | { 7 | public override bool CanConvert(Type typeToConvert) 8 | { 9 | return typeToConvert == typeof(FilePath); 10 | } 11 | 12 | public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) 13 | { 14 | if (value is not FilePath file) throw new ArgumentException("FilePath was not given"); 15 | writer.WriteValue(file.RelativePath); 16 | } 17 | 18 | public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, 19 | JsonSerializer serializer) 20 | { 21 | if (reader.ValueType == typeof(string)) 22 | { 23 | return new FilePath((string)reader.Value!); 24 | } 25 | 26 | return JsonSerializer.Create().Deserialize(reader); 27 | } 28 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt.Json/JsonConvertersMixIn.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Noggog.Json.IO; 3 | 4 | namespace Noggog.Json; 5 | 6 | public static class JsonConvertersMixIn 7 | { 8 | public static readonly FilePathJsonConverter FilePathConverter = new(); 9 | public static readonly DirectoryPathJsonConverter DirectoryPathConverter = new(); 10 | 11 | public static void AddNoggogConverters(this JsonSerializerSettings settings) 12 | { 13 | settings.Converters.Add(FilePathConverter); 14 | settings.Converters.Add(DirectoryPathConverter); 15 | } 16 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Comparers/ReferenceEqualityComparer.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | /// 4 | /// An equality comparer that evaluates equality based on ReferenceEquals 5 | /// 6 | public class ReferenceEqualityComparer : EqualityComparer 7 | { 8 | /// 9 | /// A static readonly singleton instance of ReferenceEqualityComparer for use 10 | /// 11 | public readonly static ReferenceEqualityComparer Instance = new ReferenceEqualityComparer(); 12 | 13 | private ReferenceEqualityComparer() 14 | { 15 | } 16 | 17 | /// 18 | /// Evaluates reference equality 19 | /// 20 | /// Left hand side 21 | /// Right hand side 22 | /// True if same referencec 23 | public override bool Equals(T? lhs, T? rhs) 24 | { 25 | return ReferenceEquals(lhs, rhs); 26 | } 27 | 28 | /// 29 | /// Calculates hash normally by calling an object's own GetHashCode 30 | /// 31 | /// Object to hash 32 | /// Hash returned by object 33 | public override int GetHashCode(T obj) 34 | { 35 | if (obj == null) return 0; 36 | return obj.GetHashCode(); 37 | } 38 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Containers/ExtendedList.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public class ExtendedList : List, IExtendedList, IShallowCloneable 4 | { 5 | public ExtendedList() 6 | : base() 7 | { 8 | } 9 | 10 | public ExtendedList(IEnumerable collection) 11 | : base(collection) 12 | { 13 | } 14 | 15 | public void InsertRange(IEnumerable collection, int index) 16 | { 17 | foreach (var item in collection.Reverse()) 18 | { 19 | Insert(index, item); 20 | } 21 | } 22 | 23 | public void Move(int original, int destination) 24 | { 25 | var item = this[original]; 26 | RemoveAt(original); 27 | Insert(destination, item); 28 | } 29 | 30 | public object ShallowClone() 31 | { 32 | return new ExtendedList(this); 33 | } 34 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Containers/Interfaces/IArray2d.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface IReadOnlyArray2d : IEnumerable> 4 | { 5 | int Width { get; } 6 | int Height { get; } 7 | T this[int xIndex, int yIndex] { get; } 8 | T this[P2Int index] { get; } 9 | } 10 | 11 | public interface IArray2d : IReadOnlyArray2d, IEnumerable> 12 | { 13 | new T this[int xIndex, int yIndex] { get; set; } 14 | new T this[P2Int index] { get; set; } 15 | public void SetTo(IReadOnlyArray2d rhs); 16 | public void Set(IEnumerable> vals); 17 | public void SetAllTo(T item); 18 | public void SetAllTo(Func item); 19 | new IEnumerator> GetEnumerator(); 20 | } 21 | 22 | public static class IArray2dExt 23 | { 24 | public static Array2d ShallowClone(this IReadOnlyArray2d arr) 25 | { 26 | if (arr is Array2d direct) 27 | { 28 | return direct.ShallowClone(); 29 | } 30 | 31 | return new Array2d(arr); 32 | } 33 | 34 | public static void SetTo(this IArray2d arr, IEnumerable> vals, T fallback) 35 | { 36 | arr.SetAllTo(fallback); 37 | arr.Set(vals); 38 | } 39 | 40 | public static void SetTo(this IArray2d arr, IEnumerable> vals, Func fallback) 41 | { 42 | arr.SetAllTo(fallback); 43 | arr.Set(vals); 44 | } 45 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Containers/Interfaces/IKeyValue.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | /// 4 | /// A keyed value. 5 | /// Useful compared to KeyValuePair as the interface is covariant 6 | /// 7 | /// The type of the key. 8 | /// The type of the object. 9 | public interface IKeyValue 10 | { 11 | /// 12 | /// The key 13 | /// 14 | TKey Key { get; } 15 | 16 | /// 17 | /// The value 18 | /// 19 | TObject Value { get; } 20 | } 21 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/Containers/Interfaces/ISortedList.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Noggog; 5 | 6 | public interface ISortedListGetter : IReadOnlyList 7 | { 8 | bool TryGetIndexInDirection( 9 | T item, 10 | bool higher, 11 | out int result); 12 | 13 | bool TryGetValueInDirection( 14 | T item, 15 | bool higher, 16 | [MaybeNullWhen(false)] out T result); 17 | 18 | bool TryGetInDirection( 19 | T item, 20 | bool higher, 21 | out KeyValuePair result); 22 | 23 | bool TryGetEncapsulatedIndices( 24 | T lowerKey, 25 | T higherKey, 26 | out RangeInt32 result); 27 | 28 | bool TryGetEncapsulatedValues( 29 | T lowerKey, 30 | T higherKey, 31 | [MaybeNullWhen(false)] out IEnumerable> result); 32 | } 33 | 34 | public interface ISortedList : ISortedListGetter, IList, ICollection 35 | { 36 | bool Add(T item, bool replaceIfMatch); 37 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Containers/Interfaces/ISortingListDictionary.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Noggog; 5 | 6 | public interface ISortingListDictionaryGetter : 7 | IEnumerable, 8 | IReadOnlyDictionary, 9 | IReadOnlyCollection> 10 | { 11 | bool TryGetIndexInDirection( 12 | TKey item, 13 | bool higher, 14 | out int result); 15 | 16 | bool TryGetValueInDirection( 17 | TKey item, 18 | bool higher, 19 | [MaybeNullWhen(false)] out TValue result); 20 | 21 | bool TryGetInDirection( 22 | TKey item, 23 | bool higher, 24 | out KeyValuePair result); 25 | 26 | bool TryGetEncapsulatedIndices( 27 | TKey lowerKey, 28 | TKey higherKey, 29 | out RangeInt32 result); 30 | 31 | bool TryGetEncapsulatedValues( 32 | TKey lowerKey, 33 | TKey higherKey, 34 | [MaybeNullWhen(false)] out IEnumerable> result); 35 | } 36 | 37 | public interface ISortingListDictionary : 38 | ISortingListDictionaryGetter, 39 | IDictionary, 40 | ICollection>, 41 | IEnumerable>, 42 | IEnumerable, 43 | IDictionary, 44 | ICollection, 45 | IReadOnlyDictionary, 46 | IReadOnlyCollection> 47 | { 48 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Containers/SingleCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Noggog; 4 | 5 | public class SingleCollection : IReadOnlyList, ICollection 6 | { 7 | private readonly T _item; 8 | 9 | public SingleCollection(T item) 10 | { 11 | _item = item; 12 | } 13 | 14 | public IEnumerator GetEnumerator() 15 | { 16 | yield return _item; 17 | } 18 | 19 | IEnumerator IEnumerable.GetEnumerator() 20 | { 21 | return GetEnumerator(); 22 | } 23 | 24 | public void Add(T item) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | 29 | public void Clear() 30 | { 31 | throw new NotImplementedException(); 32 | } 33 | 34 | public bool Contains(T item) 35 | { 36 | return EqualityComparer.Default.Equals(_item, item); 37 | } 38 | 39 | public void CopyTo(T[] array, int arrayIndex) 40 | { 41 | array[arrayIndex] = _item; 42 | } 43 | 44 | public bool Remove(T item) 45 | { 46 | throw new NotImplementedException(); 47 | } 48 | 49 | public int Count => 1; 50 | 51 | public bool IsReadOnly => true; 52 | 53 | public T this[int index] 54 | { 55 | get 56 | { 57 | if (index != 0) throw new IndexOutOfRangeException("Index was out of bounds"); 58 | return _item; 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/DotNetCli/DI/DotNetCommandPathProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.DotNetCli.DI; 2 | 3 | public interface IDotNetCommandPathProvider 4 | { 5 | string Path { get; } 6 | } 7 | 8 | public class DefaultDotNetCommandPathProvider : IDotNetCommandPathProvider 9 | { 10 | public string Path => "dotnet"; 11 | } 12 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/DotNetCli/DI/DotNetCommandStartConstructor.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace Noggog.DotNetCli.DI; 4 | 5 | public interface IDotNetCommandStartConstructor 6 | { 7 | ProcessStartInfo Construct(string command, FilePath path, params string?[] args); 8 | } 9 | 10 | public class DotNetCommandStartConstructor : IDotNetCommandStartConstructor 11 | { 12 | public IDotNetCommandPathProvider DotNetPathProvider { get; } 13 | 14 | public DotNetCommandStartConstructor( 15 | IDotNetCommandPathProvider dotNetPathProvider) 16 | { 17 | DotNetPathProvider = dotNetPathProvider; 18 | } 19 | 20 | public ProcessStartInfo Construct(string command, FilePath path, params string?[] args) 21 | { 22 | var argStr = string.Join(" ", args.WhereNotNull()); 23 | var cmd = $"{command} \"{path.RelativePath}\"{(argStr.IsNullOrWhitespace() ? string.Empty : $" {argStr}")}"; 24 | return new ProcessStartInfo(DotNetPathProvider.Path, cmd); 25 | } 26 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/DotNetCli/DI/NugetListingQuery.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.DotNetCli.DI; 2 | 3 | public record NugetListingQuery(string Package, string Requested, string Resolved, string? Latest); -------------------------------------------------------------------------------- /Noggog.CSharpExt/DotNetCli/DI/ProcessNugetQueryResults.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.DotNetCli.DI; 2 | 3 | public interface IProcessNugetQueryResults 4 | { 5 | IEnumerable Process(IReadOnlyList output); 6 | } 7 | 8 | public class ProcessNugetQueryResults : IProcessNugetQueryResults 9 | { 10 | public const string Prefix = " > "; 11 | public INugetListingParser LineParser { get; } 12 | 13 | public ProcessNugetQueryResults( 14 | INugetListingParser lineParser) 15 | { 16 | LineParser = lineParser; 17 | } 18 | 19 | public IEnumerable Process(IReadOnlyList output) 20 | { 21 | var lines = new List(); 22 | foreach (var s in output) 23 | { 24 | if (!s.StartsWith(Prefix)) continue; 25 | lines.Add(s); 26 | } 27 | 28 | var ret = new List(); 29 | foreach (var line in lines) 30 | { 31 | if (!LineParser.TryParse( 32 | line, 33 | out var package, 34 | out var requested, 35 | out var resolved, 36 | out var latest)) 37 | { 38 | continue; 39 | } 40 | ret.Add(new(package, requested, resolved, latest)); 41 | } 42 | return ret; 43 | } 44 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Enums/SetTo.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public enum SetTo 4 | { 5 | /// 6 | /// Clear existing collection, and set it to the new set of values 7 | /// 8 | Whitewash, 9 | 10 | /// 11 | /// Adds only new values that don't already exist to the collection 12 | /// 13 | SkipExisting, 14 | 15 | /// 16 | /// Sets all new values into the collection, replacing existing collisions 17 | /// 18 | SetExisting, 19 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/ActionExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class ActionExt 4 | { 5 | public static readonly Action Nothing = new Action(() => { }); 6 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/AsyncEnumerableExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | using System.Linq; 3 | 4 | public static class AsyncEnumerableExt 5 | { 6 | public static IAsyncEnumerable NotNull(this IAsyncEnumerable e) 7 | where T : class 8 | { 9 | return e.Where(i => i != null)!; 10 | } 11 | 12 | public static IAsyncEnumerable NotNull(this IAsyncEnumerable e) 13 | where T : struct 14 | { 15 | return e.Where(i => i.HasValue) 16 | .Select(i => i!.Value); 17 | } 18 | 19 | public static IAsyncEnumerable DoAwait(this IAsyncEnumerable e, Func doJob) 20 | { 21 | return e.SelectAwait(async i => 22 | { 23 | await doJob(i); 24 | return i; 25 | }); 26 | } 27 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/BitVector32Ext.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | 3 | namespace Noggog; 4 | 5 | public static class BitVector32Ext 6 | { 7 | private static readonly int[] _masks; 8 | 9 | static BitVector32Ext() 10 | { 11 | _masks = new int[32]; 12 | for (int i = 1; i < 32; i++) 13 | { 14 | _masks[i] = BitVector32.CreateMask(_masks[i - 1]); 15 | } 16 | } 17 | 18 | public static int GetNthMask(int i) 19 | { 20 | return _masks[i]; 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/CancellationExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class CancellationExt 4 | { 5 | public static CancellationToken Combine(this CancellationToken token, CancellationToken other) 6 | { 7 | return CancellationTokenSource.CreateLinkedTokenSource(token, other).Token; 8 | } 9 | 10 | public static CancellationToken Combine(this CancellationToken token, params CancellationToken[] other) 11 | { 12 | return CancellationTokenSource.CreateLinkedTokenSource(token.AsEnumerable().And(other).ToArray()).Token; 13 | } 14 | 15 | public static Task WhenCanceled(this CancellationToken cancellationToken) 16 | { 17 | var tcs = new TaskCompletionSource(); 18 | cancellationToken.Register(s => s.SetResult(true), tcs); 19 | return tcs.Task; 20 | } 21 | 22 | public static CancellationTokenRegistration Register(this CancellationToken cancellationToken, Action toDo, T obj) 23 | { 24 | return cancellationToken.Register(o => toDo((T)o!), obj); 25 | } 26 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/CollectionExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class CollectionExt 4 | { 5 | public static T AddReturn(this ICollection coll, T item) 6 | { 7 | coll.Add(item); 8 | return item; 9 | } 10 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/CompositeDisposableExt.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | 3 | namespace Noggog; 4 | 5 | public static class CompositeDisposableExt 6 | { 7 | public static void Add(this CompositeDisposable dispose, IEnumerable disposables) 8 | { 9 | foreach (var disp in disposables) 10 | { 11 | dispose.Add(disp); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/HashCodeExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class HashCodeExt 4 | { 5 | public static void AddEnumerable(this HashCode hashCode, IEnumerable col) 6 | { 7 | foreach (var val in col) 8 | { 9 | hashCode.Add(val); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/HashSetExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class HashSetExt 4 | { 5 | public static void Add(this HashSet set, IEnumerable enumer) 6 | { 7 | foreach (var e in enumer) 8 | { 9 | set.Add(e); 10 | } 11 | } 12 | 13 | public static void Add(this HashSet set, params T[] objs) 14 | { 15 | foreach (var e in objs) 16 | { 17 | set.Add(e); 18 | } 19 | } 20 | 21 | public static void Remove(this HashSet set, IEnumerable vals) 22 | { 23 | foreach (var item in vals) 24 | { 25 | set.Remove(item); 26 | } 27 | } 28 | 29 | public static bool SetEquals(this HashSet set, params T[] rhs) 30 | { 31 | return set.SetEquals((IEnumerable)rhs); 32 | } 33 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/IDisposableExt.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | 3 | namespace Noggog; 4 | 5 | public static class IDisposableExt 6 | { 7 | public static T DisposeWith(this T disposable, IDisposableDropoff compositeDisposable) 8 | where T : IDisposable 9 | { 10 | compositeDisposable.Add(disposable); 11 | return disposable; 12 | } 13 | 14 | public static T DisposeWithComposite(this T disposable, CompositeDisposable compositeDisposable) 15 | where T : IDisposable 16 | { 17 | compositeDisposable.Add(disposable); 18 | return disposable; 19 | } 20 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/Int16Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class Int16Ext 4 | { 5 | public static bool IsInRange(this short d, short min, short max) 6 | { 7 | if (d < min) return false; 8 | if (d > max) return false; 9 | return true; 10 | } 11 | 12 | public static short InRange(this short d, short min, short max) 13 | { 14 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 15 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 16 | return d; 17 | } 18 | 19 | public static short PutInRange(this short d, short min, short max) 20 | { 21 | if (d < min) return min; 22 | if (d > max) return max; 23 | return d; 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/Int32Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class Int32Ext 4 | { 5 | public static int Clamp(this int a, int min, int max) 6 | { 7 | return Math.Min(Math.Max(a, min), max); 8 | } 9 | 10 | public static bool IsInRange(this int d, int min, int max) 11 | { 12 | if (d < min) return false; 13 | if (d > max) return false; 14 | return true; 15 | } 16 | 17 | public static int InRange(this int d, int min, int max) 18 | { 19 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 20 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 21 | return d; 22 | } 23 | 24 | public static int PutInRange(this int d, int min, int max) 25 | { 26 | if (d < min) return min; 27 | if (d > max) return max; 28 | return d; 29 | } 30 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/Int64Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class Int64Ext 4 | { 5 | public static bool IsInRange(this long d, long min, long max) 6 | { 7 | if (d < min) return false; 8 | if (d > max) return false; 9 | return true; 10 | } 11 | 12 | public static long InRange(this long d, long min, long max) 13 | { 14 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 15 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 16 | return d; 17 | } 18 | 19 | public static long PutInRange(this long d, long min, long max) 20 | { 21 | if (d < min) return min; 22 | if (d > max) return max; 23 | return d; 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/Int8Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class Int8Ext 4 | { 5 | public static bool IsInRange(this sbyte d, sbyte min, sbyte max) 6 | { 7 | if (d < min) return false; 8 | if (d > max) return false; 9 | return true; 10 | } 11 | 12 | public static sbyte InRange(this sbyte d, sbyte min, sbyte max) 13 | { 14 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 15 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 16 | return d; 17 | } 18 | 19 | public static sbyte PutInRange(this sbyte d, sbyte min, sbyte max) 20 | { 21 | if (d < min) return min; 22 | if (d > max) return max; 23 | return d; 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/MathExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class MathExt 4 | { 5 | public static int Min(IEnumerable e) 6 | { 7 | int? rhs = null; 8 | foreach (var i in e) 9 | { 10 | rhs = Math.Min(i, rhs ?? int.MaxValue); 11 | } 12 | if (rhs == null) 13 | { 14 | throw new ArgumentException("Enumerable contained no items."); 15 | } 16 | return rhs.Value; 17 | } 18 | 19 | public static int Min(params int[] e) 20 | { 21 | return Min((IEnumerable)e); 22 | } 23 | 24 | public static int Max(IEnumerable e) 25 | { 26 | int? rhs = null; 27 | foreach (var i in e) 28 | { 29 | rhs = Math.Max(i, rhs ?? int.MinValue); 30 | } 31 | if (rhs == null) 32 | { 33 | throw new ArgumentException("Enumerable contained no items."); 34 | } 35 | return rhs.Value; 36 | } 37 | 38 | public static int Max(params int[] e) 39 | { 40 | return Max((IEnumerable)e); 41 | } 42 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/MemberInfoExt.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.Reflection; 3 | 4 | namespace Noggog; 5 | 6 | public static class MemberInfoExt 7 | { 8 | public static bool TryGetCustomAttribute(this MemberInfo memberInfo, [MaybeNullWhen(false)] out T attr) 9 | where T : Attribute 10 | { 11 | attr = memberInfo.GetCustomAttribute(); 12 | return attr != null; 13 | } 14 | 15 | public static bool IsStatic(this PropertyInfo memberInfo) 16 | { 17 | var method = (memberInfo.GetMethod ?? memberInfo.SetMethod)!; 18 | return method.IsStatic; 19 | } 20 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/ParallelQueryExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Extensions; 2 | 3 | public static class ParallelQueryExt 4 | { 5 | public static IEnumerable NotNull(this ParallelQuery e) 6 | where T : class 7 | { 8 | return e.Where(i => i != null)!; 9 | } 10 | 11 | public static IEnumerable NotNull(this ParallelQuery e) 12 | where T : struct 13 | { 14 | return e.Where(i => i.HasValue) 15 | .Select(i => i!.Value); 16 | } 17 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/QueueExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class QueueExt 4 | { 5 | public static void Enqueue(this Queue queue, IEnumerable rhs) 6 | { 7 | foreach (T t in rhs) 8 | { 9 | queue.Enqueue(t); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/RangeDoubleExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class RangeDoubleExt 4 | { 5 | public static double Get(this RangeDouble d, RandomSource rand) 6 | { 7 | return rand.NextDouble(d.Max - d.Min) + d.Min; 8 | } 9 | 10 | public static double GetNormalDist(this RangeDouble d, RandomSource rand) 11 | { 12 | return rand.NextNormalDist(d.Min, d.Max); 13 | } 14 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/RangeIntExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class RangeIntExt 4 | { 5 | public static int Get(this RangeInt32 range, RandomSource rand) 6 | { 7 | if (range.Min == range.Max) 8 | { 9 | return range.Min; 10 | } 11 | else 12 | { 13 | return rand.Next(range.Min, range.Max + 1); 14 | } 15 | } 16 | 17 | public static int GetNormalDist(this RangeInt32 range, RandomSource rand) 18 | { 19 | if (range.Min == range.Max) 20 | { 21 | return range.Min; 22 | } 23 | else 24 | { 25 | return rand.NextNormalDist(range.Min, range.Max + 1); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/SourceCacheExt.cs: -------------------------------------------------------------------------------- 1 | using DynamicData; 2 | using System.Diagnostics.CodeAnalysis; 3 | 4 | namespace Noggog; 5 | 6 | public static class SourceCacheExt 7 | { 8 | public static bool TryGetValue(this IObservableCache cache, TKey key, [MaybeNullWhen(false)] out TObject value) 9 | where TKey : notnull 10 | where TObject : notnull 11 | { 12 | var lookup = cache.Lookup(key); 13 | if (lookup.HasValue) 14 | { 15 | value = lookup.Value; 16 | return true; 17 | } 18 | value = default; 19 | return false; 20 | } 21 | 22 | public static TObject Get(this IObservableCache cache, TKey key) 23 | where TKey : notnull 24 | where TObject : notnull 25 | { 26 | if (!TryGetValue(cache, key, out var val)) 27 | { 28 | throw new KeyNotFoundException(); 29 | } 30 | return val; 31 | } 32 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/SourceListExt.cs: -------------------------------------------------------------------------------- 1 | using DynamicData; 2 | 3 | namespace Noggog; 4 | 5 | public static class SourceListExt 6 | { 7 | public static void SetTo(this ISourceList list, IEnumerable items, bool checkEquality = false) 8 | where T : notnull 9 | { 10 | list.Edit(l => 11 | { 12 | int i = 0; 13 | foreach (var item in items) 14 | { 15 | if (i >= l.Count) 16 | { 17 | l.Add(item); 18 | } 19 | else if (checkEquality) 20 | { 21 | if (!EqualityComparer.Default.Equals(l[i], item)) 22 | { 23 | l[i] = item; 24 | } 25 | } 26 | else 27 | { 28 | l[i] = item; 29 | } 30 | i++; 31 | } 32 | 33 | l.RemoveToCount(i); 34 | }); 35 | } 36 | 37 | public static void RemoveToCount(this ISourceList list, int count) 38 | where T : notnull 39 | { 40 | list.Edit(l => 41 | { 42 | var toRemove = l.Count - count; 43 | for (; toRemove > 0; toRemove--) 44 | { 45 | l.RemoveAt(l.Count - 1); 46 | } 47 | }); 48 | } 49 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/StackExt.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace Noggog; 4 | 5 | public static class StackExt 6 | { 7 | public static bool TryPop(this Stack stack, [MaybeNullWhen(false)] out T item) 8 | { 9 | if (stack.Count > 0) 10 | { 11 | item = stack.Pop(); 12 | return true; 13 | } 14 | else 15 | { 16 | item = default; 17 | return false; 18 | } 19 | } 20 | 21 | public static bool TryPeek(this Stack stack, [MaybeNullWhen(false)] out T item) 22 | { 23 | if (stack.Count > 0) 24 | { 25 | item = stack.Peek(); 26 | return true; 27 | } 28 | else 29 | { 30 | item = default; 31 | return false; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/StreamExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class StreamExt 4 | { 5 | public static long Remaining(this Stream stream) 6 | { 7 | return stream.Length - stream.Position; 8 | } 9 | 10 | // https://stackoverflow.com/questions/1358510/how-to-compare-2-files-fast-using-net 11 | const int BYTES_TO_READ = sizeof(Int64); 12 | public static bool ContentsEqual(this Stream first, Stream second) 13 | { 14 | if (first.Length != second.Length) 15 | return false; 16 | 17 | int iterations = (int)Math.Ceiling((double)first.Length / BYTES_TO_READ); 18 | 19 | byte[] one = new byte[BYTES_TO_READ]; 20 | byte[] two = new byte[BYTES_TO_READ]; 21 | 22 | for (int i = 0; i < iterations; i++) 23 | { 24 | if (0 == first.Read(one, 0, BYTES_TO_READ)) return false; 25 | if (0 == second.Read(two, 0, BYTES_TO_READ)) return false; 26 | 27 | if (BitConverter.ToInt64(one, 0) != BitConverter.ToInt64(two, 0)) 28 | return false; 29 | } 30 | 31 | return true; 32 | } 33 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/UInt16Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class UInt16Ext 4 | { 5 | public static bool IsInRange(this ushort d, ushort min, ushort max) 6 | { 7 | if (d < min) return false; 8 | if (d > max) return false; 9 | return true; 10 | } 11 | 12 | public static ushort InRange(this ushort d, ushort min, ushort max) 13 | { 14 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 15 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 16 | return d; 17 | } 18 | 19 | public static ushort PutInRange(this ushort d, ushort min, ushort max) 20 | { 21 | if (d < min) return min; 22 | if (d > max) return max; 23 | return d; 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/UInt32Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class UInt32Ext 4 | { 5 | public static bool IsInRange(this uint d, uint min, uint max) 6 | { 7 | if (d < min) return false; 8 | if (d > max) return false; 9 | return true; 10 | } 11 | 12 | public static uint InRange(this uint d, uint min, uint max) 13 | { 14 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 15 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 16 | return d; 17 | } 18 | 19 | public static uint PutInRange(this uint d, uint min, uint max) 20 | { 21 | if (d < min) return min; 22 | if (d > max) return max; 23 | return d; 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Extensions/UInt64Ext.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public static class UInt64Ext 4 | { 5 | public static bool IsInRange(this ulong d, ulong min, ulong max) 6 | { 7 | if (d < min) return false; 8 | if (d > max) return false; 9 | return true; 10 | } 11 | 12 | public static ulong InRange(this ulong d, ulong min, ulong max) 13 | { 14 | if (d < min) throw new ArgumentException($"{d} was lower than the minimum {min}."); 15 | if (d > max) throw new ArgumentException($"{d} was greater than the maximum {max}."); 16 | return d; 17 | } 18 | 19 | public static ulong PutInRange(this ulong d, ulong min, ulong max) 20 | { 21 | if (d < min) return min; 22 | if (d > max) return max; 23 | return d; 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IO/CurrentDirectoryProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.IO; 2 | 3 | public interface ICurrentDirectoryProvider 4 | { 5 | DirectoryPath CurrentDirectory { get; } 6 | } 7 | 8 | public class CurrentDirectoryProvider : ICurrentDirectoryProvider 9 | { 10 | public DirectoryPath CurrentDirectory => Environment.CurrentDirectory; 11 | } 12 | 13 | public class CurrentDirectoryInjection : ICurrentDirectoryProvider 14 | { 15 | public CurrentDirectoryInjection(DirectoryPath currentDirectory) 16 | { 17 | CurrentDirectory = currentDirectory; 18 | } 19 | 20 | public DirectoryPath CurrentDirectory { get; } 21 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IO/DeepCopyDirectory.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | 3 | namespace Noggog.IO; 4 | 5 | public interface IDeepCopyDirectory 6 | { 7 | void DeepCopy(DirectoryPath dir, DirectoryPath rhs, bool overwrite = false); 8 | } 9 | 10 | public class DeepCopyDirectory : IDeepCopyDirectory 11 | { 12 | private readonly IFileSystem _fileSystem; 13 | 14 | public DeepCopyDirectory(IFileSystem fileSystem) 15 | { 16 | _fileSystem = fileSystem; 17 | } 18 | 19 | public void DeepCopy(DirectoryPath dir, DirectoryPath rhs, bool overwrite = false) 20 | { 21 | _fileSystem.Directory.DeepCopy(dir, rhs, overwrite: overwrite); 22 | } 23 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IO/DeleteEntireDirectory.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | 3 | namespace Noggog.IO; 4 | 5 | public interface IDeleteEntireDirectory 6 | { 7 | void DeleteEntireFolder( 8 | DirectoryPath dir, 9 | bool disableReadOnly = true, 10 | bool deleteFolderItself = true); 11 | } 12 | 13 | public class DeleteEntireDirectory : IDeleteEntireDirectory 14 | { 15 | private readonly IFileSystem _fileSystem; 16 | 17 | public DeleteEntireDirectory(IFileSystem fileSystem) 18 | { 19 | _fileSystem = fileSystem; 20 | } 21 | 22 | public void DeleteEntireFolder( 23 | DirectoryPath dir, 24 | bool disableReadOnly = true, 25 | bool deleteFolderItself = true) 26 | { 27 | dir.DeleteEntireFolder( 28 | disableReadOnly: disableReadOnly, 29 | deleteFolderItself: deleteFolderItself, 30 | fileSystem: _fileSystem); 31 | } 32 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IO/EnvironmentTemporaryDirectoryProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.IO; 2 | 3 | public interface IEnvironmentTemporaryDirectoryProvider 4 | { 5 | DirectoryPath Path { get; } 6 | } 7 | 8 | public class EnvironmentTemporaryDirectoryProvider : IEnvironmentTemporaryDirectoryProvider 9 | { 10 | public DirectoryPath Path => System.IO.Path.GetTempPath(); 11 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IO/ExportStringToFile.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | 3 | namespace Noggog.IO; 4 | 5 | public interface IExportStringToFile 6 | { 7 | void ExportToFile(FilePath file, string str, bool onlyIfChanged = true); 8 | } 9 | 10 | public class ExportStringToFile : IExportStringToFile 11 | { 12 | private readonly IFileSystem _fileSystem; 13 | 14 | public ExportStringToFile(IFileSystem fileSystem) 15 | { 16 | _fileSystem = fileSystem; 17 | } 18 | 19 | public void ExportToFile(FilePath file, string str, bool onlyIfChanged = true) 20 | { 21 | if (onlyIfChanged && _fileSystem.File.Exists(file)) 22 | { 23 | var existStr = _fileSystem.File.ReadAllText(file.Path); 24 | if (str.Equals(existStr)) return; 25 | } 26 | 27 | if (file.Directory != null) 28 | { 29 | _fileSystem.Directory.CreateDirectory(file.Directory); 30 | } 31 | 32 | _fileSystem.File.WriteAllText(file.Path, str); 33 | } 34 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IO/ICreateStream.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | 3 | namespace Noggog.IO; 4 | 5 | public interface ICreateStream 6 | { 7 | Stream GetStreamFor(IFileSystem fileSystem, FilePath path, bool write); 8 | } 9 | 10 | public class NormalFileStreamCreator : ICreateStream 11 | { 12 | public static readonly NormalFileStreamCreator Instance = new(); 13 | 14 | public Stream GetStreamFor(IFileSystem fileSystem, FilePath path, bool write) 15 | { 16 | return fileSystem.File.Open(path, write ? FileMode.Create : FileMode.Open, write ? FileAccess.Write : FileAccess.Read, FileShare.Read); 17 | } 18 | } 19 | 20 | public class NoPreferenceStreamCreator : ICreateStream 21 | { 22 | public Stream GetStreamFor(IFileSystem fileSystem, FilePath path, bool write) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | 28 | public static class ICreateStreamExt 29 | { 30 | public static ICreateStream GetOrFallback(this ICreateStream? createStream, Func fallback) 31 | { 32 | if (createStream == null || createStream is NoPreferenceStreamCreator) 33 | { 34 | return fallback(); 35 | } 36 | 37 | return createStream; 38 | } 39 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Interfaces/IClearable.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface IClearable 4 | { 5 | void Clear(); 6 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Interfaces/ISelectable.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface ISelectableItem : ISelectable, ISelectedItem 4 | { 5 | new TItem Item { get; set; } 6 | new bool IsSelected { get; set; } 7 | } 8 | 9 | public interface ISelectable : ISelected 10 | { 11 | new bool IsSelected { get; set; } 12 | } 13 | 14 | public interface ISelectedItem : ISelected 15 | { 16 | TItem Item { get; } 17 | } 18 | 19 | public interface ISelected 20 | { 21 | bool IsSelected { get; } 22 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Interfaces/IShallowCloneable.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface IShallowCloneable 4 | { 5 | object ShallowClone(); 6 | } 7 | 8 | public interface IShallowCloneable : IShallowCloneable 9 | { 10 | new T ShallowClone(); 11 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/IsExternalInit.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | namespace System.Runtime.CompilerServices 3 | { 4 | // Add ability to use records in net framework projects 5 | public sealed class IsExternalInit 6 | { 7 | } 8 | } 9 | #endif -------------------------------------------------------------------------------- /Noggog.CSharpExt/Processes/DI/ProcessFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace Noggog.Processes.DI; 4 | 5 | public interface IProcessFactory 6 | { 7 | IProcessWrapper Create( 8 | ProcessStartInfo startInfo, 9 | CancellationToken cancel = default, 10 | bool hideWindow = true, 11 | bool hookOntoOutput = true, 12 | bool killWithParent = true); 13 | } 14 | 15 | public class ProcessFactory : IProcessFactory 16 | { 17 | public IProcessWrapper Create( 18 | ProcessStartInfo startInfo, 19 | CancellationToken cancel = default, 20 | bool hideWindow = true, 21 | bool hookOntoOutput = true, 22 | bool killWithParent = true) 23 | { 24 | return ProcessWrapper.Create( 25 | startInfo, 26 | cancel, 27 | hideWindow: hideWindow, 28 | hookOntoOutput: hookOntoOutput, 29 | killWithParent: killWithParent); 30 | } 31 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Processes/ProcessResult.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Processes; 2 | 3 | public record ProcessResult(int Result, List Out, List Errors) 4 | { 5 | public bool FailedReturn => Result != 0; 6 | public bool FailedReturnOrErrorMessages => FailedReturn || Errors.Count > 0; 7 | public bool NoDetectableErrors => !FailedReturnOrErrorMessages; 8 | 9 | public ProcessResult() 10 | : this(-1, new(), new()) 11 | { 12 | } 13 | 14 | public ErrorResponse AsErrorResponse() 15 | { 16 | if (Result == 0 && Errors.Count == 0) 17 | { 18 | return ErrorResponse.Success; 19 | } 20 | 21 | if (Errors.Count > 1) 22 | { 23 | return ErrorResponse.Fail($"[{Result}]: \n{Errors.First()}\n ..."); 24 | } 25 | else if (Errors.Count == 1) 26 | { 27 | return ErrorResponse.Fail($"[{Result}]: \n{Errors.First()}"); 28 | } 29 | else 30 | { 31 | return ErrorResponse.Fail($"[{Result}]"); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("CSharpExt.UnitTests")] 4 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/Reactive/ISchedulerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Concurrency; 2 | 3 | namespace Noggog.Reactive; 4 | 5 | public interface ISchedulerProvider 6 | { 7 | public IScheduler MainThread { get; } 8 | public IScheduler TaskPool { get; } 9 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Reactive/WatchDirectory.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | using System.Reactive; 3 | 4 | namespace Noggog.Reactive; 5 | 6 | public interface IWatchDirectory 7 | { 8 | IObservable Watch(DirectoryPath path, bool throwIfInvalidPath = false); 9 | } 10 | 11 | public class WatchDirectory : IWatchDirectory 12 | { 13 | private readonly IFileSystem _FileSystem; 14 | 15 | public WatchDirectory(IFileSystem fileSystem) 16 | { 17 | _FileSystem = fileSystem; 18 | } 19 | 20 | public IObservable Watch(DirectoryPath path, bool throwIfInvalidPath = false) 21 | { 22 | return ObservableExt.WatchFolder(path, throwIfInvalidPath, _FileSystem.FileSystemWatcher); 23 | } 24 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Reactive/WatchFile.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | using System.Reactive; 3 | 4 | namespace Noggog.Reactive; 5 | 6 | public interface IWatchFile 7 | { 8 | IObservable Watch(FilePath path, bool throwIfInvalidPath = false); 9 | } 10 | 11 | public class WatchFile : IWatchFile 12 | { 13 | private readonly IFileSystem _FileSystem; 14 | 15 | public WatchFile(IFileSystem fileSystem) 16 | { 17 | _FileSystem = fileSystem; 18 | } 19 | 20 | public IObservable Watch(FilePath path, bool throwIfInvalidPath = false) 21 | { 22 | return ObservableExt.WatchFile(path, throwIfInvalidPath, _FileSystem.FileSystemWatcher); 23 | } 24 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Streams/Binary/BinaryMemoryWriteStream.cs: -------------------------------------------------------------------------------- 1 | using Noggog.Streams.Binary; 2 | 3 | namespace Noggog; 4 | 5 | public static class BinaryMemoryWriteStream 6 | { 7 | public static IBinaryMemoryWriteStream Factory(byte[] buffer, bool isLittleEndian) 8 | { 9 | return isLittleEndian 10 | ? new LittleEndianBinaryMemoryWriteStream(buffer) 11 | : new BigEndianBinaryMemoryWriteStream(buffer); 12 | } 13 | 14 | public static IBinaryMemoryWriteStream LittleEndian(byte[] buffer) 15 | { 16 | return new LittleEndianBinaryMemoryWriteStream(buffer); 17 | } 18 | 19 | public static IBinaryMemoryWriteStream BigEndian(byte[] buffer) 20 | { 21 | return new BigEndianBinaryMemoryWriteStream(buffer); 22 | } 23 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Streams/Binary/IBinaryMemoryWriteStream.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface IBinaryMemoryWriteStream : IBinaryWriteStream 4 | { 5 | new int Position { get; set; } 6 | new int Length { get; } 7 | int Remaining { get; } 8 | void Write(ReadOnlySpan buffer, int offset, int amount); 9 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Streams/Binary/IBinaryWriteStream.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface IBinaryWriteStream : IDisposable 4 | { 5 | long Position { get; set; } 6 | long Length { get; } 7 | bool IsLittleEndian { get; } 8 | Stream BaseStream { get; } 9 | #if NETSTANDARD2_0 10 | #else 11 | void Write(ReadOnlySpan buffer); 12 | #endif 13 | void Write(bool value); 14 | void Write(byte value); 15 | void Write(ushort value); 16 | void Write(uint value); 17 | void Write(ulong value); 18 | void Write(sbyte value); 19 | void Write(short value); 20 | void Write(int value); 21 | void Write(long value); 22 | void Write(float value); 23 | void Write(double value); 24 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Structs/FileSystems/IPath.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public interface IPath 4 | { 5 | bool Exists { get; } 6 | string Path { get; } 7 | FileName Name { get; } 8 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Structs/IndexedItem.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public record struct IndexedItem(int Index, T Item); -------------------------------------------------------------------------------- /Noggog.CSharpExt/Structs/KeyValue.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public readonly struct KeyValue : IKeyValue 4 | { 5 | public TKey Key { get; } 6 | public TValue Value { get; } 7 | 8 | public KeyValue(TKey key, TValue value) 9 | { 10 | Key = key; 11 | Value = value; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/Structs/LastMarkedItem.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public record struct LastMarkedItem(T Item, bool Last); -------------------------------------------------------------------------------- /Noggog.CSharpExt/Structs/LifecycleActions.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public struct LifecycleActions 4 | { 5 | public readonly Action? OnCreate; 6 | public readonly Action? OnGet; 7 | public readonly Action? OnReturn; 8 | public readonly Action? OnDestroy; 9 | 10 | public LifecycleActions( 11 | Action? onCreate = null, 12 | Action? onGet = null, 13 | Action? onReturn = null, 14 | Action? onDestroy = null) 15 | { 16 | OnCreate = onCreate; 17 | OnGet = onGet; 18 | OnReturn = onReturn; 19 | OnDestroy = onDestroy; 20 | } 21 | 22 | public static LifecycleActions operator +(LifecycleActions l1, LifecycleActions l2) 23 | { 24 | return new LifecycleActions( 25 | onCreate: l1.OnCreate + l2.OnCreate, 26 | onDestroy: l1.OnDestroy + l2.OnDestroy, 27 | onGet: l1.OnGet + l2.OnGet, 28 | onReturn: l1.OnReturn + l2.OnReturn); 29 | } 30 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Structs/StringCaseAgnostic.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog; 2 | 3 | public struct StringCaseAgnostic : IEquatable, IEquatable 4 | { 5 | public readonly string Upper; 6 | public readonly string Value; 7 | 8 | public StringCaseAgnostic(string str) 9 | { 10 | Value = str; 11 | Upper = str.ToUpper(); 12 | } 13 | 14 | public StringCaseAgnostic(StringCaseAgnostic rhs) 15 | { 16 | Value = rhs.Value; 17 | Upper = rhs.Upper; 18 | } 19 | 20 | public override string ToString() 21 | { 22 | return Value; 23 | } 24 | 25 | public override bool Equals(object? obj) 26 | { 27 | if (obj is not StringCaseAgnostic rhs) return false; 28 | return Equals(rhs); 29 | } 30 | 31 | public bool Equals(string? other) 32 | { 33 | return string.Equals(Upper, other?.ToUpper()); 34 | } 35 | 36 | public bool Equals(StringCaseAgnostic other) 37 | { 38 | return string.Equals(Upper, other.Upper); 39 | } 40 | 41 | public override int GetHashCode() => HashCode.Combine(Upper); 42 | 43 | public static implicit operator string(StringCaseAgnostic ag) 44 | { 45 | return ag.Value; 46 | } 47 | 48 | public static implicit operator StringCaseAgnostic(string ag) 49 | { 50 | return new StringCaseAgnostic(ag); 51 | } 52 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/Brace.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings; 2 | 3 | public class Brace : IDisposable 4 | { 5 | private readonly StructuredStringBuilder _sb; 6 | private readonly bool _doIt; 7 | private string _start; 8 | private string _end; 9 | 10 | public Brace(StructuredStringBuilder sb, string start = "[", string end = "]", bool doIt = true) 11 | { 12 | _sb = sb; 13 | _doIt = doIt; 14 | _start = start; 15 | _end = end; 16 | if (doIt) 17 | { 18 | sb.AppendLine(_start); 19 | sb.Depth++; 20 | } 21 | } 22 | 23 | public void Dispose() 24 | { 25 | if (_doIt) 26 | { 27 | _sb.Depth--; 28 | _sb.AppendLine(_end); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/CSharp/AccessModifier.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings.CSharp; 2 | 3 | public enum AccessModifier 4 | { 5 | Public, 6 | Private, 7 | Protected, 8 | Internal, 9 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/CSharp/CurlyBrace.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings.CSharp; 2 | 3 | public class CurlyBrace : IDisposable 4 | { 5 | private readonly StructuredStringBuilder _sb; 6 | private readonly bool _doIt; 7 | 8 | public bool AppendParenthesis; 9 | public bool AppendSemicolon; 10 | public bool AppendComma; 11 | 12 | public CurlyBrace(StructuredStringBuilder sb, bool doIt = true) 13 | { 14 | _sb = sb; 15 | _doIt = doIt; 16 | if (doIt) 17 | { 18 | sb.AppendLine("{"); 19 | sb.Depth++; 20 | } 21 | } 22 | 23 | public void Dispose() 24 | { 25 | if (_doIt) 26 | { 27 | _sb.Depth--; 28 | _sb.AppendLine("}" 29 | + (AppendParenthesis ? ")" : string.Empty) 30 | + (AppendSemicolon ? ";" : string.Empty) 31 | + (AppendComma ? "," : string.Empty)); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/CSharp/Namespace.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings.CSharp; 2 | 3 | public class Namespace : IDisposable 4 | { 5 | private readonly StructuredStringBuilder _sb; 6 | private readonly bool _doThings; 7 | private readonly bool _fileScoped; 8 | 9 | public Namespace(StructuredStringBuilder sb, string str, bool fileScoped = true) 10 | { 11 | _fileScoped = fileScoped; 12 | _sb = sb; 13 | _doThings = !string.IsNullOrWhiteSpace(str); 14 | if (_doThings) 15 | { 16 | sb.AppendLine($"namespace {str}{(_fileScoped ? ";" : null)}"); 17 | if (_fileScoped) 18 | { 19 | _sb.AppendLine(); 20 | } 21 | else 22 | { 23 | sb.AppendLine("{"); 24 | sb.Depth++; 25 | } 26 | } 27 | } 28 | 29 | public void Dispose() 30 | { 31 | if (!_doThings) return; 32 | if (!_fileScoped) 33 | { 34 | _sb.Depth--; 35 | _sb.AppendLine("}"); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/CSharp/ObjectType.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings.CSharp; 2 | 3 | public enum ObjectType 4 | { 5 | Class, 6 | Struct, 7 | Interface 8 | } 9 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/CSharp/Region.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings.CSharp; 2 | 3 | public class Region : IDisposable 4 | { 5 | readonly StructuredStringBuilder _sb; 6 | readonly int _startingIndex; 7 | readonly string _name; 8 | public bool AppendExtraLine; 9 | public bool SkipIfOnlyOneLine = false; 10 | 11 | public Region(StructuredStringBuilder sb, string str, bool appendExtraLine = true, bool skipIfOnlyOneLine = false) 12 | { 13 | _sb = sb; 14 | _startingIndex = sb.Count; 15 | _name = str; 16 | AppendExtraLine = appendExtraLine; 17 | SkipIfOnlyOneLine = skipIfOnlyOneLine; 18 | } 19 | 20 | public void Dispose() 21 | { 22 | if (string.IsNullOrWhiteSpace(_name)) return; 23 | if (_startingIndex == _sb.Count) return; 24 | if (SkipIfOnlyOneLine && _startingIndex + 1 == _sb.Count) return; 25 | _sb.Insert(Math.Max(0, _startingIndex), $"{_sb.DepthStr}#region {_name}"); 26 | _sb.AppendLine("#endregion"); 27 | if (AppendExtraLine) 28 | { 29 | _sb.AppendLine(); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/CommaCollection.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings; 2 | 3 | public class CommaCollection : IDisposable 4 | { 5 | private readonly StructuredStringBuilder _sb; 6 | private readonly string _delimiter; 7 | private readonly List _items = new(); 8 | 9 | public CommaCollection(StructuredStringBuilder sb, string delimiter = ",") 10 | { 11 | _sb = sb; 12 | _delimiter = delimiter; 13 | } 14 | 15 | public void Add(string item) 16 | { 17 | _items.Add(item); 18 | } 19 | 20 | public void Add(params string[] items) 21 | { 22 | _items.AddRange(items); 23 | } 24 | 25 | public void Add(Action generator) 26 | { 27 | var gen = new StructuredStringBuilder(); 28 | generator(gen); 29 | if (gen.Empty) return; 30 | Add(gen.ToArray()); 31 | } 32 | 33 | public void Dispose() 34 | { 35 | foreach (var item in _items.IterateMarkLast()) 36 | { 37 | if (item.Last) 38 | { 39 | _sb.AppendLine(item.Item); 40 | } 41 | else 42 | { 43 | using (_sb.Line()) 44 | { 45 | _sb.Append(item.Item); 46 | _sb.Append(_delimiter); 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/Depth.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings; 2 | 3 | public class Depth : IDisposable 4 | { 5 | private readonly StructuredStringBuilder _sb; 6 | private readonly bool _doIt; 7 | 8 | public Depth( 9 | StructuredStringBuilder sb, 10 | bool doIt = true) 11 | { 12 | _sb = sb; 13 | _doIt = doIt; 14 | if (doIt) 15 | { 16 | _sb.Depth++; 17 | } 18 | } 19 | 20 | public void Dispose() 21 | { 22 | if (_doIt) 23 | { 24 | _sb.Depth--; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/IPrintable.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings; 2 | 3 | public interface IPrintable 4 | { 5 | void Print(StructuredStringBuilder sb, string? name = null); 6 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/Line.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings; 2 | 3 | public class Line : IDisposable 4 | { 5 | readonly StructuredStringBuilder _sb; 6 | private readonly bool _appendNewLine; 7 | 8 | public Line(StructuredStringBuilder sb, bool appendNewLine = true) 9 | { 10 | _sb = sb; 11 | _appendNewLine = appendNewLine; 12 | _sb.Append(_sb.DepthStr); 13 | } 14 | 15 | public void Dispose() 16 | { 17 | if (_appendNewLine) 18 | { 19 | _sb.Append(Environment.NewLine); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/StructuredStrings/StructuredStringsMixIn.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.StructuredStrings; 2 | 3 | public static class StructuredStringsMixIn 4 | { 5 | public static string Print(this IPrintable printable, string? name = null) 6 | { 7 | StructuredStringBuilder sb = new(); 8 | printable.Print(sb, name); 9 | return sb.ToString(); 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Time/NowProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Time; 2 | 3 | public interface INowProvider 4 | { 5 | public DateTime NowLocal { get; } 6 | } 7 | 8 | public class NowProvider : INowProvider 9 | { 10 | public DateTime NowLocal => DateTime.Now; 11 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Utility/AsyncLazy.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace Noggog; 4 | // https://devblogs.microsoft.com/pfxteam/asynclazyt/ 5 | 6 | public class AsyncLazy : Lazy> 7 | { 8 | public AsyncLazy(Func valueFactory) 9 | : base(() => Task.Factory.StartNew(valueFactory)) 10 | { 11 | } 12 | 13 | public AsyncLazy(Func valueFactory, LazyThreadSafetyMode mode) 14 | : base(() => Task.Factory.StartNew(valueFactory), mode) 15 | { 16 | } 17 | 18 | public AsyncLazy(Func> taskFactory) 19 | : base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap()) 20 | { 21 | } 22 | 23 | public AsyncLazy(Func> taskFactory, LazyThreadSafetyMode mode) 24 | : base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap(), mode) 25 | { 26 | } 27 | 28 | public TaskAwaiter GetAwaiter() => Value.GetAwaiter(); 29 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Utility/AsyncLock.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Disposables; 2 | 3 | namespace Noggog.Utility; 4 | 5 | public class AsyncLock 6 | { 7 | private readonly SemaphoreSlim _lock = new(1, 1); 8 | 9 | public async Task WaitAsync() 10 | { 11 | await _lock.WaitAsync(); 12 | return Disposable.Create(_lock, l => l.Release()); 13 | } 14 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/Utility/TaskCompletionSource.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | 3 | namespace Noggog 4 | { 5 | public class TaskCompletionSource : TaskCompletionSource 6 | { 7 | public void SetResult() 8 | { 9 | SetResult(true); 10 | } 11 | } 12 | } 13 | 14 | #else 15 | #endif -------------------------------------------------------------------------------- /Noggog.CSharpExt/WorkEngine/INumWorkThreadsController.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | #else 3 | using System.Reactive.Linq; 4 | 5 | namespace Noggog.WorkEngine; 6 | 7 | public interface INumWorkThreadsController 8 | { 9 | IObservable NumDesiredThreads { get; } 10 | } 11 | 12 | public class NumWorkThreadsUnopinionated : INumWorkThreadsController 13 | { 14 | public IObservable NumDesiredThreads => Observable.Return(default(int?)); 15 | } 16 | 17 | public class NumWorkThreadsConstant(int? numThreads) : INumWorkThreadsController 18 | { 19 | public IObservable NumDesiredThreads => Observable.Return(numThreads); 20 | } 21 | #endif -------------------------------------------------------------------------------- /Noggog.CSharpExt/WorkEngine/IWorkQueue.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | #else 3 | using System.Threading.Channels; 4 | 5 | namespace Noggog.WorkEngine; 6 | 7 | public interface IWorkQueue 8 | { 9 | ChannelReader Reader { get; } 10 | } 11 | #endif -------------------------------------------------------------------------------- /Noggog.CSharpExt/WorkEngine/NoPreferenceWorkDropoff.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.WorkEngine; 2 | 3 | #if NETSTANDARD2_0 4 | #else 5 | 6 | /// 7 | /// Marker class that behaves like InlineWorkDropoff, but is meant 8 | /// to be replaced by the default work dropoff as prescribed by the implementation its given to 9 | /// 10 | public class NoPreferenceWorkDropoff : InlineWorkDropoff 11 | { 12 | } 13 | 14 | #endif -------------------------------------------------------------------------------- /Noggog.CSharpExt/XML/DocumentWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | 3 | namespace Noggog.Xml; 4 | 5 | public struct DocumentWrapper : IDisposable 6 | { 7 | XmlWriter writer; 8 | 9 | public DocumentWrapper(XmlWriter writer) 10 | { 11 | this.writer = writer; 12 | writer.WriteStartDocument(); 13 | } 14 | 15 | public void Dispose() 16 | { 17 | writer.WriteEndDocument(); 18 | } 19 | } -------------------------------------------------------------------------------- /Noggog.CSharpExt/XML/ElementWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | 3 | namespace Noggog.Xml; 4 | 5 | public struct ElementWrapper : IDisposable 6 | { 7 | XmlWriter writer; 8 | 9 | public ElementWrapper(XmlWriter writer, string elem, string? nameSpace = null) 10 | { 11 | this.writer = writer; 12 | this.writer.WriteStartElement(elem, ns: nameSpace); 13 | } 14 | 15 | public void Dispose() 16 | { 17 | writer.WriteEndElement(); 18 | } 19 | } -------------------------------------------------------------------------------- /Noggog.Nuget.Tests/CorruptErrorTests.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions.TestingHelpers; 2 | using System.Xml.Linq; 3 | using AutoFixture.Xunit2; 4 | using Noggog.Nuget.Errors; 5 | using Noggog.Testing.AutoFixture; 6 | using Shouldly; 7 | using Xunit; 8 | 9 | namespace Noggog.Nuget.Tests; 10 | 11 | public class CorruptErrorTests 12 | { 13 | [Theory, DefaultAutoData] 14 | public void CorruptFix( 15 | FilePath path, 16 | [Frozen]MockFileSystem fs, 17 | CorruptError sut) 18 | { 19 | fs.File.WriteAllText(path, "Whut"); 20 | sut.RunFix(path); 21 | var doc = XDocument.Load(fs.FileStream.New(path, FileMode.Open, FileAccess.Read)); 22 | doc.ShouldBeEquivalentTo(NotExistsError.TypicalFile()); 23 | } 24 | } -------------------------------------------------------------------------------- /Noggog.Nuget.Tests/Noggog.Nuget.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Noggog.Nuget/Errors/CorruptError.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | 3 | namespace Noggog.Nuget.Errors; 4 | 5 | public class CorruptError : NotExistsError 6 | { 7 | public override string ErrorText => $"Config was corrupt. Can fix by replacing the whole file."; 8 | 9 | public Exception Exception { get; } 10 | 11 | public CorruptError( 12 | IFileSystem fileSystem, 13 | Exception ex) 14 | : base(fileSystem) 15 | { 16 | Exception = ex; 17 | } 18 | } -------------------------------------------------------------------------------- /Noggog.Nuget/Errors/INugetErrorSolution.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Nuget.Errors; 2 | 3 | public interface INugetErrorSolution 4 | { 5 | string ErrorText { get; } 6 | void RunFix(FilePath path); 7 | } -------------------------------------------------------------------------------- /Noggog.Nuget/Errors/NotExistsError.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | using System.Xml.Linq; 3 | 4 | namespace Noggog.Nuget.Errors; 5 | 6 | public class NotExistsError : INugetErrorSolution 7 | { 8 | private readonly IFileSystem _fileSystem; 9 | public virtual string ErrorText => $"Config did not exist or was empty."; 10 | 11 | public static XDocument TypicalFile() 12 | { 13 | var elem = new XElement("configuration", 14 | new XElement("packageSources", 15 | new XElement("add", 16 | new XAttribute("key", "nuget.org"), 17 | new XAttribute("value", "https://api.nuget.org/v3/index.json"), 18 | new XAttribute("protocolVersion", "3")))); 19 | return new XDocument( 20 | new XDeclaration("1.0", "utf-8", null), 21 | elem); 22 | } 23 | 24 | public NotExistsError(IFileSystem fileSystem) 25 | { 26 | _fileSystem = fileSystem; 27 | } 28 | 29 | public void RunFix(FilePath path) 30 | { 31 | using var stream = _fileSystem.FileStream.New(path, FileMode.Create, FileAccess.Write); 32 | TypicalFile().Save(stream); 33 | } 34 | } -------------------------------------------------------------------------------- /Noggog.Nuget/Noggog.Nuget.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0;net9.0;netstandard2.0 5 | true 6 | Noggog.Nuget 7 | Noggog 8 | Noggog 9 | true 10 | true 11 | preview 12 | portable 13 | true 14 | true 15 | true 16 | true 17 | true 18 | snupkg 19 | Logic to help manage nuget operations 20 | 21 | 22 | 23 | 24 | all 25 | runtime; build; native; contentfiles; analyzers; buildtransitive 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Noggog.Nuget/Services/Singleton/NugetConfigPathProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Nuget.Services.Singleton; 2 | 3 | public interface INugetConfigPathProvider 4 | { 5 | FilePath Path { get; } 6 | } 7 | 8 | public class NugetConfigPathProvider : INugetConfigPathProvider 9 | { 10 | public FilePath Path { get; } 11 | 12 | public NugetConfigPathProvider() 13 | { 14 | Path = System.IO.Path.Combine( 15 | Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), 16 | "NuGet", 17 | "Nuget.Config"); 18 | } 19 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/Array2dBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture; 3 | using AutoFixture.Kernel; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public class Array2dBuilder : ISpecimenBuilder 8 | { 9 | public object Create(object request, ISpecimenContext context) 10 | { 11 | if (request is Type type 12 | && IsTargetType(type)) 13 | { 14 | return GetCreateMethod() 15 | .MakeGenericMethod(type.GenericTypeArguments[0]) 16 | .Invoke(this, new object[] {context, request})!; 17 | } 18 | 19 | return new NoSpecimen(); 20 | } 21 | 22 | public static bool IsTargetType(Type t) 23 | { 24 | return t.GenericTypeArguments.Length == 1 25 | && t.Name.Contains("Array2d"); 26 | } 27 | 28 | public static MethodInfo GetCreateMethod() 29 | { 30 | return typeof(Array2dBuilder) 31 | .GetMethod("Create", BindingFlags.Static | BindingFlags.Public)!; 32 | } 33 | 34 | public static IArray2d Create( 35 | ISpecimenContext context, 36 | object request) 37 | { 38 | return new Array2d(3, 3, () => context.Create()); 39 | } 40 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/CancellationBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture.Kernel; 3 | 4 | namespace Noggog.Testing.AutoFixture; 5 | 6 | public class CancellationBuilder : ISpecimenBuilder 7 | { 8 | public object Create(object request, ISpecimenContext context) 9 | { 10 | if (request is ParameterInfo p) 11 | { 12 | if (p.Name == null) return new NoSpecimen(); 13 | if (p.Name.ContainsInsensitive("cancelled")) 14 | { 15 | return new CancellationToken(canceled: true); 16 | } 17 | } 18 | else if (request is Type t) 19 | { 20 | if (t == typeof(CancellationToken)) 21 | { 22 | return new CancellationToken(canceled: false); 23 | } 24 | } 25 | 26 | return new NoSpecimen(); 27 | } 28 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/ContainerAutoData.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using AutoFixture.Xunit2; 3 | 4 | namespace Noggog.Testing.AutoFixture; 5 | 6 | public class ContainerAutoData : AutoDataAttribute 7 | { 8 | public ContainerAutoData( 9 | Type ContainerType, 10 | TargetFileSystem FileSystem = TargetFileSystem.Fake, 11 | bool OmitAutoProperties = false) 12 | : base(() => 13 | { 14 | var ret = new Fixture(); 15 | ret.Customize(new DefaultCustomization(FileSystem)); 16 | ret.OmitAutoProperties = OmitAutoProperties; 17 | ret.Customize(new ContainerAutoDataCustomization(ContainerType)); 18 | return ret; 19 | }) 20 | { 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/CurrentDirectoryPathProviderBuilder.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture.Kernel; 2 | using Noggog.IO; 3 | 4 | namespace Noggog.Testing.AutoFixture; 5 | 6 | public class CurrentDirectoryPathProviderBuilder : ISpecimenBuilder 7 | { 8 | public object Create(object request, ISpecimenContext context) 9 | { 10 | if (request is not Type t) return new NoSpecimen(); 11 | if (t == typeof(ICurrentDirectoryProvider)) 12 | { 13 | return new CurrentDirectoryInjection(PathBuilder.ExistingDirectory); 14 | } 15 | return new NoSpecimen(); 16 | } 17 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/DefaultAutoData.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using AutoFixture.AutoNSubstitute; 3 | using AutoFixture.Xunit2; 4 | using Xunit; 5 | 6 | namespace Noggog.Testing.AutoFixture; 7 | 8 | /// 9 | /// AutoFixture attribute with default customizations 10 | /// 11 | public class DefaultAutoData : AutoDataAttribute 12 | { 13 | public DefaultAutoData( 14 | bool ConfigureMembers = false, 15 | TargetFileSystem FileSystem = TargetFileSystem.Fake, 16 | bool GenerateDelegates = false, 17 | bool OmitAutoProperties = false) 18 | : base(() => 19 | { 20 | var ret = new Fixture(); 21 | ret.Customize(new AutoNSubstituteCustomization() 22 | { 23 | ConfigureMembers = ConfigureMembers, 24 | GenerateDelegates = GenerateDelegates 25 | }); 26 | ret.Customize(new DefaultCustomization(FileSystem)); 27 | ret.OmitAutoProperties = OmitAutoProperties; 28 | return ret; 29 | }) 30 | { 31 | } 32 | } 33 | 34 | public class DefaultInlineData : CompositeDataAttribute 35 | { 36 | public DefaultInlineData( 37 | bool ConfigureMembers = false, 38 | params object[] ExtraParameters) 39 | : base( 40 | new InlineDataAttribute(ExtraParameters), 41 | new DefaultAutoData(ConfigureMembers: ConfigureMembers)) 42 | { 43 | } 44 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/ErrorResponseBuilder.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using AutoFixture.Kernel; 3 | 4 | namespace Noggog.Testing.AutoFixture; 5 | 6 | public class ErrorResponseBuilder : ISpecimenBuilder 7 | { 8 | public object Create(object request, ISpecimenContext context) 9 | { 10 | if (request is Type t 11 | && t == typeof(ErrorResponse)) 12 | { 13 | return ErrorResponse.Create( 14 | successful: true, 15 | context.Create()); 16 | } 17 | return new NoSpecimen(); 18 | } 19 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/ErrorResponseParameterBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture; 3 | using AutoFixture.Kernel; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public class ErrorResponseParameterBuilder : ISpecimenBuilder 8 | { 9 | public object Create(object request, ISpecimenContext context) 10 | { 11 | if (request is not ParameterInfo p) return new NoSpecimen(); 12 | if (p.Name == null) return new NoSpecimen(); 13 | 14 | if (p.ParameterType == typeof(ErrorResponse)) 15 | { 16 | if (IsFail(p.Name)) 17 | { 18 | return ErrorResponse.Create( 19 | successful: false, 20 | context.Create(), 21 | ex: null); 22 | } 23 | 24 | return context.Create(); 25 | } 26 | 27 | return new NoSpecimen(); 28 | } 29 | 30 | private bool IsPassing(string name) 31 | { 32 | return name.ContainsInsensitive("success") 33 | || name.ContainsInsensitive("pass"); 34 | } 35 | 36 | private bool IsFail(string name) 37 | { 38 | return name.ContainsInsensitive("fail"); 39 | } 40 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/ExtendedListBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture; 3 | using AutoFixture.Kernel; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public class ExtendedListBuilder : ISpecimenBuilder 8 | { 9 | public object Create(object request, ISpecimenContext context) 10 | { 11 | if (request is SeededRequest seed) 12 | { 13 | request = seed.Request; 14 | } 15 | 16 | if (request is not Type t 17 | || !IsTargetType(t)) return new NoSpecimen(); 18 | 19 | return GetCreateMethod() 20 | .MakeGenericMethod(t.GenericTypeArguments[0]) 21 | .Invoke(this, new object[] {context, request})!; 22 | } 23 | 24 | public static bool IsTargetType(Type t) 25 | { 26 | if (t.GenericTypeArguments.Length != 1) return false; 27 | return t.Name switch 28 | { 29 | "ExtendedList`1" => true, 30 | "IExtendedList`1" => true, 31 | _ => false 32 | }; 33 | } 34 | 35 | public static MethodInfo GetCreateMethod() 36 | { 37 | return typeof(ExtendedListBuilder) 38 | .GetMethod("CreateList", BindingFlags.Static | BindingFlags.Public)!; 39 | } 40 | 41 | public static ExtendedList CreateList( 42 | ISpecimenContext context, 43 | object request) 44 | { 45 | return new ExtendedList(context.Create()); 46 | } 47 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/GetResponseBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture; 3 | using AutoFixture.Kernel; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public class GetResponseBuilder : ISpecimenBuilder 8 | { 9 | public object Create(object request, ISpecimenContext context) 10 | { 11 | if (request is Type t 12 | && IsGetResponseType(t)) 13 | { 14 | return GetCreateMethod() 15 | .MakeGenericMethod(t.GenericTypeArguments[0]) 16 | .Invoke(this, new object[] {context, true})!; 17 | } 18 | return new NoSpecimen(); 19 | } 20 | 21 | public static bool IsGetResponseType(Type t) 22 | { 23 | return t.GenericTypeArguments.Length == 1 24 | && t.Name.StartsWith("GetResponse"); 25 | } 26 | 27 | public static MethodInfo GetCreateMethod() 28 | { 29 | return typeof(GetResponseBuilder) 30 | .GetMethod("CreateGetResponse", BindingFlags.Static | BindingFlags.Public)!; 31 | } 32 | 33 | public static GetResponse CreateGetResponse( 34 | ISpecimenContext context, 35 | bool successful) 36 | { 37 | return GetResponse.Create( 38 | successful: successful, 39 | successful ? context.Create() : default(T), 40 | context.Create()); 41 | } 42 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/GetResponseParameterBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture.Kernel; 3 | 4 | namespace Noggog.Testing.AutoFixture; 5 | 6 | public class GetResponseParameterBuilder : ISpecimenBuilder 7 | { 8 | public object Create(object request, ISpecimenContext context) 9 | { 10 | if (request is not ParameterInfo p) return new NoSpecimen(); 11 | if (p.Name == null) return new NoSpecimen(); 12 | 13 | if (GetResponseBuilder.IsGetResponseType(p.ParameterType)) 14 | { 15 | if (IsFail(p.Name)) 16 | { 17 | return GetResponseBuilder.GetCreateMethod() 18 | .MakeGenericMethod(p.ParameterType.GenericTypeArguments[0]) 19 | .Invoke(this, new object[] {context, false})!; 20 | } 21 | 22 | return context.Resolve(new SeededRequest(p.ParameterType, p.ParameterType)); 23 | } 24 | 25 | return new NoSpecimen(); 26 | } 27 | 28 | private bool IsFail(string name) 29 | { 30 | return name.ContainsInsensitive("fail"); 31 | } 32 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/IFileSystemEnvironmentInstructions.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture.Kernel; 2 | 3 | namespace Noggog.Testing.AutoFixture; 4 | 5 | public interface IFileSystemEnvironmentInstructions 6 | { 7 | IEnumerable FilePaths(ISpecimenContext context); 8 | IEnumerable DirectoryPaths(ISpecimenContext context); 9 | } 10 | 11 | public class DefaultFileSystemEnvironmentInstructions : IFileSystemEnvironmentInstructions 12 | { 13 | public virtual IEnumerable FilePaths(ISpecimenContext context) => Enumerable.Empty(); 14 | 15 | public virtual IEnumerable DirectoryPaths(ISpecimenContext context) => Enumerable.Empty(); 16 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/LazyBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using AutoFixture; 3 | using AutoFixture.Kernel; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public class LazyBuilder : ISpecimenBuilder 8 | { 9 | public object Create(object request, ISpecimenContext context) 10 | { 11 | if (request is Type type 12 | && IsLazyType(type)) 13 | { 14 | return GetCreateMethod() 15 | .MakeGenericMethod(type.GenericTypeArguments[0]) 16 | .Invoke(this, new object[] {context, request})!; 17 | } 18 | 19 | return new NoSpecimen(); 20 | } 21 | 22 | public static bool IsLazyType(Type t) 23 | { 24 | return t.GenericTypeArguments.Length == 1 25 | && t.Name.StartsWith("Lazy"); 26 | } 27 | 28 | public static MethodInfo GetCreateMethod() 29 | { 30 | return typeof(LazyBuilder) 31 | .GetMethod("CreateLazy", BindingFlags.Static | BindingFlags.Public)!; 32 | } 33 | 34 | public static Lazy CreateLazy( 35 | ISpecimenContext context, 36 | object request) 37 | { 38 | return new Lazy(() => (T)context.Create()); 39 | } 40 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/MakeFileExist.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions.TestingHelpers; 2 | using AutoFixture; 3 | using AutoFixture.Kernel; 4 | 5 | namespace Noggog.Testing.AutoFixture; 6 | 7 | public interface IMakeFileExist 8 | { 9 | void MakeExist(FilePath path, ISpecimenContext context); 10 | } 11 | 12 | public class MakeFileExist : IMakeFileExist 13 | { 14 | public void MakeExist(FilePath path, ISpecimenContext context) 15 | { 16 | var fs = context.Create(); 17 | fs.Directory.CreateDirectory(path.Directory!); 18 | fs.File.Create(path); 19 | } 20 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/ObservableEmptyBehavior.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture.Kernel; 2 | 3 | namespace Noggog.Testing.AutoFixture; 4 | 5 | public class ObservableEmptyBehavior : ISpecimenBuilderTransformation 6 | { 7 | public ISpecimenBuilderNode Transform(ISpecimenBuilder builder) 8 | { 9 | return new Postprocessor( 10 | builder, 11 | new ObservableSpecimenCommand()); 12 | } 13 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/ProcessBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Reflection; 3 | using AutoFixture; 4 | using AutoFixture.Kernel; 5 | 6 | namespace Noggog.Testing.AutoFixture; 7 | 8 | public class ProcessBuilder : ISpecimenBuilder 9 | { 10 | public object Create(object request, ISpecimenContext context) 11 | { 12 | if (request is ParameterInfo p) 13 | { 14 | if (p.Name == null) return new NoSpecimen(); 15 | if (p.ParameterType == typeof(ProcessStartInfo)) 16 | { 17 | if (p.Name.ContainsInsensitive("existing")) 18 | { 19 | return new ProcessStartInfo( 20 | PathBuilder.ExistingFile, 21 | context.Create()) 22 | { 23 | WorkingDirectory = PathBuilder.ExistingDirectory 24 | }; 25 | } 26 | } 27 | } 28 | else if (request is Type t) 29 | { 30 | if (t == typeof(ProcessStartInfo)) 31 | { 32 | return new ProcessStartInfo( 33 | context.Create().Path, 34 | context.Create()) 35 | { 36 | WorkingDirectory = context.Create().Path 37 | }; 38 | } 39 | } 40 | 41 | return new NoSpecimen(); 42 | } 43 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/SpecimenBuilderFor.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture.Kernel; 2 | 3 | namespace Noggog.Testing.AutoFixture; 4 | 5 | public abstract class SpecimenBuilderFor : ISpecimenBuilder 6 | where T : notnull 7 | { 8 | public object Create(object request, ISpecimenContext context) 9 | { 10 | if (request is Type t && t == typeof(T)) 11 | { 12 | return Create(context); 13 | } 14 | 15 | return new NoSpecimen(); 16 | } 17 | 18 | public abstract T Create(ISpecimenContext context); 19 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/SplitEnumerableIntoSubtypes.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture; 2 | using AutoFixture.Kernel; 3 | 4 | namespace Noggog.Testing.AutoFixture; 5 | 6 | public interface ISplitEnumerableIntoSubtypes 7 | { 8 | object Split( 9 | ISpecimenContext context, 10 | Type paramType); 11 | } 12 | 13 | public class SplitEnumerableIntoSubtypes : ISplitEnumerableIntoSubtypes 14 | { 15 | public object Split( 16 | ISpecimenContext context, 17 | Type paramType) 18 | { 19 | if (paramType == typeof(IEnumerable)) 20 | { 21 | return context.Create>(); 22 | } 23 | 24 | if (typeof(TItem[]).IsAssignableFrom(paramType)) 25 | { 26 | return context.Create>().ToArray(); 27 | } 28 | 29 | if (typeof(IReadOnlyList).IsAssignableFrom(paramType) 30 | || typeof(IList).IsAssignableFrom(paramType)) 31 | { 32 | return context.Create>().ToList(); 33 | } 34 | 35 | if (typeof(IReadOnlySet).IsAssignableFrom(paramType) 36 | || typeof(ISet).IsAssignableFrom(paramType)) 37 | { 38 | return context.Create>().ToHashSet(); 39 | } 40 | 41 | return new NoSpecimen(); 42 | } 43 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/TargetFileSystem.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Testing.AutoFixture; 2 | 3 | public enum TargetFileSystem 4 | { 5 | Fake, 6 | Substitute, 7 | Real 8 | } -------------------------------------------------------------------------------- /Noggog.Testing/AutoFixture/Testing/SpecimenContextSubstituteExt.cs: -------------------------------------------------------------------------------- 1 | using AutoFixture.Kernel; 2 | using NSubstitute; 3 | using NSubstitute.Core; 4 | 5 | namespace Noggog.Testing.AutoFixture.Testing; 6 | 7 | public static class SpecimenContextSubstituteExt 8 | { 9 | public static void ShouldHaveCreated(this ISpecimenContext context) 10 | { 11 | context.Received(1).Resolve(Arg.Is(o => (Type) o.Request == typeof(T))); 12 | } 13 | 14 | public static ConfiguredCall MockToReturn(this ISpecimenContext context, T item) 15 | { 16 | return context.Resolve(Arg.Is(o => (Type)o.Request == typeof(T))) 17 | .Returns(item!); 18 | } 19 | 20 | public static ConfiguredCall MockToReturn(this ISpecimenContext context) 21 | where T : class 22 | { 23 | return context.Resolve(Arg.Is(o => (Type)o.Request == typeof(T))) 24 | .Returns(Substitute.For()); 25 | } 26 | 27 | public static void FillAllProperties(this ISpecimenContext context, T item) 28 | where T : class 29 | { 30 | foreach (var prop in item.GetType().GetProperties()) 31 | { 32 | var setter = prop.GetSetMethod(); 33 | if (setter == null) continue; 34 | setter.Invoke(item, new object[] { context.Resolve(prop.PropertyType) }); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /Noggog.Testing/Extensions/ContainerBuilderExt.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Autofac.Builder; 3 | using NSubstitute; 4 | 5 | namespace Noggog; 6 | 7 | public static class RegistrationBuilderExt 8 | { 9 | public static IRegistrationBuilder RegisterMock(this ContainerBuilder builder) 10 | where T : class 11 | { 12 | return builder.RegisterInstance(Substitute.For()).As(); 13 | } 14 | } -------------------------------------------------------------------------------- /Noggog.Testing/Extensions/NSubstituteExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Linq; 2 | using NSubstitute; 3 | using NSubstitute.Core; 4 | 5 | namespace Noggog.NSubstitute; 6 | 7 | public static class NSubstituteExtensions 8 | { 9 | public static ConfiguredCall ReturnEmpty(this IObservable obs) 10 | { 11 | return obs.Returns(Observable.Empty()); 12 | } 13 | 14 | public static T ArgIsSame(this T item) 15 | where T : class 16 | { 17 | return Arg.Is(x => ReferenceEquals(x, item)); 18 | } 19 | 20 | public static ConfiguredCall ReturnsSerially( 21 | this T value, 22 | params T[] returnThese) 23 | { 24 | return value.Returns(returnThese[0], returnThese.Skip(1).ToArray()); 25 | } 26 | 27 | public static ConfiguredCall ReturnsSeriallyForAnyArgs( 28 | this T value, 29 | params T[] returnThese) 30 | { 31 | return value.ReturnsForAnyArgs(returnThese[0], returnThese.Skip(1).ToArray()); 32 | } 33 | } -------------------------------------------------------------------------------- /Noggog.Testing/Extensions/TestableObservableExt.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive; 2 | using Microsoft.Reactive.Testing; 3 | using Shouldly; 4 | 5 | namespace Noggog; 6 | 7 | public static class TestableObservableExt 8 | { 9 | public static void ShouldHaveNoErrors(this ITestableObservable obs) 10 | { 11 | obs.Messages.Where(x => x.Value.Kind == NotificationKind.OnError) 12 | .ShouldBeEmpty(); 13 | } 14 | 15 | public static void ShouldNotBeCompleted(this ITestableObservable obs) 16 | { 17 | obs.Messages.Where(x => x.Value.Kind == NotificationKind.OnCompleted) 18 | .ShouldBeEmpty(); 19 | } 20 | } -------------------------------------------------------------------------------- /Noggog.Testing/Extensions/TestableObserverExt.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive; 2 | using Microsoft.Reactive.Testing; 3 | using Shouldly; 4 | 5 | namespace Noggog; 6 | 7 | public static class TestableObserverExt 8 | { 9 | public static void ShouldHaveNoErrors(this ITestableObserver obs) 10 | { 11 | obs.Messages.Where(x => x.Value.Kind == NotificationKind.OnError) 12 | .ShouldBeEmpty(); 13 | } 14 | 15 | public static void ShouldNotBeCompleted(this ITestableObserver obs) 16 | { 17 | obs.Messages.Where(x => x.Value.Kind == NotificationKind.OnCompleted) 18 | .ShouldBeEmpty(); 19 | } 20 | } -------------------------------------------------------------------------------- /Noggog.Testing/FileSystem/NoggogMockFileSystem.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | using System.IO.Abstractions.TestingHelpers; 3 | 4 | namespace Noggog.Testing.FileSystem; 5 | 6 | public class NoggogMockFileSystem : MockFileSystem 7 | { 8 | private IFileSystemWatcherFactory? _fileSystemWatcher; 9 | 10 | public override IFileSystemWatcherFactory FileSystemWatcher 11 | { 12 | get 13 | { 14 | if (_fileSystemWatcher == null) return base.FileSystemWatcher; 15 | return _fileSystemWatcher; 16 | } 17 | } 18 | 19 | public NoggogMockFileSystem(IFileSystemWatcherFactory? fileSystemWatcher = null) 20 | { 21 | _fileSystemWatcher = fileSystemWatcher; 22 | } 23 | 24 | public NoggogMockFileSystem(IDictionary files, string currentDirectory = "", IFileSystemWatcherFactory? fileSystemWatcher = null) 25 | : base(files, currentDirectory) 26 | { 27 | _fileSystemWatcher = fileSystemWatcher; 28 | } 29 | 30 | public void SetFileSystemWatcherFactory(IFileSystemWatcherFactory factory) 31 | { 32 | _fileSystemWatcher = factory; 33 | } 34 | } -------------------------------------------------------------------------------- /Noggog.Testing/FileSystem/TestingFileSystem.cs: -------------------------------------------------------------------------------- 1 | using System.IO.Abstractions; 2 | 3 | namespace Noggog.Testing.FileSystem; 4 | 5 | public static class TestingFileSystem 6 | { 7 | public static MockFileSystemWatcherFactory GetFileWatcher(IFileSystem fileSystem, out MockFileSystemWatcher watcher) 8 | { 9 | watcher = new MockFileSystemWatcher(fileSystem); 10 | return new MockFileSystemWatcherFactory(fileSystem, watcher); 11 | } 12 | } -------------------------------------------------------------------------------- /Noggog.Testing/IO/DisposeTesterStream.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Testing.IO; 2 | 3 | public class DisposeTesterStream : Stream 4 | { 5 | public bool Disposed { get; set; } 6 | 7 | public override void Flush() 8 | { 9 | } 10 | 11 | public override int Read(byte[] buffer, int offset, int count) 12 | { 13 | return 0; 14 | } 15 | 16 | public override long Seek(long offset, SeekOrigin origin) 17 | { 18 | return 0; 19 | } 20 | 21 | public override void SetLength(long value) 22 | { 23 | } 24 | 25 | public override void Write(byte[] buffer, int offset, int count) 26 | { 27 | } 28 | 29 | public override bool CanRead { get; } 30 | public override bool CanSeek { get; } 31 | public override bool CanWrite { get; } 32 | public override long Length { get; } 33 | public override long Position { get; set; } 34 | 35 | protected override void Dispose(bool disposing) 36 | { 37 | base.Dispose(disposing); 38 | Disposed = true; 39 | } 40 | } -------------------------------------------------------------------------------- /Noggog.Testing/IO/DisposeTesterWrapStream.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Testing.IO; 2 | 3 | public class DisposeTesterWrapStream : Stream 4 | { 5 | public bool Disposed { get; set; } 6 | public Stream Stream { get; } 7 | 8 | public DisposeTesterWrapStream(Stream stream) 9 | { 10 | Stream = stream; 11 | } 12 | 13 | public override void Flush() 14 | { 15 | Stream.Flush(); 16 | } 17 | 18 | public override int Read(byte[] buffer, int offset, int count) 19 | { 20 | return Stream.Read(buffer, offset, count); 21 | } 22 | 23 | public override long Seek(long offset, SeekOrigin origin) 24 | { 25 | return Stream.Seek(offset, origin); 26 | } 27 | 28 | public override void SetLength(long value) 29 | { 30 | Stream.SetLength(value); 31 | } 32 | 33 | public override void Write(byte[] buffer, int offset, int count) 34 | { 35 | Stream.Write(buffer, offset, count); 36 | } 37 | 38 | public override bool CanRead => Stream.CanRead; 39 | 40 | public override bool CanSeek => Stream.CanSeek; 41 | 42 | public override bool CanWrite => Stream.CanWrite; 43 | 44 | public override long Length => Stream.Length; 45 | 46 | public override long Position 47 | { 48 | get => Stream.Position; 49 | set => Stream.Position = value; 50 | } 51 | 52 | protected override void Dispose(bool disposing) 53 | { 54 | base.Dispose(disposing); 55 | Disposed = true; 56 | } 57 | } -------------------------------------------------------------------------------- /Noggog.Testing/IO/LengthLiarStream.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Testing.IO; 2 | 3 | public class LengthLiarStream : Stream 4 | { 5 | private readonly Stream _wrap; 6 | private readonly int _lengthOverride; 7 | 8 | public LengthLiarStream(Stream wrap, int lengthOverride) 9 | { 10 | _wrap = wrap; 11 | _lengthOverride = lengthOverride; 12 | } 13 | 14 | public override void Flush() 15 | { 16 | _wrap.Flush(); 17 | } 18 | 19 | public override int Read(byte[] buffer, int offset, int count) 20 | { 21 | return _wrap.Read(buffer, offset, count); 22 | } 23 | 24 | public override long Seek(long offset, SeekOrigin origin) 25 | { 26 | return _wrap.Seek(offset, origin); 27 | } 28 | 29 | public override void SetLength(long value) 30 | { 31 | _wrap.SetLength(value); 32 | } 33 | 34 | public override void Write(byte[] buffer, int offset, int count) 35 | { 36 | _wrap.Write(buffer, offset, count); 37 | } 38 | 39 | public override bool CanRead => _wrap.CanRead; 40 | 41 | public override bool CanSeek => _wrap.CanSeek; 42 | 43 | public override bool CanWrite => _wrap.CanWrite; 44 | 45 | public override long Length => _lengthOverride; 46 | 47 | public override long Position 48 | { 49 | get => _wrap.Position; 50 | set => _wrap.Position = value; 51 | } 52 | } -------------------------------------------------------------------------------- /Noggog.Testing/IO/PathingUtil.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace Noggog.Testing.IO; 4 | 5 | public class PathingUtil 6 | { 7 | public static string DrivePrefix 8 | { 9 | get 10 | { 11 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 12 | { 13 | return "C:\\"; 14 | } 15 | else 16 | { 17 | return "/"; 18 | } 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Noggog.Testing/Noggog.Testing.csproj.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | CSharp100 -------------------------------------------------------------------------------- /Noggog.Testing/TestClassData/ErrorResponseSuccessFailData.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace Noggog.Testing.TestClassData; 4 | 5 | public class ErrorResponseSuccessFailData : IEnumerable 6 | { 7 | public static IEnumerable Data { get; } = new[] 8 | { 9 | new object[] {ErrorResponse.Success}, 10 | new object[] {ErrorResponse.Failure}, 11 | }; 12 | 13 | public IEnumerator GetEnumerator() => Data.GetEnumerator(); 14 | 15 | IEnumerator IEnumerable.GetEnumerator() => Data.GetEnumerator(); 16 | } -------------------------------------------------------------------------------- /Noggog.Testing/TestClassData/MemberData.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.Testing.TestClassData; 2 | 3 | public static class MemberData 4 | { 5 | public static IEnumerable TestPerItem(params object[] objs) 6 | { 7 | foreach (var obj in objs) 8 | { 9 | yield return new[] {obj}; 10 | } 11 | } 12 | 13 | public static IEnumerable AlternatingBools(int size) 14 | { 15 | return Enumerable.Range(0, (int)Math.Pow(2, size)) 16 | .Select(i => 17 | Enumerable.Range(0, size) 18 | .Select(b => ((i & (1 << b)) > 0)) 19 | .Select(x => (object)x) 20 | .ToArray() 21 | ).ToArray(); 22 | } 23 | } -------------------------------------------------------------------------------- /Noggog.Testing/TestingPermissions.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("CSharpExt.UnitTests")] -------------------------------------------------------------------------------- /Noggog.WPF/Constants/Brushes.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.WPF.Brushes; 2 | 3 | public static class Constants 4 | { 5 | public const string PassiveForeground = "Noggog.Brushes.Passive.Foreground"; 6 | public const string YellowForeground = "Noggog.Brushes.Yellow.Foreground"; 7 | public const string YellowDark = "Noggog.Brushes.Yellow.Dark"; 8 | public const string GreenForeground = "Noggog.Brushes.Green.Foreground"; 9 | public const string GreenBackground = "Noggog.Brushes.Green.Background"; 10 | public const string RedForeground = "Noggog.Brushes.Red.Foreground"; 11 | public const string RedBackground = "Noggog.Brushes.Green.Background"; 12 | public const string WarningForeground = "Noggog.Brushes.Warning.Foreground"; 13 | public const string WarningDark = "Noggog.Brushes.Warning.Dark"; 14 | public const string SuccessForeground = "Noggog.Brushes.Success.Foreground"; 15 | public const string ErrorForeground = "Noggog.Brushes.Error.Foreground"; 16 | public const string ErrorLight = "Noggog.Brushes.Error.Light"; 17 | public const string ErrorPressed = "Noggog.Brushes.Error.Pressed"; 18 | public const string ErrorBackground = "Noggog.Brushes.Error.Background"; 19 | public const string SelectedNeon = "Noggog.Brushes.Selected.Neon"; 20 | public const string SelectedForeground = "Noggog.Brushes.Selected.Foreground"; 21 | public const string SelectedBackground = "Noggog.Brushes.Selected.Background"; 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/Constants/Colors.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.WPF.Colors; 2 | 3 | public static class Constants 4 | { 5 | public const string PassiveForeground = "Noggog.Colors.Passive.Foreground"; 6 | public const string YellowForeground = "Noggog.Colors.Yellow.Foreground"; 7 | public const string YellowDark = "Noggog.Colors.Yellow.Dark"; 8 | public const string GreenForeground = "Noggog.Colors.Green.Foreground"; 9 | public const string GreenBackground = "Noggog.Colors.Green.Background"; 10 | public const string RedForeground = "Noggog.Colors.Red.Foreground"; 11 | public const string RedBackground = "Noggog.Colors.Green.Background"; 12 | public const string WarningForeground = "Noggog.Colors.Warning.Foreground"; 13 | public const string WarningDark = "Noggog.Colors.Warning.Dark"; 14 | public const string SuccessForeground = "Noggog.Colors.Success.Foreground"; 15 | public const string ErrorForeground = "Noggog.Colors.Error.Foreground"; 16 | public const string ErrorLight = "Noggog.Colors.Error.Light"; 17 | public const string ErrorPressed = "Noggog.Colors.Error.Pressed"; 18 | public const string ErrorBackground = "Noggog.Colors.Error.Background"; 19 | public const string SelectedNeon = "Noggog.Colors.Selected.Neon"; 20 | public const string SelectedForeground = "Noggog.Colors.Selected.Foreground"; 21 | public const string SelectedBackground = "Noggog.Colors.Selected.Background"; 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/Controls/ErroredTextBox.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public class ErroredTextBox : TextBox 7 | { 8 | public bool InError 9 | { 10 | get => (bool)GetValue(InErrorProperty); 11 | set => SetValue(InErrorProperty, value); 12 | } 13 | public static readonly DependencyProperty InErrorProperty = DependencyProperty.Register(nameof(InError), typeof(bool), typeof(ErroredTextBox), 14 | new FrameworkPropertyMetadata(default(bool))); 15 | 16 | public string ErrorText 17 | { 18 | get => (string)GetValue(ErrorTextProperty); 19 | set => SetValue(ErrorTextProperty, value); 20 | } 21 | public static readonly DependencyProperty ErrorTextProperty = DependencyProperty.Register(nameof(ErrorText), typeof(string), typeof(ErroredTextBox), 22 | new FrameworkPropertyMetadata(default(string))); 23 | } -------------------------------------------------------------------------------- /Noggog.WPF/Controls/Helpers/ControlsHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls.Primitives; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public class ControlsHelper 7 | { 8 | public static readonly DependencyProperty InErrorProperty = DependencyProperty.RegisterAttached("InError", typeof(bool), typeof(ControlsHelper), new UIPropertyMetadata(false)); 9 | 10 | [AttachedPropertyBrowsableForType(typeof(TextBoxBase))] 11 | public static bool GetInError(DependencyObject obj) 12 | { 13 | return (bool)obj.GetValue(InErrorProperty); 14 | } 15 | 16 | [AttachedPropertyBrowsableForType(typeof(TextBoxBase))] 17 | public static void SetInError(DependencyObject obj, bool value) 18 | { 19 | obj.SetValue(InErrorProperty, value); 20 | } 21 | 22 | public static readonly DependencyProperty ErrorTooltipProperty = DependencyProperty.RegisterAttached("ErrorTooltip", typeof(string), typeof(ControlsHelper), new UIPropertyMetadata(string.Empty)); 23 | 24 | [AttachedPropertyBrowsableForType(typeof(TextBoxBase))] 25 | public static string GetErrorTooltip(DependencyObject obj) 26 | { 27 | return (string)obj.GetValue(ErrorTooltipProperty); 28 | } 29 | 30 | [AttachedPropertyBrowsableForType(typeof(TextBoxBase))] 31 | public static void SetErrorTooltip(DependencyObject obj, string value) 32 | { 33 | obj.SetValue(ErrorTooltipProperty, value); 34 | } 35 | } -------------------------------------------------------------------------------- /Noggog.WPF/Controls/PathPicker.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace Noggog.WPF; 5 | 6 | /// 7 | /// Interaction logic for PathPicker.xaml 8 | /// 9 | public partial class PathPicker : UserControl 10 | { 11 | // This exists, as utilizing the datacontext directly seemed to bug out the exit animations 12 | // "Bouncing" off this property seems to fix it, though. Could perhaps be done other ways. 13 | public PathPickerVM PickerVM 14 | { 15 | get => (PathPickerVM)GetValue(PickerVMProperty); 16 | set => SetValue(PickerVMProperty, value); 17 | } 18 | public static readonly DependencyProperty PickerVMProperty = DependencyProperty.Register(nameof(PickerVM), typeof(PathPickerVM), typeof(PathPicker), 19 | new FrameworkPropertyMetadata(default(PathPickerVM))); 20 | 21 | public PathPicker() 22 | { 23 | InitializeComponent(); 24 | } 25 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/Converters.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Noggog.WPF/Converters/DirectoryPathConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace Noggog.WPF; 5 | 6 | [ValueConversion(typeof(DirectoryPath), typeof(string))] 7 | public class DirectoryPathConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | if (targetType != typeof(string)) 12 | throw new InvalidOperationException($"The target must be of type string"); 13 | return ((DirectoryPath)value).Path; 14 | } 15 | 16 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | if (targetType != typeof(DirectoryPath)) 19 | throw new InvalidOperationException($"The target must be of type {nameof(DirectoryPath)}"); 20 | return new DirectoryPath((string)value); 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/EnumDescriptionConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public class EnumDescriptionConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 9 | { 10 | if (targetType != typeof(string)) 11 | throw new InvalidOperationException($"The target must be of type string"); 12 | return EnumExt.ToDescriptionString((Enum)value); 13 | } 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | throw new NotImplementedException(); 18 | } 19 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/EnumToIntConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public class EnumToIntConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 9 | { 10 | return ((IConvertible)value).ToInt32(null); 11 | } 12 | 13 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/FilePathConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace Noggog.WPF; 5 | 6 | [ValueConversion(typeof(FilePath), typeof(string))] 7 | public class FilePathConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | if (targetType != typeof(string)) 12 | throw new InvalidOperationException($"The target must be of type string"); 13 | return ((FilePath)value).Path; 14 | } 15 | 16 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | if (targetType != typeof(FilePath)) 19 | throw new InvalidOperationException($"The target must be of type {nameof(FilePath)}"); 20 | return new FilePath((string)value); 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/InverseBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace Noggog.WPF; 5 | 6 | [ValueConversion(typeof(bool), typeof(bool))] 7 | public class InverseBooleanConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | if (targetType != typeof(bool)) 12 | throw new InvalidOperationException($"The target must be of type bool"); 13 | return !((bool)value); 14 | } 15 | 16 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | if (targetType != typeof(bool)) 19 | throw new InvalidOperationException($"The target must be of type bool"); 20 | return !((bool)value); 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/IsNotEmptyVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows; 3 | using System.Windows.Data; 4 | 5 | namespace Noggog.WPF; 6 | 7 | [ValueConversion(typeof(Visibility), typeof(int))] 8 | public class IsNotEmptyVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (targetType != typeof(Visibility)) 13 | throw new InvalidOperationException($"The target must be of type {nameof(Visibility)}"); 14 | int count = (int)value; 15 | return count > 0 ? Visibility.Visible : Visibility.Collapsed; 16 | } 17 | 18 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/IsNotNullVisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows; 3 | using System.Windows.Data; 4 | 5 | namespace Noggog.WPF; 6 | 7 | [ValueConversion(typeof(Visibility), typeof(object))] 8 | public class IsNotNullVisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (targetType != typeof(Visibility)) 13 | throw new InvalidOperationException($"The target must be of type {nameof(Visibility)}"); 14 | bool compareTo = true; 15 | if (parameter is bool p) 16 | { 17 | compareTo = p; 18 | } 19 | else if (parameter is string str && str.Equals("FALSE", StringComparison.OrdinalIgnoreCase)) 20 | { 21 | compareTo = false; 22 | } 23 | return value != null ? Visibility.Visible : Visibility.Collapsed; 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/StringIsWhitespaceBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public class StringIsWhitespaceBooleanConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 9 | { 10 | return string.IsNullOrWhiteSpace(value as string); 11 | } 12 | 13 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | throw new NotImplementedException(); 16 | } 17 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/VisibilityConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows; 3 | using System.Windows.Data; 4 | 5 | namespace Noggog.WPF; 6 | 7 | [ValueConversion(typeof(Visibility), typeof(bool))] 8 | public class VisibilityConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (targetType != typeof(Visibility)) 13 | throw new InvalidOperationException($"The target must be of type {nameof(Visibility)}"); 14 | bool compareTo = true; 15 | if (parameter is bool p) 16 | { 17 | compareTo = p; 18 | } 19 | else if (parameter is string str && str.Equals("FALSE", StringComparison.OrdinalIgnoreCase)) 20 | { 21 | compareTo = false; 22 | } 23 | return ((bool)value) == compareTo ? Visibility.Visible : Visibility.Collapsed; 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } -------------------------------------------------------------------------------- /Noggog.WPF/Converters/VisibilityHiddenConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows; 3 | using System.Windows.Data; 4 | 5 | namespace Noggog.WPF; 6 | 7 | [ValueConversion(typeof(Visibility), typeof(bool))] 8 | public class VisibilityHiddenConverter : IValueConverter 9 | { 10 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 11 | { 12 | if (targetType != typeof(Visibility)) 13 | throw new InvalidOperationException($"The target must be of type {nameof(Visibility)}"); 14 | bool compareTo = true; 15 | if (parameter is bool p) 16 | { 17 | compareTo = p; 18 | } 19 | else if (parameter is string str && str.Equals("FALSE", StringComparison.OrdinalIgnoreCase)) 20 | { 21 | compareTo = false; 22 | } 23 | return ((bool)value) == compareTo ? Visibility.Visible : Visibility.Hidden; 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } -------------------------------------------------------------------------------- /Noggog.WPF/Drag/DragEventParams.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public static partial class Drag 7 | { 8 | public record DragEventParams(DragEventArgs RawArgs) 9 | { 10 | public TViewModel? Vm { get; set; } 11 | public ListBox? SourceListBox { get; set; } 12 | public int SourceListIndex { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /Noggog.WPF/Enums/StatusIndicatorState.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.WPF; 2 | 3 | public enum StatusIndicatorState 4 | { 5 | Passive, 6 | Success, 7 | Failure 8 | } -------------------------------------------------------------------------------- /Noggog.WPF/Everything.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Noggog.WPF/Extensions/CommandExt.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using System.Reactive; 3 | using System.Reactive.Linq; 4 | using System.Windows.Input; 5 | 6 | namespace Noggog.WPF; 7 | 8 | public static class CommandExt 9 | { 10 | public static IObservable StartingExecution(this IReactiveCommand cmd) 11 | { 12 | return cmd.IsExecuting 13 | .DistinctUntilChanged() 14 | .Where(x => x) 15 | .Unit(); 16 | } 17 | 18 | public static IObservable EndingExecution(this IReactiveCommand cmd) 19 | { 20 | return cmd.IsExecuting 21 | .DistinctUntilChanged() 22 | .Pairwise() 23 | .Where(x => x.Previous && !x.Current) 24 | .Unit(); 25 | } 26 | 27 | public static ReactiveCommand CreateCombinedAny(params ReactiveCommand[] commands) 28 | { 29 | 30 | return ReactiveCommand.CreateFromTask( 31 | execute: () => 32 | { 33 | return Task.WhenAll(commands.Select(async c => 34 | { 35 | if (((ICommand)c).CanExecute(Unit.Default)) 36 | { 37 | await c.Execute(); 38 | } 39 | })); 40 | }, 41 | canExecute: Noggog.ObservableExt.Any(commands.Select(x => x.CanExecute).ToArray())); 42 | } 43 | } -------------------------------------------------------------------------------- /Noggog.WPF/Extensions/ListBoxExt.cs: -------------------------------------------------------------------------------- 1 | namespace Noggog.WPF; 2 | 3 | public static class ListBoxExt 4 | { 5 | } -------------------------------------------------------------------------------- /Noggog.WPF/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Noggog.WPF/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 12 | 13 | 14 | 15 | 16 | A comma-separated list of error codes that can be safely ignored in assembly verification. 17 | 18 | 19 | 20 | 21 | 'false' to turn off automatic generation of the XML Schema file. 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Noggog.WPF/ImageUtility.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | using System.IO; 3 | using System.Windows.Media.Imaging; 4 | 5 | namespace Noggog.WPF; 6 | 7 | public static class ImageUtility 8 | { 9 | public static BitmapImage BitmapImageFromResource(string assemblyName, string resourceName) => BitmapImageFromStream(System.Windows.Application.GetResourceStream(new Uri($"pack://application:,,,/{assemblyName};component/{resourceName}")).Stream); 10 | 11 | public static BitmapImage BitmapImageFromStream(Stream stream) 12 | { 13 | var img = new BitmapImage(); 14 | img.BeginInit(); 15 | img.CacheOption = BitmapCacheOption.OnLoad; 16 | img.StreamSource = stream; 17 | img.EndInit(); 18 | img.Freeze(); 19 | return img; 20 | } 21 | 22 | public static bool TryGetBitmapImageFromFile(string path, [MaybeNullWhen(false)] out BitmapImage bitmapImage) 23 | { 24 | try 25 | { 26 | if (!File.Exists(path)) 27 | { 28 | bitmapImage = default; 29 | return false; 30 | } 31 | bitmapImage = new BitmapImage(new Uri((string)path, UriKind.RelativeOrAbsolute)); 32 | return true; 33 | } 34 | catch (Exception) 35 | { 36 | bitmapImage = default; 37 | return false; 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Noggog.WPF/NoggogControl.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Controls; 2 | 3 | namespace Noggog.WPF; 4 | 5 | public class NoggogControl : Control 6 | { 7 | protected readonly IDisposableBucket _unloadDisposable = new DisposableBucket(); 8 | protected readonly IDisposableBucket _templateDisposable = new DisposableBucket(); 9 | 10 | public NoggogControl() 11 | { 12 | Loaded += (_, _) => OnLoaded(); 13 | Loaded += (_, _) => 14 | { 15 | if (Template != null) 16 | { 17 | OnApplyTemplate(); 18 | } 19 | }; 20 | Unloaded += (_, _) => 21 | { 22 | _templateDisposable.Clear(); 23 | _unloadDisposable.Clear(); 24 | }; 25 | } 26 | 27 | public override void OnApplyTemplate() 28 | { 29 | base.OnApplyTemplate(); 30 | _templateDisposable.Clear(); 31 | } 32 | 33 | protected virtual void OnLoaded() 34 | { 35 | } 36 | } -------------------------------------------------------------------------------- /Noggog.WPF/NoggogUserControl.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | 3 | namespace Noggog.WPF; 4 | 5 | public class NoggogUserControl : ReactiveUserControl 6 | where TViewModel : class 7 | { 8 | public NoggogUserControl() 9 | { 10 | DataContextChanged += (o, e) => 11 | { 12 | if (e.NewValue is TViewModel vm) 13 | { 14 | ViewModel = vm; 15 | } 16 | else 17 | { 18 | ViewModel = null!; 19 | } 20 | }; 21 | } 22 | } -------------------------------------------------------------------------------- /Noggog.WPF/SchedulerProvider.cs: -------------------------------------------------------------------------------- 1 | using System.Reactive.Concurrency; 2 | using Noggog.Reactive; 3 | using ReactiveUI; 4 | 5 | namespace Noggog.WPF; 6 | 7 | public class SchedulerProvider : ISchedulerProvider 8 | { 9 | public IScheduler MainThread => RxApp.MainThreadScheduler; 10 | public IScheduler TaskPool => RxApp.TaskpoolScheduler; 11 | } -------------------------------------------------------------------------------- /Noggog.WPF/UserControlRx.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using System.ComponentModel; 3 | using System.Reactive.Disposables; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | 7 | namespace Noggog.WPF; 8 | 9 | public class UserControlRx : UserControl, IDisposable, IReactiveObject 10 | { 11 | public event PropertyChangedEventHandler? PropertyChanged; 12 | public event PropertyChangingEventHandler? PropertyChanging; 13 | 14 | public void RaisePropertyChanging(PropertyChangingEventArgs args) 15 | { 16 | PropertyChanging?.Invoke(this, args); 17 | } 18 | 19 | public void RaisePropertyChanged(PropertyChangedEventArgs args) 20 | { 21 | PropertyChanged?.Invoke(this, args); 22 | } 23 | 24 | private readonly Lazy _CompositeDisposable = new Lazy(); 25 | public CompositeDisposable CompositeDisposable => _CompositeDisposable.Value; 26 | 27 | public virtual void Dispose() 28 | { 29 | if (_CompositeDisposable.IsValueCreated) 30 | { 31 | _CompositeDisposable.Value.Dispose(); 32 | } 33 | } 34 | 35 | protected static void WireNotifyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 36 | { 37 | if (!(d is UserControlRx control)) return; 38 | if (Equals(e.OldValue, e.NewValue)) return; 39 | control.RaisePropertyChanged(e.Property.Name); 40 | } 41 | } -------------------------------------------------------------------------------- /Noggog.WPF/VMs/CommandVM.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI; 2 | using System.Reactive; 3 | 4 | namespace Noggog.WPF; 5 | 6 | public class CommandVM : ViewModel 7 | { 8 | private readonly ObservableAsPropertyHelper _CanExecute; 9 | public bool CanExecute => _CanExecute.Value; 10 | 11 | public ReactiveCommand Command { get; private set; } 12 | 13 | private CommandVM(ReactiveCommand cmd) 14 | { 15 | Command = cmd; 16 | _CanExecute = cmd.CanExecute 17 | .ToProperty(this, nameof(CanExecute), initialValue: false); 18 | } 19 | 20 | public static CommandVM Factory(ReactiveCommand cmd) 21 | { 22 | return new CommandVM(cmd); 23 | } 24 | } -------------------------------------------------------------------------------- /Noggog.WPF/VMs/SelectedVm.cs: -------------------------------------------------------------------------------- 1 | using ReactiveUI.Fody.Helpers; 2 | 3 | namespace Noggog.WPF; 4 | 5 | public class SelectedVm : ViewModel, ISelectedItem 6 | { 7 | [Reactive] public bool IsSelected { get; set; } 8 | [Reactive] public T Item { get; set; } 9 | 10 | public SelectedVm(T initialItem) 11 | { 12 | Item = initialItem; 13 | } 14 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Build](https://github.com/Noggog/CSharpExt/workflows/Build/badge.svg?branch=master) [![NuGet Stats](https://img.shields.io/nuget/v/Noggog.CSharpExt.svg)](https://www.nuget.org/packages/Noggog.CSharpExt) 2 | 3 | # CSharpExt 4 | Generic reusable classes and extension methods that apply to no specific project and flavored to taste 5 | -------------------------------------------------------------------------------- /Snippets/RxOAPH.snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | ReactiveUI - ObservableAsPropertyHelper 6 | oaph 7 | Code snippet for a ReactiveUI ObservableAsPropertyHelper 8 | 9 | Expansion 10 | 11 |
12 | 13 | 14 | 15 | type 16 | Property type 17 | int 18 | 19 | 20 | property 21 | Property name 22 | MyProperty 23 | 24 | 25 | _$property$; 26 | public $type$ $property$ => _$property$.Value;$end$]]> 27 | 28 | 29 |
30 |
31 | -------------------------------------------------------------------------------- /Snippets/guiprop.snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | Notify property changed property 6 | guiprop 7 | Code snippet for a ReactiveUI ObservableAsPropertyHelper 8 | 9 | Expansion 10 | 11 |
12 | 13 | 14 | 15 | type 16 | Property type 17 | int 18 | 19 | 20 | property 21 | Property name 22 | MyProperty 23 | 24 | 25 | _$property$; set => this.RaiseAndSetIfChanged(ref _$property$, value); }$end$]]> 27 | 28 | 29 |
30 |
31 | -------------------------------------------------------------------------------- /Snippets/guipropdp.snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | Dependency property 6 | guipropdp 7 | Code snippet for a dependency property 8 | 9 | Expansion 10 | 11 |
12 | 13 | 14 | 15 | type 16 | Property type 17 | int 18 | 19 | 20 | property 21 | Property name 22 | MyProperty 23 | 24 | 25 | class 26 | Class name 27 | ClassName 28 | 29 | 30 | ($type$)GetValue($property$Property); 33 | set => SetValue($property$Property, value); 34 | } 35 | public static readonly DependencyProperty $property$Property = DependencyProperty.Register(nameof($property$), typeof($type$), typeof($class$), 36 | new FrameworkPropertyMetadata(default($type$), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));$end$]]> 37 | 38 | 39 |
40 |
41 | -------------------------------------------------------------------------------- /Snippets/guipropdprx.snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | Dependency property 6 | guipropdp 7 | Code snippet for a dependency property 8 | 9 | Expansion 10 | 11 |
12 | 13 | 14 | 15 | type 16 | Property type 17 | int 18 | 19 | 20 | property 21 | Property name 22 | MyProperty 23 | 24 | 25 | class 26 | Class name 27 | ClassName 28 | 29 | 30 | ($type$)GetValue($property$Property); 33 | set => SetValue($property$Property, value); 34 | } 35 | public static readonly DependencyProperty $property$Property = DependencyProperty.Register(nameof($property$), typeof($type$), typeof($class$), 36 | new FrameworkPropertyMetadata(default($type$), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, WireNotifyPropertyChanged));$end$]]> 37 | 38 | 39 |
40 |
41 | --------------------------------------------------------------------------------