├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── straight_skeleton ├── README.md ├── StraightSkeletonNet.Tests │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── SkeletonExtendedTest.cs │ ├── SkeletonLevelEventsTest.cs │ ├── SkeletonTest.cs │ ├── SkeletonTestUtil.cs │ ├── StraightSkeletonNet.Tests.csproj │ └── packages.config ├── StraightSkeletonNet.sln └── StraightSkeletonNet │ ├── Circular │ ├── CircularList.cs │ ├── CircularNode.cs │ ├── Edge.cs │ └── Vertex.cs │ ├── EdgeResult.cs │ ├── Events │ ├── Chains │ │ ├── ChainType.cs │ │ ├── EdgeChain.cs │ │ ├── IChain.cs │ │ ├── SingleEdgeChain.cs │ │ └── SplitChain.cs │ ├── EdgeEvent.cs │ ├── MultiEdgeEvent.cs │ ├── MultiSplitEvent.cs │ ├── PickEvent.cs │ ├── SkeletonEvent.cs │ ├── SplitEvent.cs │ └── VertexSplitEvent.cs │ ├── LavUtil.cs │ ├── Path │ ├── FaceNode.cs │ ├── FaceQueue.cs │ ├── FaceQueueUtil.cs │ ├── PathQueue.cs │ └── PathQueueNode.cs │ ├── Primitives │ ├── LineLinear2d.cs │ ├── LineParametric2d.cs │ ├── PrimitiveUtils.cs │ ├── PriorityQueue.cs │ └── Vector2d.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Skeleton.cs │ ├── SkeletonBuilder.cs │ └── StraightSkeletonNet.csproj ├── utydepend ├── UtyDepend.Tests │ ├── ContainerTests.cs │ ├── InterceptionTests.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── Stubs │ │ ├── ClassA.cs │ │ ├── CollectionDependencyClass.cs │ │ ├── ConfigurableClass.cs │ │ ├── DummyConfigSection.cs │ │ └── PropertyClass.cs │ ├── UtyDepend.Tests.csproj │ └── packages.config ├── UtyDepend.sln └── UtyDepend │ ├── Component.cs │ ├── ComponentExtensions.cs │ ├── Config │ ├── IConfigSection.cs │ └── IConfigurable.cs │ ├── Container.cs │ ├── DependencyAttribute.cs │ ├── DependencyException.cs │ ├── IContainer.cs │ ├── Interception │ ├── Behaviors │ │ ├── ExecuteBehavior.cs │ │ └── IBehavior.cs │ ├── IInterceptor.cs │ ├── IMethodReturn.cs │ ├── IProxy.cs │ ├── InterceptionContext.cs │ ├── InterfaceInterceptor.cs │ ├── MethodInvocation.cs │ ├── MethodReturn.cs │ └── ProxyBase.cs │ ├── Lifetime │ ├── ContainerLifetimeManager.cs │ ├── ExternalLifetimeManager.cs │ ├── ILifetimeManager.cs │ ├── SingletonLifetimeManager.cs │ └── TransientLifetimeManager.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── Utils │ ├── Guard.cs │ ├── ProxyGen.cs │ └── TypeHelper.cs │ ├── UtyDepend.csproj │ └── packages.config └── utyrx ├── README.md ├── UtyRx.Tests ├── Disposables │ └── DisposableTest.cs ├── InternalUtil │ ├── MicroCoroutineTest.cs │ └── QueueWorkerTest.cs ├── Observable │ ├── Observable.ConcatTest.cs │ ├── Observable.ConcurrencyTest.cs │ ├── Observable.ErrorHandlingTest.cs │ ├── Observable.Events.cs │ ├── Observable.GeneratorTest.cs │ ├── Observable.PagingTest.cs │ ├── Observable.TimeTest.cs │ └── ObservableTest.cs ├── Operators │ ├── AggregateTest.cs │ ├── ContinueWithTest.cs │ ├── ConversionTest.cs │ ├── DoTest.cs │ ├── DurabilityTest.cs │ ├── RangeTest.cs │ ├── SelectMany.cs │ ├── TakeTest.cs │ ├── ToTest.cs │ └── WhenAllTest.cs ├── Properties │ └── AssemblyInfo.cs ├── Schedulers │ └── SchedulerTest.cs ├── Subjects │ └── SubjectTest.cs ├── Utils │ ├── ChainingAssertion.cs │ └── TestUtil.cs ├── UtyRx.Tests.csproj └── packages.config ├── UtyRx.sln └── UtyRx ├── Asynchronous └── WebRequestExtensions.cs ├── Disposables ├── BooleanDisposable.cs ├── CompositeDisposable.cs ├── DictionaryDisposable.cs ├── Disposable.cs ├── DisposableExtensions.cs ├── ICancelable.cs ├── MultipleAssignmentDisposable.cs ├── RefCountDisposable.cs ├── ScheduledDisposable.cs ├── SerialDisposable.cs ├── SingleAssignmentDisposable.cs └── StableCompositeDisposable.cs ├── InternalUtil ├── AscynLock.cs ├── ImmutableList.cs ├── ListObserver.cs ├── MicroCoroutine.cs ├── PriorityQueue.cs ├── ReflectionAccessor.cs ├── ScheduledItem.cs └── ThreadSafeQueueWorker.cs ├── Notifiers ├── BooleanNotifier.cs ├── CountNotifier.cs ├── MessageBroker.cs └── ScheduledNotifier.cs ├── Observable ├── Observable.Aggregate.cs ├── Observable.Binding.cs ├── Observable.Blocking.cs ├── Observable.Concatenate.cs ├── Observable.Concurrency.cs ├── Observable.Conversions.cs ├── Observable.Creation.cs ├── Observable.ErrorHandling.cs ├── Observable.Events.cs ├── Observable.FromAsync.cs ├── Observable.Joins.cs ├── Observable.Paging.cs ├── Observable.Time.cs └── Observable.cs ├── Operators ├── Aggregate.cs ├── Amb.cs ├── AsObservable.cs ├── AsSingleUnitObservable.cs ├── AsUnitObservable.cs ├── Buffer.cs ├── Cast.cs ├── Catch.cs ├── CombineLatest.cs ├── Concat.cs ├── ContinueWith.cs ├── Create.cs ├── DefaultIfEmpty.cs ├── Defer.cs ├── Delay.cs ├── DelaySubscription.cs ├── Dematerialize.cs ├── Distinct.cs ├── DistinctUntilChanged.cs ├── Do.cs ├── Empty.cs ├── Finally.cs ├── First.cs ├── ForEachAsync.cs ├── FromEvent.cs ├── GroupBy.cs ├── IgnoreElements.cs ├── Last.cs ├── Materialize.cs ├── Merge.cs ├── Never.cs ├── ObserveOn.cs ├── OfType.cs ├── OperatorObservableBase.cs ├── OperatorObserverBase.cs ├── PairWise.cs ├── Range.cs ├── RefCount.cs ├── Repeat.cs ├── RepeatSafe.cs ├── Return.cs ├── Sample.cs ├── Scan.cs ├── Select.cs ├── SelectMany.cs ├── Single.cs ├── Skip.cs ├── SkipUntil.cs ├── SkipWhile.cs ├── Start.cs ├── StartWith.cs ├── SubscribeOn.cs ├── Switch.cs ├── Synchronize.cs ├── SynchronizedObserver.cs ├── Take.cs ├── TakeLast.cs ├── TakeUntil.cs ├── TakeWhile.cs ├── Throttle.cs ├── ThrottleFirst.cs ├── Throw.cs ├── TimeInterval.cs ├── Timeout.cs ├── Timer.cs ├── Timestamp.cs ├── ToArray.cs ├── ToList.cs ├── ToObservable.cs ├── Wait.cs ├── WhenAll.cs ├── Where.cs ├── WithLatestFrom.cs ├── Zip.cs └── ZipLatest.cs ├── Properties └── AssemblyInfo.cs ├── Schedulers ├── IScheduler.cs ├── Scheduler.CurrentThread.cs ├── Scheduler.Immediate.cs ├── Scheduler.Main.cs ├── Scheduler.ThreadPool.cs └── Scheduler.cs ├── Subjects ├── AsyncSubject.cs ├── BehaviorSubject.cs ├── ConnectableObservable.cs ├── ISubject.cs ├── ReplaySubject.cs ├── Subject.cs └── SubjectExtensions.cs ├── System ├── CancellationToken.cs ├── EventPattern.cs ├── IObservable.cs ├── IObserver.cs ├── IOptimizedObservable.cs ├── IProgress.cs ├── Notification.cs ├── Observer.cs ├── Pair.cs ├── TimeInterval.cs ├── Timestamped.cs ├── Tuple.cs └── Unit.cs └── UtyRx.csproj /.gitignore: -------------------------------------------------------------------------------- 1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs) 2 | [Bb]in/ 3 | [Oo]bj/ 4 | 5 | # mstest test results 6 | TestResults 7 | 8 | ## Ignore Visual Studio temporary files, build results, and 9 | ## files generated by popular Visual Studio add-ons. 10 | 11 | # User-specific files 12 | *.suo 13 | *.user 14 | *.sln.docstates 15 | 16 | # Build results 17 | [Dd]ebug/ 18 | [Rr]elease/ 19 | x64/ 20 | *_i.c 21 | *_p.c 22 | *.ilk 23 | #*.meta 24 | *.obj 25 | *.pch 26 | *.pdb 27 | *.pgc 28 | *.pgd 29 | *.rsp 30 | *.sbr 31 | *.tlb 32 | *.tli 33 | *.tlh 34 | *.tmp 35 | *.log 36 | *.vspscc 37 | *.vssscc 38 | .builds 39 | 40 | # Visual C++ cache files 41 | ipch/ 42 | *.aps 43 | *.ncb 44 | *.opensdf 45 | *.sdf 46 | 47 | # Visual Studio profiler 48 | *.psess 49 | *.vsp 50 | *.vspx 51 | 52 | # Guidance Automation Toolkit 53 | *.gpState 54 | 55 | # ReSharper is a .NET coding add-in 56 | _ReSharper* 57 | 58 | # NCrunch 59 | *.ncrunch* 60 | .*crunch*.local.xml 61 | 62 | # Installshield output folder 63 | [Ee]xpress 64 | 65 | # DocProject is a documentation generator add-in 66 | DocProject/buildhelp/ 67 | DocProject/Help/*.HxT 68 | DocProject/Help/*.HxC 69 | DocProject/Help/*.hhc 70 | DocProject/Help/*.hhk 71 | DocProject/Help/*.hhp 72 | DocProject/Help/Html2 73 | DocProject/Help/html 74 | 75 | #Unity 76 | Library/ 77 | Temp/ 78 | 79 | # Click-Once directory 80 | publish 81 | 82 | # Publish Web Output 83 | *.Publish.xml 84 | 85 | # NuGet Packages Directory 86 | packages 87 | 88 | # Windows Azure Build Output 89 | csx 90 | *.build.csdef 91 | 92 | # Windows Store app package directory 93 | AppPackages/ 94 | 95 | # Others 96 | [Bb]in 97 | [Oo]bj 98 | sql 99 | TestResults 100 | [Tt]est[Rr]esult* 101 | *.Cache 102 | ClientBin 103 | [Ss]tyle[Cc]op.* 104 | ~$* 105 | *.dbmdl 106 | Generated_Code #added for RIA/Silverlight projects 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Description

2 | 3 | This repository contains different C# libraries which I use in different projects: 4 | 5 | * utydepend - dependency injection container 6 | * utyrx - reactive extensions fork which is based on unirx fork. 7 | * straight_skeleton - straight skeleton implementation which is port of kendzi's implementation 8 | -------------------------------------------------------------------------------- /straight_skeleton/README.md: -------------------------------------------------------------------------------- 1 | # StraightSkeletonNet 2 | 3 | Implementation of straight skeleton algorithm for polygons with holes. It is based on concept of tracking bisector intersection with queue of events to process and circular list with processed events called lavs. This implementation is highly modified concept described by Petr Felkel and Stepan Obdrzalek. In compare to original this algorithm has new kind of event and support for multiple events which appear in the same distance from edges. It is common when processing degenerate cases caused by polygon with right angles. 4 | 5 | This port has no external dependencies: all needed classes are ported. Original Java code depends on external libraries which provide some primitives: vector, line, ray, etc. It can be found here: 6 | https://github.com/kendzi/kendzi-math/tree/master/kendzi-straight-skeleton 7 | 8 | You can read more about this implementation at blog: 9 | http://reinterpretcat.blogspot.de/2016/02/straight-skeleton-on-net.html 10 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("StraightSkeletonNet.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("StraightSkeletonNet.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("11f01a71-1332-4e7f-9cfd-f963f72c36b8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet.Tests/SkeletonTestUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using StraightSkeletonNet.Primitives; 6 | 7 | namespace StraightSkeletonNet.Tests 8 | { 9 | internal class SkeletonTestUtil 10 | { 11 | public static List GetFacePoints(Skeleton sk) 12 | { 13 | List ret = new List(); 14 | 15 | foreach (EdgeResult edgeOutput in sk.Edges) 16 | { 17 | List points = edgeOutput.Polygon; 18 | foreach (Vector2d vector2d in points) 19 | { 20 | if (!ContainsEpsilon(ret, vector2d)) 21 | ret.Add(vector2d); 22 | } 23 | } 24 | return ret; 25 | } 26 | 27 | public static void AssertExpectedPoints(List expectedList, List givenList) 28 | { 29 | StringBuilder sb = new StringBuilder(); 30 | foreach (Vector2d expected in expectedList) 31 | { 32 | if (!ContainsEpsilon(givenList, expected)) 33 | sb.AppendFormat("Can't find expected point ({0}, {1}) in given list\n", expected.X, expected.Y); 34 | } 35 | 36 | foreach (Vector2d given in givenList) 37 | { 38 | if (!ContainsEpsilon(expectedList, given)) 39 | sb.AppendFormat("Can't find given point ({0}, {1}) in expected list\n", given.X, given.Y); 40 | } 41 | 42 | if (sb.Length > 0) 43 | throw new InvalidOperationException(sb.ToString()); 44 | } 45 | 46 | public static bool ContainsEpsilon(List list, Vector2d p) 47 | { 48 | return list.Any(l => EqualEpsilon(l.X, p.X) && EqualEpsilon(l.Y, p.Y)); 49 | } 50 | 51 | public static bool EqualEpsilon(double d1, double d2) 52 | { 53 | return Math.Abs(d1 - d2) < 5E-6; 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet.Tests/StraightSkeletonNet.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {3898AF36-98E4-4EBF-BB2C-06EC91F1EC8E} 8 | Library 9 | Properties 10 | StraightSkeletonNet.Tests 11 | StraightSkeletonNet.Tests 12 | v3.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {4b85469b-a41f-4e31-a7f1-c7337a78dc6a} 51 | StraightSkeletonNet 52 | 53 | 54 | 55 | 62 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30324.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StraightSkeletonNet", "StraightSkeletonNet\StraightSkeletonNet.csproj", "{4B85469B-A41F-4E31-A7F1-C7337A78DC6A}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StraightSkeletonNet.Tests", "StraightSkeletonNet.Tests\StraightSkeletonNet.Tests.csproj", "{3898AF36-98E4-4EBF-BB2C-06EC91F1EC8E}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4B85469B-A41F-4E31-A7F1-C7337A78DC6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {4B85469B-A41F-4E31-A7F1-C7337A78DC6A}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {4B85469B-A41F-4E31-A7F1-C7337A78DC6A}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {4B85469B-A41F-4E31-A7F1-C7337A78DC6A}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {3898AF36-98E4-4EBF-BB2C-06EC91F1EC8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {3898AF36-98E4-4EBF-BB2C-06EC91F1EC8E}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {3898AF36-98E4-4EBF-BB2C-06EC91F1EC8E}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {3898AF36-98E4-4EBF-BB2C-06EC91F1EC8E}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Circular/CircularNode.cs: -------------------------------------------------------------------------------- 1 | namespace StraightSkeletonNet.Circular 2 | { 3 | public class CircularNode 4 | { 5 | internal ICircularList List; 6 | 7 | public CircularNode Next; 8 | public CircularNode Previous; 9 | 10 | public void AddNext(CircularNode node) 11 | { 12 | List.AddNext(this, node); 13 | } 14 | 15 | public void AddPrevious(CircularNode node) 16 | { 17 | List.AddPrevious(this, node); 18 | } 19 | 20 | public void Remove() 21 | { 22 | List.Remove(this); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Circular/Edge.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Primitives; 2 | 3 | namespace StraightSkeletonNet.Circular 4 | { 5 | public class Edge : CircularNode 6 | { 7 | public readonly Vector2d Begin; 8 | public readonly Vector2d End; 9 | public readonly Vector2d Norm; 10 | 11 | internal readonly LineLinear2d LineLinear2d; 12 | internal LineParametric2d BisectorNext; 13 | internal LineParametric2d BisectorPrevious; 14 | 15 | public Edge(Vector2d begin, Vector2d end) 16 | { 17 | Begin = begin; 18 | End = end; 19 | 20 | LineLinear2d = new LineLinear2d(begin, end); 21 | Norm = (end - begin).Normalized(); 22 | } 23 | 24 | public override string ToString() 25 | { 26 | return "Edge [p1=" + Begin + ", p2=" + End + "]"; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Circular/Vertex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using StraightSkeletonNet.Path; 3 | using StraightSkeletonNet.Primitives; 4 | 5 | namespace StraightSkeletonNet.Circular 6 | { 7 | internal class Vertex : CircularNode 8 | { 9 | const int RoundDigitCount = 5; 10 | 11 | public Vector2d Point; 12 | public readonly double Distance; 13 | public readonly LineParametric2d Bisector; 14 | 15 | public readonly Edge NextEdge; 16 | public readonly Edge PreviousEdge; 17 | 18 | public FaceNode LeftFace; 19 | public FaceNode RightFace; 20 | 21 | public bool IsProcessed; 22 | 23 | public Vertex(Vector2d point, double distance, LineParametric2d bisector, 24 | Edge previousEdge, Edge nextEdge) 25 | { 26 | Point = point; 27 | Distance = Math.Round(distance, RoundDigitCount); 28 | Bisector = bisector; 29 | PreviousEdge = previousEdge; 30 | NextEdge = nextEdge; 31 | 32 | IsProcessed = false; 33 | } 34 | 35 | public override string ToString() 36 | { 37 | return "Vertex [v=" + Point + ", IsProcessed=" + IsProcessed + 38 | ", Bisector=" + Bisector + ", PreviousEdge=" + PreviousEdge + 39 | ", NextEdge=" + NextEdge; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/EdgeResult.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using StraightSkeletonNet.Circular; 3 | using StraightSkeletonNet.Primitives; 4 | 5 | namespace StraightSkeletonNet 6 | { 7 | public class EdgeResult 8 | { 9 | public readonly Edge Edge; 10 | public readonly List Polygon; 11 | 12 | public EdgeResult(Edge edge, List polygon) 13 | { 14 | Edge = edge; 15 | Polygon = polygon; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/Chains/ChainType.cs: -------------------------------------------------------------------------------- 1 | namespace StraightSkeletonNet.Events.Chains 2 | { 3 | internal enum ChainType 4 | { 5 | Edge, 6 | ClosedEdge, 7 | Split 8 | } 9 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/Chains/EdgeChain.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using StraightSkeletonNet.Circular; 3 | 4 | namespace StraightSkeletonNet.Events.Chains 5 | { 6 | internal class EdgeChain : IChain 7 | { 8 | private readonly bool _closed; 9 | 10 | public EdgeChain(List edgeList) 11 | { 12 | EdgeList = edgeList; 13 | _closed = PreviousVertex == NextVertex; 14 | } 15 | 16 | public List EdgeList { get; private set; } 17 | 18 | public Edge PreviousEdge 19 | { 20 | get { return EdgeList[0].PreviousVertex.PreviousEdge; } 21 | } 22 | 23 | public Edge NextEdge 24 | { 25 | get { return EdgeList[EdgeList.Count - 1].NextVertex.NextEdge; } 26 | } 27 | 28 | public Vertex PreviousVertex 29 | { 30 | get { return EdgeList[0].PreviousVertex; } 31 | } 32 | 33 | public Vertex NextVertex 34 | { 35 | get { return EdgeList[EdgeList.Count - 1].NextVertex; } 36 | } 37 | 38 | public Vertex CurrentVertex 39 | { 40 | get { return null; } 41 | } 42 | 43 | public ChainType ChainType 44 | { 45 | get { return _closed ? ChainType.ClosedEdge : ChainType.Edge; } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/Chains/IChain.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Circular; 2 | 3 | namespace StraightSkeletonNet.Events.Chains 4 | { 5 | internal interface IChain 6 | { 7 | Edge PreviousEdge { get; } 8 | Edge NextEdge { get; } 9 | Vertex PreviousVertex { get; } 10 | Vertex NextVertex { get; } 11 | Vertex CurrentVertex { get; } 12 | ChainType ChainType { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/Chains/SingleEdgeChain.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Circular; 2 | 3 | namespace StraightSkeletonNet.Events.Chains 4 | { 5 | internal class SingleEdgeChain : IChain 6 | { 7 | private readonly Vertex _nextVertex; 8 | private readonly Edge _oppositeEdge; 9 | private readonly Vertex _previousVertex; 10 | 11 | public SingleEdgeChain(Edge oppositeEdge, Vertex nextVertex) 12 | { 13 | _oppositeEdge = oppositeEdge; 14 | _nextVertex = nextVertex; 15 | 16 | // previous vertex for opposite edge event is valid only before 17 | // processing of multi split event start. We need to store vertex before 18 | // processing starts. 19 | _previousVertex = nextVertex.Previous as Vertex; 20 | } 21 | 22 | public Edge PreviousEdge { get { return _oppositeEdge; } } 23 | 24 | public Edge NextEdge { get { return _oppositeEdge; } } 25 | 26 | public Vertex PreviousVertex { get { return _previousVertex; } } 27 | 28 | public Vertex NextVertex { get { return _nextVertex; } } 29 | 30 | public Vertex CurrentVertex { get { return null; } } 31 | 32 | public ChainType ChainType { get { return ChainType.Split; } } 33 | } 34 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/Chains/SplitChain.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Circular; 2 | 3 | namespace StraightSkeletonNet.Events.Chains 4 | { 5 | internal class SplitChain : IChain 6 | { 7 | private readonly SplitEvent _splitEvent; 8 | 9 | public SplitChain(SplitEvent @event) 10 | { 11 | _splitEvent = @event; 12 | } 13 | 14 | public Edge OppositeEdge 15 | { 16 | get 17 | { 18 | if (!(_splitEvent is VertexSplitEvent)) 19 | return _splitEvent.OppositeEdge; 20 | 21 | return null; 22 | } 23 | } 24 | 25 | public Edge PreviousEdge 26 | { 27 | get { return _splitEvent.Parent.PreviousEdge; } 28 | } 29 | 30 | public Edge NextEdge 31 | { 32 | get { return _splitEvent.Parent.NextEdge; } 33 | } 34 | 35 | public Vertex PreviousVertex 36 | { 37 | get { return _splitEvent.Parent.Previous as Vertex; } 38 | } 39 | 40 | public Vertex NextVertex 41 | { 42 | get { return _splitEvent.Parent.Next as Vertex; } 43 | } 44 | 45 | public Vertex CurrentVertex 46 | { 47 | get { return _splitEvent.Parent; } 48 | } 49 | 50 | public ChainType ChainType 51 | { 52 | get { return ChainType.Split; } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/EdgeEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using StraightSkeletonNet.Circular; 3 | using StraightSkeletonNet.Primitives; 4 | 5 | namespace StraightSkeletonNet.Events 6 | { 7 | internal class EdgeEvent : SkeletonEvent 8 | { 9 | public readonly Vertex NextVertex; 10 | public readonly Vertex PreviousVertex; 11 | 12 | public override bool IsObsolete 13 | { 14 | get { return PreviousVertex.IsProcessed || NextVertex.IsProcessed; } 15 | } 16 | 17 | public EdgeEvent(Vector2d point, double distance, Vertex previousVertex, Vertex nextVertex) : 18 | base(point, distance) 19 | { 20 | PreviousVertex = previousVertex; 21 | NextVertex = nextVertex; 22 | } 23 | 24 | public override String ToString() 25 | { 26 | return "EdgeEvent [V=" + V + ", PreviousVertex=" 27 | + (PreviousVertex != null ? PreviousVertex.Point.ToString() : "null") + 28 | ", NextVertex=" 29 | + (NextVertex != null ? NextVertex.Point.ToString() : "null") + ", Distance=" + 30 | Distance + "]"; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/MultiEdgeEvent.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Events.Chains; 2 | using StraightSkeletonNet.Primitives; 3 | 4 | namespace StraightSkeletonNet.Events 5 | { 6 | internal class MultiEdgeEvent : SkeletonEvent 7 | { 8 | public readonly EdgeChain Chain; 9 | 10 | public override bool IsObsolete { get { return false; } } 11 | 12 | public MultiEdgeEvent(Vector2d point, double distance, EdgeChain chain) : base(point, distance) 13 | { 14 | Chain = chain; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/MultiSplitEvent.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using StraightSkeletonNet.Events.Chains; 3 | using StraightSkeletonNet.Primitives; 4 | 5 | namespace StraightSkeletonNet.Events 6 | { 7 | internal class MultiSplitEvent : SkeletonEvent 8 | { 9 | public readonly List Chains; 10 | 11 | public override bool IsObsolete { get { return false; } } 12 | 13 | public MultiSplitEvent(Vector2d point, double distance, List chains) 14 | : base(point, distance) 15 | { 16 | Chains = chains; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/PickEvent.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Events.Chains; 2 | using StraightSkeletonNet.Primitives; 3 | 4 | namespace StraightSkeletonNet.Events 5 | { 6 | internal class PickEvent : SkeletonEvent 7 | { 8 | public readonly EdgeChain Chain; 9 | 10 | public override bool IsObsolete { get { return false; } } 11 | 12 | public PickEvent(Vector2d point, double distance, EdgeChain chain) : base(point, distance) 13 | { 14 | Chain = chain; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/SkeletonEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using StraightSkeletonNet.Primitives; 3 | 4 | namespace StraightSkeletonNet.Events 5 | { 6 | internal abstract class SkeletonEvent 7 | { 8 | public Vector2d V; 9 | 10 | public double Distance { get; protected set; } 11 | public abstract bool IsObsolete { get; } 12 | 13 | protected SkeletonEvent(Vector2d point, double distance) 14 | { 15 | V = point; 16 | Distance = distance; 17 | } 18 | 19 | public override String ToString() 20 | { 21 | return "IntersectEntry [V=" + V + ", Distance=" + Distance + "]"; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/SplitEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using StraightSkeletonNet.Circular; 3 | using StraightSkeletonNet.Primitives; 4 | 5 | namespace StraightSkeletonNet.Events 6 | { 7 | internal class SplitEvent : SkeletonEvent 8 | { 9 | public readonly Edge OppositeEdge; 10 | public readonly Vertex Parent; 11 | 12 | public SplitEvent(Vector2d point, double distance, Vertex parent, Edge oppositeEdge) 13 | : base(point, distance) 14 | { 15 | Parent = parent; 16 | OppositeEdge = oppositeEdge; 17 | } 18 | 19 | public override bool IsObsolete { get { return Parent.IsProcessed; } } 20 | 21 | 22 | public override String ToString() 23 | { 24 | return "SplitEvent [V=" + V + ", Parent=" + (Parent != null ? Parent.Point.ToString() : "null") + 25 | ", Distance=" + Distance + "]"; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Events/VertexSplitEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using StraightSkeletonNet.Circular; 3 | using StraightSkeletonNet.Primitives; 4 | 5 | namespace StraightSkeletonNet.Events 6 | { 7 | internal class VertexSplitEvent : SplitEvent 8 | { 9 | public VertexSplitEvent(Vector2d point, double distance, Vertex parent) : 10 | base(point, distance, parent, null) 11 | { 12 | } 13 | 14 | public override String ToString() 15 | { 16 | return "VertexSplitEvent [V=" + V + ", Parent=" + 17 | (Parent != null ? Parent.Point.ToString() : "null") 18 | + ", Distance=" + Distance + "]"; 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Path/FaceNode.cs: -------------------------------------------------------------------------------- 1 | using StraightSkeletonNet.Circular; 2 | 3 | namespace StraightSkeletonNet.Path 4 | { 5 | internal class FaceNode : PathQueueNode 6 | { 7 | public readonly Vertex Vertex; 8 | 9 | public FaceNode(Vertex vertex) 10 | { 11 | Vertex = vertex; 12 | } 13 | 14 | public FaceQueue FaceQueue { get { return (FaceQueue) List; } } 15 | 16 | public bool IsQueueUnconnected { get { return FaceQueue.IsUnconnected; } } 17 | 18 | public void QueueClose() 19 | { 20 | FaceQueue.Close(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Path/FaceQueue.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using StraightSkeletonNet.Circular; 3 | 4 | namespace StraightSkeletonNet.Path 5 | { 6 | internal class FaceQueue : PathQueue 7 | { 8 | /// Edge for given queue. 9 | public Edge Edge; 10 | 11 | /// Flag if queue is closed. After closing can't be modify. 12 | public bool Closed { get; private set; } 13 | 14 | /// Flag if queue is connected to edges. 15 | public bool IsUnconnected 16 | { 17 | get { return Edge == null; } 18 | } 19 | 20 | public override void AddPush(PathQueueNode node, PathQueueNode newNode) 21 | { 22 | if (Closed) 23 | throw new InvalidOperationException("Can't add node to closed FaceQueue"); 24 | 25 | base.AddPush(node, newNode); 26 | } 27 | 28 | /// Mark queue as closed. After closing can't be modify. 29 | public void Close() 30 | { 31 | Closed = true; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Path/FaceQueueUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace StraightSkeletonNet.Path 4 | { 5 | internal class FaceQueueUtil 6 | { 7 | /// 8 | /// Connect two nodes queue. Id both nodes comes from the same queue, queue 9 | /// is closed. If nodes are from different queues nodes are moved to one of 10 | /// them. 11 | /// 12 | /// First face queue. 13 | /// Second face queue. 14 | public static void ConnectQueues(FaceNode firstFace, FaceNode secondFace) 15 | { 16 | if (firstFace.List == null) 17 | throw new ArgumentException("firstFace.list cannot be null."); 18 | if (secondFace.List == null) 19 | throw new ArgumentException("secondFace.list cannot be null."); 20 | 21 | if (firstFace.List == secondFace.List) 22 | { 23 | if (!firstFace.IsEnd || !secondFace.IsEnd) 24 | throw new InvalidOperationException("try to connect the same list not on end nodes"); 25 | 26 | if (firstFace.IsQueueUnconnected || secondFace.IsQueueUnconnected) 27 | throw new InvalidOperationException("can't close node queue not conected with edges"); 28 | 29 | firstFace.QueueClose(); 30 | return; 31 | } 32 | 33 | if (!firstFace.IsQueueUnconnected && !secondFace.IsQueueUnconnected) 34 | throw new InvalidOperationException( 35 | "can't connect two diffrent queues if each of them is connected to edge"); 36 | 37 | if (!firstFace.IsQueueUnconnected) 38 | { 39 | var qLeft = secondFace.FaceQueue; 40 | MoveNodes(firstFace, secondFace); 41 | qLeft.Close(); 42 | } 43 | else 44 | { 45 | var qRight = firstFace.FaceQueue; 46 | MoveNodes(secondFace, firstFace); 47 | qRight.Close(); 48 | } 49 | } 50 | 51 | private static void MoveNodes(FaceNode firstFace, FaceNode secondFace) 52 | { 53 | firstFace.AddQueue(secondFace); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Path/PathQueueNode.cs: -------------------------------------------------------------------------------- 1 | namespace StraightSkeletonNet.Path 2 | { 3 | internal class PathQueueNode where T : PathQueueNode 4 | { 5 | public PathQueue List; 6 | public PathQueueNode Next; 7 | public PathQueueNode Previous; 8 | 9 | public bool IsEnd 10 | { 11 | get { return Next == null || Previous == null; } 12 | } 13 | 14 | public void AddPush(PathQueueNode node) 15 | { 16 | List.AddPush(this, node); 17 | } 18 | 19 | public PathQueueNode AddQueue(PathQueueNode queue) 20 | { 21 | if (List == queue.List) 22 | return null; 23 | 24 | var currentQueue = this; 25 | 26 | var current = queue; 27 | 28 | while (current != null) 29 | { 30 | var next = current.Pop(); 31 | currentQueue.AddPush(current); 32 | currentQueue = current; 33 | 34 | current = next; 35 | } 36 | 37 | return currentQueue; 38 | } 39 | 40 | public PathQueueNode FindEnd() 41 | { 42 | if (IsEnd) 43 | return this; 44 | 45 | var current = this; 46 | while (current.Previous != null) 47 | current = current.Previous; 48 | 49 | return current; 50 | } 51 | 52 | public PathQueueNode Pop() 53 | { 54 | return List.Pop(this); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Primitives/LineLinear2d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace StraightSkeletonNet.Primitives 4 | { 5 | /// 6 | /// Geometry line in linear form. General form: 7 | /// Ax + By + C = 0; 8 | /// 9 | /// 10 | internal struct LineLinear2d 11 | { 12 | public double A; 13 | public double B; 14 | public double C; 15 | 16 | /// Linear line from two points on line. 17 | public LineLinear2d(Vector2d pP1, Vector2d pP2) 18 | { 19 | A = pP1.Y - pP2.Y; 20 | B = pP2.X - pP1.X; 21 | C = pP1.X*pP2.Y - pP2.X*pP1.Y; 22 | } 23 | 24 | /// Linear line. 25 | public LineLinear2d(double pA, double pB, double pC) 26 | { 27 | A = pA; 28 | B = pB; 29 | C = pC; 30 | } 31 | 32 | /// Collision point of two lines. 33 | /// Line to collision. 34 | /// Collision point. 35 | public Vector2d Collide(LineLinear2d pLine) 36 | { 37 | return Collide(this, pLine); 38 | } 39 | 40 | /// Collision point of two lines. 41 | public static Vector2d Collide(LineLinear2d pLine1, LineLinear2d pLine2) 42 | { 43 | return Collide(pLine1.A, pLine1.B, pLine1.C, pLine2.A, pLine2.B, pLine2.C); 44 | } 45 | 46 | /// Collision point of two lines. 47 | public static Vector2d Collide(double A1, double B1, double C1, double A2, double B2, double C2) 48 | { 49 | var WAB = A1*B2 - A2*B1; 50 | var WBC = B1*C2 - B2*C1; 51 | var WCA = C1*A2 - C2*A1; 52 | 53 | return WAB == 0 ? Vector2d.Empty : new Vector2d(WBC / WAB, WCA / WAB); 54 | } 55 | 56 | /// Check whether point belongs to line. 57 | public bool Contains(Vector2d point) 58 | { 59 | return Math.Abs((point.X * A + point.Y * B + C)) < double.Epsilon; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Primitives/LineParametric2d.cs: -------------------------------------------------------------------------------- 1 |  2 | namespace StraightSkeletonNet.Primitives 3 | { 4 | /// 5 | /// Geometry line in parametric form: 6 | /// x = x_A + t * u_x; 7 | /// y = y_A + t * u_y; 8 | /// where t in R 9 | /// 10 | /// 11 | internal struct LineParametric2d 12 | { 13 | public static readonly LineParametric2d Empty = new LineParametric2d(Vector2d.Empty, Vector2d.Empty); 14 | public Vector2d A; 15 | public Vector2d U; 16 | 17 | public LineParametric2d(Vector2d pA, Vector2d pU) 18 | { 19 | A = pA; 20 | U = pU; 21 | } 22 | 23 | public LineLinear2d CreateLinearForm() 24 | { 25 | var x = this.A.X; 26 | var y = this.A.Y; 27 | 28 | var B = -U.X; 29 | var A = U.Y; 30 | 31 | var C = -(A*x + B*y); 32 | return new LineLinear2d(A, B, C); 33 | } 34 | 35 | public static Vector2d Collide(LineParametric2d ray, LineLinear2d line, double epsilon) 36 | { 37 | var collide = LineLinear2d.Collide(ray.CreateLinearForm(), line); 38 | if (collide.Equals(Vector2d.Empty)) 39 | return Vector2d.Empty; 40 | 41 | var collideVector = collide - ray.A; 42 | return ray.U.Dot(collideVector) < epsilon ? Vector2d.Empty : collide; 43 | } 44 | 45 | public bool IsOnLeftSite(Vector2d point, double epsilon) 46 | { 47 | var direction = point - A; 48 | return PrimitiveUtils.OrthogonalRight(U).Dot(direction) < epsilon; 49 | } 50 | 51 | public bool IsOnRightSite(Vector2d point, double epsilon) 52 | { 53 | var direction = point - A; 54 | return PrimitiveUtils.OrthogonalRight(U).Dot(direction) > -epsilon; 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Primitives/Vector2d.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace StraightSkeletonNet.Primitives 4 | { 5 | /// Represents point or vector in 2D space. 6 | public struct Vector2d 7 | { 8 | public static Vector2d Empty = new Vector2d(double.MinValue, double.MinValue); 9 | 10 | public double X; 11 | public double Y; 12 | 13 | public Vector2d(Vector2d var1) 14 | { 15 | X = var1.X; 16 | Y = var1.Y; 17 | } 18 | 19 | public Vector2d(double var1, double var3) 20 | { 21 | X = var1; 22 | Y = var3; 23 | } 24 | 25 | public void Negate() 26 | { 27 | X = -X; 28 | Y = -Y; 29 | } 30 | 31 | public double DistanceTo(Vector2d var1) 32 | { 33 | var var2 = X - var1.X; 34 | var var4 = Y - var1.Y; 35 | return Math.Sqrt(var2 * var2 + var4 * var4); 36 | } 37 | 38 | public Vector2d Normalized() 39 | { 40 | var var1 = 1.0D/Math.Sqrt(X*X + Y*Y); 41 | return new Vector2d(X *= var1, Y *= var1); 42 | } 43 | 44 | public double Dot(Vector2d var1) 45 | { 46 | return X*var1.X + Y*var1.Y; 47 | } 48 | 49 | public double DistanceSquared(Vector2d var1) 50 | { 51 | var var2 = X - var1.X; 52 | var var4 = Y - var1.Y; 53 | return var2*var2 + var4*var4; 54 | } 55 | 56 | public static Vector2d operator -(Vector2d left, Vector2d right) 57 | { 58 | return new Vector2d(left.X - right.X, left.Y - right.Y); 59 | } 60 | 61 | public static Vector2d operator +(Vector2d left, Vector2d right) 62 | { 63 | return new Vector2d(left.X + right.X, left.Y + right.Y); 64 | } 65 | 66 | public static Vector2d operator *(Vector2d left, double scale) 67 | { 68 | return new Vector2d(left.X * scale, left.Y * scale); 69 | } 70 | 71 | public static bool operator ==(Vector2d left, Vector2d right) 72 | { 73 | return left.Equals(right); 74 | } 75 | 76 | public static bool operator !=(Vector2d left, Vector2d right) 77 | { 78 | return !(left == right); 79 | } 80 | 81 | public bool Equals(Vector2d obj) 82 | { 83 | return X.Equals(obj.X) && Y.Equals(obj.Y); 84 | } 85 | 86 | public override bool Equals(object obj) 87 | { 88 | if (ReferenceEquals(null, obj)) return false; 89 | return obj is Vector2d && Equals((Vector2d)obj); 90 | } 91 | 92 | public override int GetHashCode() 93 | { 94 | unchecked 95 | { 96 | return (X.GetHashCode()*397) ^ Y.GetHashCode(); 97 | } 98 | } 99 | 100 | public override string ToString() 101 | { 102 | return string.Format("({0}, {1})", X, Y); 103 | } 104 | } 105 | } -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("StraightSkeletonNet")] 6 | [assembly: AssemblyDescription("Straight Skeleton implementation.")] 7 | [assembly: AssemblyProduct("StraightSkeletonNet")] 8 | [assembly: AssemblyCopyright("Copyright © Ilya Builuk, 2016")] 9 | 10 | [assembly: ComVisible(false)] 11 | [assembly: Guid("8be8b2be-6c02-41b6-bbb6-5c69f2d5e987")] 12 | 13 | [assembly: AssemblyVersion("1.0.*")] 14 | [assembly: AssemblyFileVersion("1.0.*")] 15 | [assembly: InternalsVisibleTo("StraightSkeletonNet.Tests")] 16 | -------------------------------------------------------------------------------- /straight_skeleton/StraightSkeletonNet/Skeleton.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using StraightSkeletonNet.Primitives; 3 | 4 | namespace StraightSkeletonNet 5 | { 6 | /// Represents skeleton algorithm results. 7 | public class Skeleton 8 | { 9 | /// Result of skeleton algorithm for edge. 10 | public readonly List Edges; 11 | 12 | /// Distance points from edges. 13 | public readonly Dictionary Distances; 14 | 15 | /// Creates instance of . 16 | public Skeleton(List edges, Dictionary distances) 17 | { 18 | Edges = edges; 19 | Distances = distances; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UtyDepend.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UtyDepend.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("60ef5fe5-d2a5-46e8-aa41-d57938265ed2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/Stubs/ClassA.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using UtyDepend.Interception; 4 | 5 | namespace UtyDepend.Tests.Stubs 6 | { 7 | public interface IClassA 8 | { 9 | int Add(int a, int b); 10 | string SayHello(string name); 11 | } 12 | 13 | public class ClassA1: IClassA 14 | { 15 | 16 | public int Add(int a, int b) 17 | { 18 | return a + b; 19 | } 20 | 21 | public string SayHello(string name) 22 | { 23 | return String.Format("Hello from A1, {0}", name); 24 | } 25 | } 26 | 27 | public class ClassA2 : IClassA 28 | { 29 | 30 | public int Add(int a, int b) 31 | { 32 | return a + b; 33 | } 34 | 35 | public string SayHello(string name) 36 | { 37 | return String.Format("Hello from A2, {0}", name); 38 | } 39 | } 40 | 41 | public class ClassA3 : IClassA 42 | { 43 | 44 | public int Add(int a, int b) 45 | { 46 | return a + b; 47 | } 48 | 49 | public string SayHello(string name) 50 | { 51 | return String.Format("Hello from A3, {0}", name); 52 | } 53 | } 54 | 55 | 56 | public class ClassAProxy : ProxyBase, IClassA 57 | { 58 | public System.Int32 Add(System.Int32 a, System.Int32 b) 59 | { 60 | var methodInvocation = BuildMethodInvocation(MethodBase.GetCurrentMethod(), a, b); 61 | return (int) RunBehaviors(methodInvocation).GetReturnValue(); 62 | } 63 | 64 | public System.String SayHello(System.String name) 65 | { 66 | var methodInvocation = BuildMethodInvocation(MethodBase.GetCurrentMethod(), name); 67 | return (string) RunBehaviors(methodInvocation).GetReturnValue(); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/Stubs/CollectionDependencyClass.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UtyDepend.Tests.Stubs 4 | { 5 | public class CollectionDependencyClass 6 | { 7 | public IEnumerable Classes { get; private set; } 8 | 9 | [Dependency] 10 | public CollectionDependencyClass(IEnumerable classes) 11 | { 12 | Classes = classes; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/Stubs/ConfigurableClass.cs: -------------------------------------------------------------------------------- 1 | using UtyDepend.Config; 2 | 3 | namespace UtyDepend.Tests.Stubs 4 | { 5 | class ConfigurableClass: IConfigurable 6 | { 7 | public IConfigSection ConfigSection { get; set; } 8 | public void Configure(IConfigSection config) 9 | { 10 | ConfigSection = config; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/Stubs/DummyConfigSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UtyDepend.Config; 4 | 5 | namespace UtyDepend.Tests.Stubs 6 | { 7 | public class DummyConfigSection : IConfigSection 8 | { 9 | public IEnumerable GetSections(string xpath) 10 | { 11 | throw new NotImplementedException(); 12 | } 13 | 14 | public IConfigSection GetSection(string xpath) 15 | { 16 | throw new NotImplementedException(); 17 | } 18 | 19 | public string GetString(string xpath, string defaultValue = "") 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | 24 | public int GetInt(string xpath, int defaultValue) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | 29 | public float GetFloat(string xpath, float defaultValue) 30 | { 31 | throw new NotImplementedException(); 32 | } 33 | 34 | public bool GetBool(string xpath, bool defaultValue) 35 | { 36 | throw new NotImplementedException(); 37 | } 38 | 39 | public Type GetType(string xpath) 40 | { 41 | throw new NotImplementedException(); 42 | } 43 | 44 | public T GetInstance(string xpath) 45 | { 46 | throw new NotImplementedException(); 47 | } 48 | 49 | public T GetInstance(string xpath, params object[] args) 50 | { 51 | throw new NotImplementedException(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/Stubs/PropertyClass.cs: -------------------------------------------------------------------------------- 1 | namespace UtyDepend.Tests.Stubs 2 | { 3 | public interface ITestInterface 4 | { 5 | } 6 | 7 | public class TestInterface : ITestInterface 8 | { 9 | } 10 | 11 | public interface IPropertyClass 12 | { 13 | } 14 | 15 | public class PropertyClass : IPropertyClass 16 | { 17 | [Dependency] 18 | public ITestInterface Test { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/UtyDepend.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {83449520-C81A-4D7A-AE0F-33F285571AFF} 8 | Library 9 | Properties 10 | UtyDepend.Tests 11 | UtyDepend.Tests 12 | v3.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\NUnit.2.6.3\lib\nunit.framework.dll 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | {72ee10a7-bdb1-4a33-990d-62ea88e2496e} 54 | DependencyNet 55 | 56 | 57 | 58 | 65 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /utydepend/UtyDepend.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30324.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtyDepend", "UtyDepend\UtyDepend.csproj", "{72EE10A7-BDB1-4A33-990D-62EA88E2496E}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtyDepend.Tests", "UtyDepend.Tests\UtyDepend.Tests.csproj", "{83449520-C81A-4D7A-AE0F-33F285571AFF}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {72EE10A7-BDB1-4A33-990D-62EA88E2496E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {72EE10A7-BDB1-4A33-990D-62EA88E2496E}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {72EE10A7-BDB1-4A33-990D-62EA88E2496E}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {72EE10A7-BDB1-4A33-990D-62EA88E2496E}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {83449520-C81A-4D7A-AE0F-33F285571AFF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {83449520-C81A-4D7A-AE0F-33F285571AFF}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {83449520-C81A-4D7A-AE0F-33F285571AFF}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {83449520-C81A-4D7A-AE0F-33F285571AFF}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /utydepend/UtyDepend/ComponentExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyDepend.Lifetime; 3 | 4 | namespace UtyDepend 5 | { 6 | /// Defines the extension methods for Component class. 7 | public static class ComponentExtensions 8 | { 9 | /// Defines singleton lifetime manager for component. 10 | public static Component Singleton(this Component component) 11 | { 12 | component.LifetimeManager = Activator.CreateInstance(typeof (SingletonLifetimeManager)) as ILifetimeManager; 13 | return component; 14 | } 15 | 16 | /// Defines Transient lifetime manager for component. 17 | public static Component Transient(this Component component) 18 | { 19 | component.LifetimeManager = Activator.CreateInstance(typeof (TransientLifetimeManager)) as ILifetimeManager; 20 | return component; 21 | } 22 | 23 | /// Uses custom LifetimeManager. 24 | public static Component CustomLifetime(this Component component, ILifetimeManager lifetimeManager) 25 | { 26 | component.LifetimeManager = lifetimeManager; 27 | return component; 28 | } 29 | 30 | /// Defines singleton lifetime manager for component. 31 | public static Component External(this Component component) 32 | { 33 | component.LifetimeManager = Activator.CreateInstance(typeof (ExternalLifetimeManager)) as ILifetimeManager; 34 | return component; 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Config/IConfigSection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyDepend.Config 5 | { 6 | /// Represens a config entry. 7 | public interface IConfigSection 8 | { 9 | /// Returns the set of ConfigSections. 10 | /// xpath 11 | IEnumerable GetSections(string xpath); 12 | 13 | /// Returns JsonConfigSection. 14 | /// xpath 15 | /// IConfigSection. 16 | IConfigSection GetSection(string xpath); 17 | 18 | /// Returns string. 19 | /// xpath. 20 | /// 21 | /// String value. 22 | string GetString(string xpath, string defaultValue = ""); 23 | 24 | /// Returns int. 25 | /// 26 | /// 27 | /// Int value. 28 | int GetInt(string xpath, int defaultValue); 29 | 30 | /// Returns float. 31 | /// xpath 32 | /// Default value. 33 | /// Float value. 34 | float GetFloat(string xpath, float defaultValue); 35 | 36 | /// Returns bool. 37 | /// xpath 38 | /// Default value. 39 | /// Boolean. 40 | bool GetBool(string xpath, bool defaultValue); 41 | 42 | /// Returns type object. 43 | /// xpath. 44 | /// Type. 45 | Type GetType(string xpath); 46 | 47 | /// Returns the instance of T. 48 | /// Type of instance. 49 | /// xpath. 50 | /// Instance. 51 | T GetInstance(string xpath); 52 | 53 | /// Returns the instance of T. 54 | /// Instance type. 55 | /// xpath 56 | /// Constructor parameters. 57 | /// Instance. 58 | T GetInstance(string xpath, params object[] args); 59 | } 60 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Config/IConfigurable.cs: -------------------------------------------------------------------------------- 1 | namespace UtyDepend.Config 2 | { 3 | /// Defines configurable class behaviour. 4 | public interface IConfigurable 5 | { 6 | /// Configures object using configuration section. 7 | /// Configuration section. 8 | void Configure(IConfigSection configSection); 9 | } 10 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/DependencyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyDepend 4 | { 5 | /// Allows automatical resolving of constructor/property dependency. 6 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Constructor)] 7 | public class DependencyAttribute : Attribute 8 | { 9 | /// Named type/instance in container. 10 | public string Name { get; private set; } 11 | 12 | /// Creates attribute. 13 | public DependencyAttribute() 14 | { 15 | } 16 | 17 | /// Allows definition of name of registered type. Used only for property injection. 18 | public DependencyAttribute(string name) 19 | { 20 | Name = name; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/DependencyException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyDepend 4 | { 5 | /// Used to highlight issues related to DI container flow. 6 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2240:ImplementISerializableCorrectly")] 7 | [Serializable] 8 | public class DependencyException : Exception 9 | { 10 | /// Creates . 11 | /// Exception message. 12 | /// Inner exception. 13 | public DependencyException(string message, Exception innerException) 14 | : base(message, innerException) { } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/Behaviors/ExecuteBehavior.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using UtyDepend.Utils; 3 | 4 | namespace UtyDepend.Interception.Behaviors 5 | { 6 | /// Executes method source method. 7 | public class ExecuteBehavior : IBehavior 8 | { 9 | /// Creates ExecuteBehavior. 10 | public ExecuteBehavior() 11 | { 12 | Name = "execute"; 13 | } 14 | 15 | /// 16 | public string Name { get; protected set; } 17 | 18 | /// 19 | public virtual IMethodReturn Invoke(MethodInvocation methodInvocation) 20 | { 21 | if (!methodInvocation.IsInvoked) 22 | { 23 | var methodBase = TypeHelper.GetMethodBySign(methodInvocation.Target.GetType(), 24 | methodInvocation.MethodBase, methodInvocation.GenericTypes.ToArray()); 25 | var result = methodBase.Invoke(methodInvocation.Target, methodInvocation.Parameters.Values.ToArray()); 26 | methodInvocation.IsInvoked = true; 27 | return methodInvocation.Return = new MethodReturn(result); 28 | } 29 | return methodInvocation.Return; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/Behaviors/IBehavior.cs: -------------------------------------------------------------------------------- 1 | namespace UtyDepend.Interception.Behaviors 2 | { 3 | /// Represents an additional behavior of method invocation. 4 | public interface IBehavior 5 | { 6 | /// The name of behavior. 7 | string Name { get; } 8 | 9 | /// Provides the way to attach additional behavior to method. 10 | IMethodReturn Invoke(MethodInvocation methodInvocation); 11 | } 12 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/IInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyDepend.Interception 4 | { 5 | /// Defines behavior of method interception. 6 | public interface IInterceptor 7 | { 8 | /// True, if type can be intercepted. 9 | bool CanIntercept(Type type); 10 | 11 | /// Return proxy for the type. 12 | IProxy CreateProxy(Type type, object instance); 13 | 14 | /// Registers component. 15 | void Register(Type type, Component component); 16 | 17 | /// Registers type. 18 | /// Type. 19 | void Register(Type type); 20 | 21 | /// Resolves component. 22 | Component Resolve(Type type); 23 | } 24 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/IMethodReturn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyDepend.Interception 4 | { 5 | /// Represents a result of method invocation. 6 | public interface IMethodReturn 7 | { 8 | /// Returns return value of method. 9 | object GetReturnValue(); 10 | 11 | /// Exception which occured during method invocation. 12 | Exception Exception { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/IProxy.cs: -------------------------------------------------------------------------------- 1 | using UtyDepend.Interception.Behaviors; 2 | 3 | namespace UtyDepend.Interception 4 | { 5 | /// Represents a behavior of proxy. 6 | public interface IProxy 7 | { 8 | /// Returns wrapped instance. 9 | object Instance { get; set; } 10 | 11 | /// Adds new behavior to wrapped instance. 12 | void AddBehavior(IBehavior behavior); 13 | 14 | /// Clear list of behaviors. 15 | void ClearBehaviors(); 16 | } 17 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/InterceptionContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace UtyDepend.Interception 6 | { 7 | /// Represents interception context which provide the way create proxy objects and interact with interceptors. 8 | internal static class InterceptionContext 9 | { 10 | private static readonly List Interceptors = new List(); 11 | 12 | static InterceptionContext() 13 | { 14 | Interceptors.Add(new InterfaceInterceptor()); 15 | } 16 | 17 | /// Creates proxy from interface type and instance. 18 | /// Interface type. 19 | /// Instance of implementation type. 20 | public static IProxy CreateProxy(Type type, object instance) 21 | { 22 | var interceptor = GetInterceptor(type); 23 | return interceptor != null ? interceptor.CreateProxy(type, instance) : null; 24 | } 25 | 26 | /// Gets first interceptor which can intercept type. 27 | public static IInterceptor GetInterceptor(Type type) 28 | { 29 | return Interceptors.SingleOrDefault(i => i.CanIntercept(type)); 30 | } 31 | 32 | /// Gets component for type from interceptor. 33 | public static Component GetComponent(Type type) 34 | { 35 | var interceptor = GetInterceptor(type); 36 | return interceptor != null ? interceptor.Resolve(type) : null; 37 | } 38 | 39 | /// Gets default interceptor. 40 | public static IInterceptor GetInterceptor() 41 | { 42 | return Interceptors.First(); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/InterfaceInterceptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UtyDepend.Interception.Behaviors; 4 | 5 | namespace UtyDepend.Interception 6 | { 7 | /// Represents interceptor which is able to intercept interface. 8 | internal class InterfaceInterceptor : IInterceptor 9 | { 10 | protected readonly Dictionary ProxyComponentMapping = new Dictionary(); 11 | protected readonly List Behaviors = new List(); 12 | 13 | /// 14 | public bool CanIntercept(Type type) 15 | { 16 | if (type == null) 17 | return false; 18 | return ProxyComponentMapping.ContainsKey(type) && ProxyComponentMapping[type].CanCreateProxy; 19 | } 20 | 21 | /// 22 | public Component Resolve(Type type) 23 | { 24 | //Resolve from mapping 25 | return ProxyComponentMapping[type]; 26 | } 27 | 28 | /// 29 | public IProxy CreateProxy(Type type, object instance) 30 | { 31 | var component = Resolve(type); 32 | var proxy = component.CreateProxy(instance, Behaviors); 33 | return proxy; 34 | } 35 | 36 | /// 37 | public void Register(Type type, Component component) 38 | { 39 | ProxyComponentMapping.Add(type, component); 40 | } 41 | 42 | /// 43 | public void Register(Type type) 44 | { 45 | throw new NotSupportedException("Platform specific feature is disabled."); 46 | //if (!ProxyComponentMapping.ContainsKey(type)) 47 | // ProxyComponentMapping.Add(type, new Component(type, ProxyGen.Generate(type))); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/MethodInvocation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace UtyDepend.Interception 6 | { 7 | /// Represents a call of method. 8 | public class MethodInvocation 9 | { 10 | /// Creates MethodInvocation. 11 | public MethodInvocation() 12 | { 13 | Parameters = new Dictionary(); 14 | InvocationContext = new Dictionary(); 15 | GenericTypes = new List(); 16 | } 17 | 18 | /// Executed method. 19 | public MethodBase MethodBase { get; set; } 20 | 21 | /// Input parameters. 22 | public IDictionary Parameters { get; private set; } 23 | 24 | /// Invocation context which can be used for passing parameters through bahavior chain. 25 | public IDictionary InvocationContext { get; private set; } 26 | 27 | /// Target instance. 28 | public object Target { get; set; } 29 | 30 | /// Should be set to true if method has been invoked. 31 | public bool IsInvoked { get; set; } 32 | 33 | /// Generic type list. 34 | public IList GenericTypes { get; set; } 35 | 36 | /// Wrapped return value. 37 | public IMethodReturn Return { get; set; } 38 | } 39 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/MethodReturn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyDepend.Interception 4 | { 5 | /// Represents a result of method invocation. 6 | public class MethodReturn : IMethodReturn 7 | { 8 | private readonly object _returnValue; 9 | 10 | /// Creates . 11 | /// Return value. 12 | public MethodReturn(object returnValue) 13 | { 14 | _returnValue = returnValue; 15 | } 16 | 17 | /// Returns return value of method. 18 | public object GetReturnValue() 19 | { 20 | return _returnValue; 21 | } 22 | 23 | /// Exception which occured during method invocation. 24 | public Exception Exception { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Interception/ProxyBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | using UtyDepend.Interception.Behaviors; 5 | 6 | namespace UtyDepend.Interception 7 | { 8 | /// Provides base functionality to proxy object. 9 | public class ProxyBase : IProxy 10 | { 11 | private readonly LinkedList _behaviors = new LinkedList(); 12 | 13 | /// 14 | public object Instance { get; set; } 15 | 16 | /// Adds behavior to behaviors' chain. 17 | /// 18 | public void AddBehavior(IBehavior behavior) 19 | { 20 | // NOTE due to the current IContainer implementation we should check this 21 | if (!_behaviors.Contains(behavior)) 22 | _behaviors.AddLast(behavior); 23 | } 24 | 25 | /// Build object from executed method. 26 | /// 27 | /// 28 | protected MethodInvocation BuildMethodInvocation(MethodBase methodBase, params object[] args) 29 | { 30 | MethodInvocation methodInvocation = new MethodInvocation {MethodBase = methodBase, Target = Instance}; 31 | var parameters = methodBase.GetParameters(); 32 | for (int i = 0; i < parameters.Length; i++) 33 | methodInvocation.Parameters.Add(parameters[i], args[i]); 34 | return methodInvocation; 35 | } 36 | 37 | /// Run behaviors' chain. 38 | /// 39 | /// 40 | protected IMethodReturn RunBehaviors(MethodInvocation methodInvocation) 41 | { 42 | IMethodReturn methodReturn = null; 43 | return _behaviors.Aggregate(methodReturn, (ac, b) => b.Invoke(methodInvocation)); 44 | } 45 | 46 | /// Clears list of behaviors. 47 | public void ClearBehaviors() 48 | { 49 | _behaviors.Clear(); 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Lifetime/ContainerLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using UtyDepend.Config; 4 | 5 | namespace UtyDepend.Lifetime 6 | { 7 | /// Keeps instance as long as container exists. 8 | internal class ContainerLifetimeManager : ILifetimeManager 9 | { 10 | private object _instance; 11 | 12 | public ContainerLifetimeManager(object instance) 13 | { 14 | _instance = instance; 15 | TargetType = instance.GetType(); 16 | } 17 | 18 | /// 19 | public Type InterfaceType { get; set; } 20 | 21 | /// 22 | public Type TargetType { get; set; } 23 | 24 | /// 25 | public bool NeedResolveCstorArgs { get; set; } 26 | 27 | /// 28 | public IConfigSection ConfigSection { get; set; } 29 | 30 | /// 31 | public object[] CstorArgs { get; set; } 32 | 33 | /// 34 | public ConstructorInfo Constructor { get; set; } 35 | 36 | /// Returns instance. 37 | public object GetInstance() 38 | { 39 | return _instance; 40 | } 41 | 42 | public object GetInstance(string name) 43 | { 44 | return GetInstance(); 45 | } 46 | 47 | /// 48 | public void Dispose() 49 | { 50 | Dispose(true); 51 | } 52 | 53 | /// 54 | protected virtual void Dispose(bool disposing) 55 | { 56 | if (disposing) 57 | _instance = null; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /utydepend/UtyDepend/Lifetime/ExternalLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyDepend.Config; 3 | 4 | namespace UtyDepend.Lifetime 5 | { 6 | /// Wraps already created instance using WeakReference object. 7 | internal class ExternalLifetimeManager : ILifetimeManager 8 | { 9 | private readonly WeakReference _reference; 10 | 11 | public ExternalLifetimeManager(object instance) 12 | { 13 | _reference = new WeakReference(instance); 14 | TargetType = instance.GetType(); 15 | } 16 | 17 | /// 18 | public Type InterfaceType { get; set; } 19 | 20 | /// 21 | public Type TargetType { get; set; } 22 | 23 | /// 24 | public bool NeedResolveCstorArgs { get; set; } 25 | 26 | /// 27 | public IConfigSection ConfigSection { get; set; } 28 | 29 | /// 30 | public object[] CstorArgs { get; set; } 31 | 32 | /// 33 | public System.Reflection.ConstructorInfo Constructor { get; set; } 34 | 35 | /// Returns instance if it exists. 36 | public object GetInstance() 37 | { 38 | if (_reference.IsAlive) 39 | return _reference.Target; 40 | throw new InvalidOperationException( 41 | String.Format("Registered object is dead! Type: {0}, interface: {1}", TargetType, InterfaceType)); 42 | } 43 | 44 | public object GetInstance(string name) 45 | { 46 | return GetInstance(); 47 | } 48 | 49 | public void Dispose() 50 | { 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Lifetime/ILifetimeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using UtyDepend.Config; 4 | 5 | namespace UtyDepend.Lifetime 6 | { 7 | /// 8 | /// Manages lifetime of object creation. 9 | /// 10 | public interface ILifetimeManager : IDisposable 11 | { 12 | /// 13 | /// Interface type. 14 | /// 15 | Type InterfaceType { get; set; } 16 | 17 | /// 18 | /// Target type. 19 | /// 20 | Type TargetType { get; set; } 21 | 22 | /// 23 | /// Constructor's signature. 24 | /// 25 | ConstructorInfo Constructor { get; set; } 26 | 27 | /// 28 | /// True if cstor args are types which should be resolved. 29 | /// 30 | bool NeedResolveCstorArgs { get; set; } 31 | 32 | /// 33 | /// Config section of object. 34 | /// 35 | IConfigSection ConfigSection { get; set; } 36 | 37 | /// 38 | /// Constructor's parameters. 39 | /// 40 | object[] CstorArgs { get; set; } 41 | 42 | /// 43 | /// Returns instance of the target type. 44 | /// 45 | object GetInstance(); 46 | 47 | /// 48 | /// Returns instance of the target type using name provided. 49 | /// 50 | object GetInstance(string name); 51 | } 52 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Lifetime/SingletonLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyDepend.Config; 3 | using UtyDepend.Interception; 4 | using UtyDepend.Utils; 5 | 6 | namespace UtyDepend.Lifetime 7 | { 8 | /// Creates singleton instance for wrapped type. 9 | internal class SingletonLifetimeManager : ILifetimeManager 10 | { 11 | /// 12 | public Type InterfaceType { get; set; } 13 | 14 | /// 15 | public Type TargetType { get; set; } 16 | 17 | /// 18 | public bool NeedResolveCstorArgs { get; set; } 19 | 20 | /// 21 | public IConfigSection ConfigSection { get; set; } 22 | 23 | /// 24 | public object[] CstorArgs { get; set; } 25 | 26 | /// 27 | public System.Reflection.ConstructorInfo Constructor { get; set; } 28 | 29 | private object _instance; 30 | private IProxy _proxy; 31 | 32 | /// 33 | public object GetInstance() 34 | { 35 | return GetInstance(String.Empty); 36 | } 37 | 38 | /// 39 | public object GetInstance(string name) 40 | { 41 | object target = _proxy ?? _instance; 42 | if (_instance == null) 43 | { 44 | _instance = (Constructor ?? TypeHelper.GetConstructor(TargetType, CstorArgs)) 45 | .Invoke(CstorArgs); 46 | _proxy = InterceptionContext.CreateProxy(InterfaceType, _instance); 47 | 48 | var configurable = _instance as IConfigurable; 49 | if (configurable != null && ConfigSection != null) 50 | configurable.Configure(ConfigSection); 51 | target = _proxy ?? _instance; 52 | // no need in this data anymore 53 | ConfigSection = null; 54 | CstorArgs = null; 55 | Constructor = null; 56 | } 57 | 58 | return target; 59 | } 60 | 61 | /// 62 | public void Dispose() 63 | { 64 | Dispose(true); 65 | } 66 | 67 | /// 68 | protected virtual void Dispose(bool disposing) 69 | { 70 | if (disposing) 71 | { 72 | var instance = _instance as IDisposable; 73 | if (instance != null) 74 | instance.Dispose(); 75 | _instance = null; 76 | } 77 | } 78 | } 79 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Lifetime/TransientLifetimeManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using UtyDepend.Config; 4 | using UtyDepend.Interception; 5 | using UtyDepend.Utils; 6 | 7 | namespace UtyDepend.Lifetime 8 | { 9 | /// Every time build a new instance. 10 | internal class TransientLifetimeManager : ILifetimeManager 11 | { 12 | /// 13 | public Type InterfaceType { get; set; } 14 | 15 | /// 16 | public Type TargetType { get; set; } 17 | 18 | /// 19 | public bool NeedResolveCstorArgs { get; set; } 20 | 21 | /// 22 | public IConfigSection ConfigSection { get; set; } 23 | 24 | /// 25 | public object[] CstorArgs { get; set; } 26 | 27 | /// 28 | public ConstructorInfo Constructor { get; set; } 29 | 30 | private ConstructorInfo _constructor; 31 | 32 | private ConstructorInfo ConstructorInstance 33 | { 34 | get 35 | { 36 | return _constructor = _constructor ?? (Constructor ?? TypeHelper.GetConstructor(TargetType, CstorArgs)); 37 | } 38 | } 39 | 40 | /// Returns new instance of the target type. 41 | public object GetInstance() 42 | { 43 | var instance = ConstructorInstance.Invoke(CstorArgs); 44 | var proxy = InterceptionContext.CreateProxy(InterfaceType, instance); 45 | 46 | var target = proxy ?? instance; 47 | var configurable = target as IConfigurable; 48 | if (configurable != null && ConfigSection != null) 49 | configurable.Configure(ConfigSection); 50 | return target; 51 | } 52 | 53 | /// Returns new instance of the target type. The name parameters isn't used. 54 | public object GetInstance(string name) 55 | { 56 | return GetInstance(); 57 | } 58 | 59 | public void Dispose() 60 | { 61 | Dispose(true); 62 | } 63 | 64 | protected virtual void Dispose(bool disposing) 65 | { 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /utydepend/UtyDepend/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UtyDepend")] 9 | [assembly: AssemblyDescription("Simple dependency injection container.")] 10 | [assembly: AssemblyProduct("UtyDepend")] 11 | [assembly: AssemblyCopyright("Copyright © Ilya Builuk, 2011-2016")] 12 | 13 | // Setting ComVisible to false makes the types in this assembly not visible 14 | // to COM components. If you need to access a type in this assembly from 15 | // COM, set the ComVisible attribute to true on that type. 16 | [assembly: ComVisible(false)] 17 | 18 | // The following GUID is for the ID of the typelib if this project is exposed to COM 19 | [assembly: Guid("641536c5-40dd-471e-b7c2-115ed900cbe2")] 20 | 21 | [assembly: AssemblyVersion("1.0.*")] 22 | [assembly: AssemblyFileVersion("1.0.*")] 23 | 24 | [assembly: InternalsVisibleTo("UtyDepend.Tests")] 25 | -------------------------------------------------------------------------------- /utydepend/UtyDepend/Utils/Guard.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyDepend.Utils 4 | { 5 | internal static class Guard 6 | { 7 | public static void IsNotNull(object o, string name, string message) 8 | { 9 | if (o == null) 10 | throw new ArgumentException(message, name); 11 | } 12 | 13 | public static void IsNull(object o, string name, string message) 14 | { 15 | if (o != null) 16 | throw new ArgumentNullException(message, name); 17 | } 18 | 19 | public static void IsAssignableFrom(Type baseType, Type targetType) 20 | { 21 | if (!baseType.IsAssignableFrom(targetType)) 22 | throw new InvalidOperationException(String.Format("{0} cannot be assigned from {1}", 23 | targetType == null ? "" : targetType.ToString(), baseType)); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /utydepend/UtyDepend/Utils/TypeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | 5 | namespace UtyDepend.Utils 6 | { 7 | internal static class TypeHelper 8 | { 9 | public static ConstructorInfo GetConstructor(Type type, object[] cstorArgs) 10 | { 11 | var constructor = type.GetConstructor(cstorArgs.Select(a => a.GetType()).ToArray()); 12 | Guard.IsNotNull(constructor, "constructor", 13 | String.Format("Unable to find appropriate constructor of type: {0}", type)); 14 | return constructor; 15 | } 16 | 17 | public static ConstructorInfo GetConstructor(Type type, Type[] cstorSignature) 18 | { 19 | var constructor = type.GetConstructor(cstorSignature); 20 | //Guard.IsNotNull(constructor, "constructor", 21 | // String.Format("Unable to find appropriate constructor of type: {0}", type)); 22 | return constructor; 23 | } 24 | 25 | public static ConstructorInfo GetConstructor(Type type, Type attribute) 26 | { 27 | if (type.GetConstructors().Any(c => c.GetCustomAttributes(attribute, true).Any())) 28 | 29 | return type.GetConstructors().Single( 30 | c => c.GetCustomAttributes(typeof(DependencyAttribute), true).Any()); 31 | return null; 32 | } 33 | 34 | public static MethodBase GetMethodBySign(Type target, MethodBase sign, params Type[] genericTypes) 35 | { 36 | var signParameters = sign.GetParameters(); 37 | foreach (var methodInfo in target.GetMethods()) 38 | { 39 | if (methodInfo.Name == sign.Name) 40 | { 41 | var parameters = methodInfo.GetParameters(); 42 | if (signParameters.Length == parameters.Length) 43 | { 44 | var found = !signParameters.Where((t, i) => t.ParameterType != parameters[i].ParameterType).Any(); 45 | if (found) 46 | { 47 | if(methodInfo.IsGenericMethod) 48 | return GetGenericMethod(methodInfo, genericTypes); 49 | return methodInfo; 50 | } 51 | } 52 | } 53 | } 54 | 55 | return null; 56 | } 57 | 58 | public static MethodBase GetGenericMethod(MethodInfo method, params Type[] genericTypes) 59 | { 60 | return method.MakeGenericMethod(genericTypes); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /utydepend/UtyDepend/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /utyrx/README.md: -------------------------------------------------------------------------------- 1 |

UtyRx: a Reactive Extensions fork

2 | 3 | The fork is based on UniRx project which is Unity3D specific fork. 4 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Observable/Observable.ErrorHandlingTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using NUnit.Framework; 4 | 5 | namespace UtyRx.Tests.Observable 6 | { 7 | [TestFixture] 8 | public class ErrorHandlingTest 9 | { 10 | [Test] 11 | public void Finally() 12 | { 13 | var called = false; 14 | try 15 | { 16 | UtyRx.Observable.Range(1, 10, Scheduler.Immediate) 17 | .Do(x => { throw new Exception(); }) 18 | .Finally(() => called = true) 19 | .Subscribe(); 20 | } 21 | catch 22 | { 23 | } 24 | finally 25 | { 26 | called.IsTrue(); 27 | } 28 | } 29 | 30 | [Test] 31 | public void Catch() 32 | { 33 | var xs = UtyRx.Observable.Return(2, Scheduler.ThreadPool).Concat(UtyRx.Observable.Throw(new InvalidOperationException())) 34 | .Catch((InvalidOperationException ex) => 35 | { 36 | return UtyRx.Observable.Range(1, 3); 37 | }) 38 | .ToArrayWait(); 39 | 40 | xs.IsCollection(2, 1, 2, 3); 41 | } 42 | 43 | [Test] 44 | public void CatchEnumerable() 45 | { 46 | { 47 | var xs = new[] 48 | { 49 | UtyRx.Observable.Return(2).Concat(UtyRx.Observable.Throw(new Exception())), 50 | UtyRx.Observable.Return(99).Concat(UtyRx.Observable.Throw(new Exception())), 51 | UtyRx.Observable.Range(10,2) 52 | } 53 | .Catch() 54 | .Materialize() 55 | .ToArrayWait(); 56 | 57 | xs[0].Value.Is(2); 58 | xs[1].Value.Is(99); 59 | xs[2].Value.Is(10); 60 | xs[3].Value.Is(11); 61 | xs[4].Kind.Is(NotificationKind.OnCompleted); 62 | } 63 | { 64 | var xs = new[] 65 | { 66 | UtyRx.Observable.Return(2).Concat(UtyRx.Observable.Throw(new Exception())), 67 | UtyRx.Observable.Return(99).Concat(UtyRx.Observable.Throw(new Exception())) 68 | } 69 | .Catch() 70 | .Materialize() 71 | .ToArrayWait(); 72 | 73 | xs[0].Value.Is(2); 74 | xs[1].Value.Is(99); 75 | xs[2].Kind.Is(NotificationKind.OnError); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/AggregateTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using NUnit.Framework; 4 | 5 | namespace UtyRx.Tests.Operators 6 | { 7 | [TestFixture] 8 | public class AggregateTest 9 | { 10 | [Test] 11 | public void Scan() 12 | { 13 | var range = UtyRx.Observable.Range(1, 5); 14 | 15 | range.Scan((x, y) => x + y).ToArrayWait().IsCollection(1, 3, 6, 10, 15); 16 | range.Scan(100, (x, y) => x + y).ToArrayWait().IsCollection(101, 103, 106, 110, 115); 17 | 18 | UtyRx.Observable.Empty().Scan((x, y) => x + y).ToArrayWait().IsCollection(); 19 | UtyRx.Observable.Empty().Scan(100, (x, y) => x + y).ToArrayWait().IsCollection(); 20 | } 21 | 22 | [Test] 23 | public void Aggregate() 24 | { 25 | AssertEx.Throws(() => UtyRx.Observable.Empty().Aggregate((x, y) => x + y).Wait()); 26 | UtyRx.Observable.Range(1, 5).Aggregate((x, y) => x + y).Wait().Is(15); 27 | 28 | UtyRx.Observable.Empty().Aggregate(100, (x, y) => x + y).Wait().Is(100); 29 | UtyRx.Observable.Range(1, 5).Aggregate(100, (x, y) => x + y).Wait().Is(115); 30 | 31 | UtyRx.Observable.Empty().Aggregate(100, (x, y) => x + y, x => x + x).Wait().Is(200); 32 | UtyRx.Observable.Range(1, 5).Aggregate(100, (x, y) => x + y, x => x + x).Wait().Is(230); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/ContinueWithTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | using NUnit.Framework; 6 | 7 | namespace UtyRx.Tests.Operators 8 | { 9 | [TestFixture] 10 | public class ContinueWithTest 11 | { 12 | [TestFixtureSetUp] 13 | public void SetUp() 14 | { 15 | Scheduler.MainThread = Scheduler.CurrentThread; 16 | } 17 | 18 | [Test] 19 | public void ContinueWith() 20 | { 21 | var subject = new Subject(); 22 | 23 | var record = subject.ContinueWith(x => UtyRx.Observable.Return(x)).Record(); 24 | 25 | subject.OnNext(10); 26 | record.Values.Count.Is(0); 27 | 28 | subject.OnNext(100); 29 | record.Values.Count.Is(0); 30 | 31 | subject.OnCompleted(); 32 | record.Values[0].Is(100); 33 | record.Notifications.Last().Kind.Is(NotificationKind.OnCompleted); 34 | } 35 | 36 | [Test] 37 | public void ContinueWith2() 38 | { 39 | var subject = new Subject(); 40 | 41 | var record = subject.ContinueWith(x => UtyRx.Observable.Return(x).Delay(TimeSpan.FromMilliseconds(100))).Record(); 42 | 43 | subject.OnNext(10); 44 | record.Values.Count.Is(0); 45 | 46 | subject.OnNext(100); 47 | record.Values.Count.Is(0); 48 | 49 | subject.OnCompleted(); 50 | Thread.Sleep(TimeSpan.FromMilliseconds(200)); 51 | record.Values[0].Is(100); 52 | record.Notifications.Last().Kind.Is(NotificationKind.OnCompleted); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/ConversionTest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using NUnit.Framework; 5 | 6 | namespace UtyRx.Tests.Operators 7 | { 8 | [TestFixture] 9 | public class ConversionTest 10 | { 11 | [Test] 12 | public void AsObservable() 13 | { 14 | UtyRx.Observable.Range(1, 10).AsObservable().ToArrayWait().IsCollection(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 15 | } 16 | 17 | [Test] 18 | public void AsSingleUnitObservable() 19 | { 20 | var subject = new Subject(); 21 | 22 | var done = false; 23 | subject.AsSingleUnitObservable().Subscribe(_ => done = true); 24 | 25 | subject.OnNext(1); 26 | done.IsFalse(); 27 | subject.OnNext(100); 28 | done.IsFalse(); 29 | subject.OnCompleted(); 30 | done.IsTrue(); 31 | } 32 | 33 | [Test] 34 | public void AsUnitObservable() 35 | { 36 | UtyRx.Observable.Range(1, 3) 37 | .AsUnitObservable() 38 | .ToArrayWait() 39 | .IsCollection(Unit.Default, Unit.Default, Unit.Default); 40 | } 41 | 42 | [Test] 43 | public void Cast() 44 | { 45 | UtyRx.Observable.Range(1, 3).Cast().ToArrayWait().IsCollection(1, 2, 3); 46 | } 47 | 48 | [Test] 49 | public void OfType() 50 | { 51 | var subject = new Subject(); 52 | 53 | var list = new List(); 54 | subject.OfType(default(int)).Subscribe(x => list.Add(x)); 55 | 56 | subject.OnNext(1); 57 | subject.OnNext(2); 58 | subject.OnNext("hogehoge"); 59 | subject.OnNext(3); 60 | 61 | list.IsCollection(1, 2, 3); 62 | } 63 | 64 | [Test] 65 | public void ToObservable() 66 | { 67 | Enumerable.Range(1, 3).ToObservable(Scheduler.CurrentThread).ToArrayWait().IsCollection(1, 2, 3); 68 | Enumerable.Range(1, 3).ToObservable(Scheduler.ThreadPool).ToArrayWait().IsCollection(1, 2, 3); 69 | Enumerable.Range(1, 3).ToObservable(Scheduler.Immediate).ToArrayWait().IsCollection(1, 2, 3); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/RangeTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using NUnit.Framework; 4 | 5 | namespace UtyRx.Tests.Operators 6 | { 7 | [TestFixture] 8 | public class RangeTest 9 | { 10 | [Test] 11 | public void Range() 12 | { 13 | AssertEx.Throws(() => UtyRx.Observable.Range(1, -1).ToArray().Wait()); 14 | 15 | UtyRx.Observable.Range(1, 0).ToArray().Wait().Length.Is(0); 16 | UtyRx.Observable.Range(1, 10).ToArray().Wait().IsCollection(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 17 | 18 | UtyRx.Observable.Range(1, 0, Scheduler.Immediate).ToArray().Wait().Length.Is(0); 19 | UtyRx.Observable.Range(1, 10, Scheduler.Immediate).ToArray().Wait().IsCollection(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/TakeTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.VisualStudio.TestTools.UnitTesting; 3 | using NUnit.Framework; 4 | 5 | namespace UtyRx.Tests.Operators 6 | { 7 | [TestFixture] 8 | public class TakeTest 9 | { 10 | [Test] 11 | public void TakeCount() 12 | { 13 | var range = UtyRx.Observable.Range(1, 10); 14 | 15 | AssertEx.Throws(() => range.Take(-1)); 16 | 17 | range.Take(0).ToArray().Wait().Length.Is(0); 18 | 19 | range.Take(3).ToArrayWait().IsCollection(1, 2, 3); 20 | range.Take(15).ToArrayWait().IsCollection(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/ToTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using NUnit.Framework; 3 | 4 | namespace UtyRx.Tests.Operators 5 | { 6 | [TestFixture] 7 | public class ToTest 8 | { 9 | [Test] 10 | public void ToArray() 11 | { 12 | UtyRx.Observable.Empty().ToArray().Wait().IsCollection(); 13 | UtyRx.Observable.Return(10).ToArray().Wait().IsCollection(10); 14 | UtyRx.Observable.Range(1, 10).ToArray().Wait().IsCollection(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 15 | } 16 | 17 | [Test] 18 | public void ToList() 19 | { 20 | UtyRx.Observable.Empty().ToList().Wait().IsCollection(); 21 | UtyRx.Observable.Return(10).ToList().Wait().IsCollection(10); 22 | UtyRx.Observable.Range(1, 10).ToList().Wait().IsCollection(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Operators/WhenAllTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using NUnit.Framework; 5 | 6 | namespace UtyRx.Tests.Operators 7 | { 8 | [TestFixture] 9 | public class WhenAllTest 10 | { 11 | [Test] 12 | public void WhenAllEmpty() 13 | { 14 | var xs = UtyRx.Observable.WhenAll(new IObservable[0]).Wait(); 15 | xs.Length.Is(0); 16 | 17 | var xs2 = UtyRx.Observable.WhenAll(Enumerable.Empty>().Select(x => x)).Wait(); 18 | xs2.Length.Is(0); 19 | } 20 | 21 | [Test] 22 | public void WhenAll() 23 | { 24 | var xs = UtyRx.Observable.WhenAll( 25 | UtyRx.Observable.Return(100), 26 | UtyRx.Observable.Timer(TimeSpan.FromSeconds(1)).Select(_ => 5), 27 | UtyRx.Observable.Range(1, 4)) 28 | .Wait(); 29 | 30 | xs.IsCollection(100, 5, 4); 31 | } 32 | 33 | [Test] 34 | public void WhenAllEnumerable() 35 | { 36 | var xs = new[] { 37 | UtyRx.Observable.Return(100), 38 | UtyRx.Observable.Timer(TimeSpan.FromSeconds(1)).Select(_ => 5), 39 | UtyRx.Observable.Range(1, 4) 40 | }.Select(x => x).WhenAll().Wait(); 41 | 42 | xs.IsCollection(100, 5, 4); 43 | } 44 | 45 | [Test] 46 | public void WhenAllUnitEmpty() 47 | { 48 | var xs = UtyRx.Observable.WhenAll(new IObservable[0]).Wait(); 49 | xs.Is(Unit.Default); 50 | 51 | var xs2 = UtyRx.Observable.WhenAll(Enumerable.Empty>().Select(x => x)).Wait(); 52 | xs2.Is(Unit.Default); 53 | } 54 | 55 | [Test] 56 | public void WhenAllUnit() 57 | { 58 | var xs = UtyRx.Observable.WhenAll( 59 | UtyRx.Observable.Return(100).AsUnitObservable(), 60 | UtyRx.Observable.Timer(TimeSpan.FromSeconds(1)).AsUnitObservable(), 61 | UtyRx.Observable.Range(1, 4).AsUnitObservable()) 62 | .Wait(); 63 | 64 | xs.Is(Unit.Default); 65 | } 66 | 67 | [Test] 68 | public void WhenAllUnitEnumerable() 69 | { 70 | var xs = new[] { 71 | UtyRx.Observable.Return(100).AsUnitObservable(), 72 | UtyRx.Observable.Timer(TimeSpan.FromSeconds(1)).AsUnitObservable(), 73 | UtyRx.Observable.Range(1, 4).AsUnitObservable() 74 | }.Select(x => x).WhenAll().Wait(); 75 | 76 | xs.Is(Unit.Default); 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UtyRx.Tests")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UtyRx.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("5f034612-0e0e-490c-bc88-70b1ddc46f61")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Schedulers/SchedulerTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using NUnit.Framework; 5 | 6 | namespace UtyRx.Tests.Schedulers 7 | { 8 | [TestFixture] 9 | public class SchedulerTest 10 | { 11 | private static string[] ScheduleTasks(IScheduler scheduler) 12 | { 13 | var list = new List(); 14 | 15 | Action leafAction = () => list.Add("----leafAction."); 16 | Action innerAction = () => 17 | { 18 | list.Add("--innerAction start."); 19 | scheduler.Schedule(leafAction); 20 | list.Add("--innerAction end."); 21 | }; 22 | Action outerAction = () => 23 | { 24 | list.Add("outer start."); 25 | scheduler.Schedule(innerAction); 26 | list.Add("outer end."); 27 | }; 28 | scheduler.Schedule(outerAction); 29 | 30 | return list.ToArray(); 31 | } 32 | 33 | [Test] 34 | public void CurrentThread() 35 | { 36 | var hoge = ScheduleTasks(Scheduler.CurrentThread); 37 | hoge.IsCollection("outer start.", "outer end.", "--innerAction start.", "--innerAction end.", "----leafAction."); 38 | } 39 | [Test] 40 | public void CurrentThread2() 41 | { 42 | var scheduler = Scheduler.CurrentThread; 43 | 44 | var list = new List(); 45 | scheduler.Schedule(() => 46 | { 47 | list.Add("one"); 48 | 49 | scheduler.Schedule(TimeSpan.FromSeconds(3), () => 50 | { 51 | list.Add("after 3"); 52 | }); 53 | 54 | scheduler.Schedule(TimeSpan.FromSeconds(1), () => 55 | { 56 | list.Add("after 1"); 57 | }); 58 | }); 59 | 60 | list.IsCollection("one", "after 1", "after 3"); 61 | } 62 | 63 | [Test] 64 | public void CurrentThread3() 65 | { 66 | var scheduler = Scheduler.CurrentThread; 67 | 68 | var list = new List(); 69 | scheduler.Schedule(() => 70 | { 71 | list.Add("one"); 72 | 73 | var cancel = scheduler.Schedule(TimeSpan.FromSeconds(3), () => 74 | { 75 | list.Add("after 3"); 76 | }); 77 | 78 | scheduler.Schedule(TimeSpan.FromSeconds(1), () => 79 | { 80 | list.Add("after 1"); 81 | cancel.Dispose(); 82 | }); 83 | }); 84 | 85 | list.IsCollection("one", "after 1"); 86 | } 87 | 88 | [Test] 89 | public void Immediate() 90 | { 91 | var hoge = ScheduleTasks(Scheduler.Immediate); 92 | hoge.IsCollection("outer start.", "--innerAction start.", "----leafAction.", "--innerAction end.", "outer end."); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/Utils/TestUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx.Tests 5 | { 6 | public static class TestUtil 7 | { 8 | public static T[] ToArrayWait(this IObservable source) 9 | { 10 | return source.ToArray().Wait(); 11 | } 12 | 13 | public static RecordObserver Record(this IObservable source) 14 | { 15 | var d = new SingleAssignmentDisposable(); 16 | var observer = new RecordObserver(d); 17 | d.Disposable = source.Subscribe(observer); 18 | 19 | return observer; 20 | } 21 | } 22 | 23 | public class RecordObserver : IObserver 24 | { 25 | readonly object gate = new object(); 26 | readonly IDisposable subscription; 27 | 28 | public List Values { get; set; } 29 | public List> Notifications { get; set; } 30 | 31 | public RecordObserver(IDisposable subscription) 32 | { 33 | this.subscription = subscription; 34 | this.Values = new List(); 35 | this.Notifications = new List>(); 36 | } 37 | 38 | public void DisposeSubscription() 39 | { 40 | subscription.Dispose(); 41 | } 42 | 43 | void IObserver.OnNext(T value) 44 | { 45 | lock (gate) 46 | { 47 | Values.Add(value); 48 | Notifications.Add(Notification.CreateOnNext(value)); 49 | } 50 | } 51 | 52 | void IObserver.OnError(Exception error) 53 | { 54 | lock (gate) 55 | { 56 | Notifications.Add(Notification.CreateOnError(error)); 57 | } 58 | } 59 | void IObserver.OnCompleted() 60 | { 61 | lock (gate) 62 | { 63 | Notifications.Add(Notification.CreateOnCompleted()); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /utyrx/UtyRx.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /utyrx/UtyRx.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30324.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtyRx", "UtyRx\UtyRx.csproj", "{F87BCE71-0567-4FE1-83A3-2FD21EA8CD17}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UtyRx.Tests", "UtyRx.Tests\UtyRx.Tests.csproj", "{D05558D9-A9C2-4B1B-85AD-7973F3373114}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {F87BCE71-0567-4FE1-83A3-2FD21EA8CD17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {F87BCE71-0567-4FE1-83A3-2FD21EA8CD17}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {F87BCE71-0567-4FE1-83A3-2FD21EA8CD17}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {F87BCE71-0567-4FE1-83A3-2FD21EA8CD17}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {D05558D9-A9C2-4B1B-85AD-7973F3373114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {D05558D9-A9C2-4B1B-85AD-7973F3373114}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {D05558D9-A9C2-4B1B-85AD-7973F3373114}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {D05558D9-A9C2-4B1B-85AD-7973F3373114}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Asynchronous/WebRequestExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Text; 7 | using System.Threading; 8 | 9 | namespace UtyRx 10 | { 11 | public static class WebRequestExtensions 12 | { 13 | static IObservable AbortableDeferredAsyncRequest(Func begin, Func end, WebRequest request) 14 | { 15 | var result = Observable.Create(observer => 16 | { 17 | var isCompleted = -1; 18 | var subscription = Observable.FromAsyncPattern(begin, 19 | ar => 20 | { 21 | try 22 | { 23 | Interlocked.Increment(ref isCompleted); 24 | return end(ar); 25 | } 26 | catch (WebException ex) 27 | { 28 | if (ex.Status == WebExceptionStatus.RequestCanceled) return default(TResult); 29 | throw; 30 | } 31 | })() 32 | .Subscribe(observer); 33 | return Disposable.Create(() => 34 | { 35 | if (Interlocked.Increment(ref isCompleted) == 0) 36 | { 37 | subscription.Dispose(); 38 | request.Abort(); 39 | } 40 | }); 41 | }); 42 | 43 | return result; 44 | } 45 | 46 | public static IObservable GetResponseAsObservable(this WebRequest request) 47 | { 48 | return AbortableDeferredAsyncRequest(request.BeginGetResponse, request.EndGetResponse, request); 49 | } 50 | 51 | public static IObservable GetResponseAsObservable(this HttpWebRequest request) 52 | { 53 | return AbortableDeferredAsyncRequest(request.BeginGetResponse, ar => (HttpWebResponse)request.EndGetResponse(ar), request); 54 | } 55 | 56 | public static IObservable GetRequestStreamAsObservable(this WebRequest request) 57 | { 58 | return AbortableDeferredAsyncRequest(request.BeginGetRequestStream, request.EndGetRequestStream, request); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/BooleanDisposable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | namespace UtyRx 5 | { 6 | public class BooleanDisposable : IDisposable, ICancelable 7 | { 8 | public bool IsDisposed { get; private set; } 9 | 10 | public BooleanDisposable() 11 | { 12 | 13 | } 14 | 15 | internal BooleanDisposable(bool isDisposed) 16 | { 17 | IsDisposed = isDisposed; 18 | } 19 | 20 | public void Dispose() 21 | { 22 | if (!IsDisposed) IsDisposed = true; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/Disposable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | namespace UtyRx 5 | { 6 | public static class Disposable 7 | { 8 | public static readonly IDisposable Empty = EmptyDisposable.Singleton; 9 | 10 | public static IDisposable Create(Action disposeAction) 11 | { 12 | return new AnonymousDisposable(disposeAction); 13 | } 14 | 15 | public static IDisposable CreateWithState(TState state, Action disposeAction) 16 | { 17 | return new AnonymousDisposable(state, disposeAction); 18 | } 19 | 20 | class EmptyDisposable : IDisposable 21 | { 22 | public static EmptyDisposable Singleton = new EmptyDisposable(); 23 | 24 | private EmptyDisposable() 25 | { 26 | 27 | } 28 | 29 | public void Dispose() 30 | { 31 | } 32 | } 33 | 34 | class AnonymousDisposable : IDisposable 35 | { 36 | bool isDisposed = false; 37 | readonly Action dispose; 38 | 39 | public AnonymousDisposable(Action dispose) 40 | { 41 | this.dispose = dispose; 42 | } 43 | 44 | public void Dispose() 45 | { 46 | if (!isDisposed) 47 | { 48 | isDisposed = true; 49 | dispose(); 50 | } 51 | } 52 | } 53 | 54 | class AnonymousDisposable : IDisposable 55 | { 56 | bool isDisposed = false; 57 | readonly T state; 58 | readonly Action dispose; 59 | 60 | public AnonymousDisposable(T state, Action dispose) 61 | { 62 | this.state = state; 63 | this.dispose = dispose; 64 | } 65 | 66 | public void Dispose() 67 | { 68 | if (!isDisposed) 69 | { 70 | isDisposed = true; 71 | dispose(state); 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/DisposableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx 5 | { 6 | public static partial class DisposableExtensions 7 | { 8 | /// Add disposable(self) to CompositeDisposable(or other ICollection). Return value is self disposable. 9 | public static T AddTo(this T disposable, ICollection container) 10 | where T : IDisposable 11 | { 12 | if (disposable == null) throw new ArgumentNullException("disposable"); 13 | if (container == null) throw new ArgumentNullException("container"); 14 | 15 | container.Add(disposable); 16 | 17 | return disposable; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/ICancelable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace UtyRx 6 | { 7 | public interface ICancelable : IDisposable 8 | { 9 | bool IsDisposed { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/MultipleAssignmentDisposable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | namespace UtyRx 5 | { 6 | public class MultipleAssignmentDisposable : IDisposable, ICancelable 7 | { 8 | static readonly BooleanDisposable True = new BooleanDisposable(true); 9 | 10 | object gate = new object(); 11 | IDisposable current; 12 | 13 | public bool IsDisposed 14 | { 15 | get 16 | { 17 | lock (gate) 18 | { 19 | return current == True; 20 | } 21 | } 22 | } 23 | 24 | public IDisposable Disposable 25 | { 26 | get 27 | { 28 | lock (gate) 29 | { 30 | return (current == True) 31 | ? UtyRx.Disposable.Empty 32 | : current; 33 | } 34 | } 35 | set 36 | { 37 | var shouldDispose = false; 38 | lock (gate) 39 | { 40 | shouldDispose = (current == True); 41 | if (!shouldDispose) 42 | { 43 | current = value; 44 | } 45 | } 46 | if (shouldDispose && value != null) 47 | { 48 | value.Dispose(); 49 | } 50 | } 51 | } 52 | 53 | public void Dispose() 54 | { 55 | IDisposable old = null; 56 | 57 | lock (gate) 58 | { 59 | if (current != True) 60 | { 61 | old = current; 62 | current = True; 63 | } 64 | } 65 | 66 | if (old != null) old.Dispose(); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/ScheduledDisposable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace UtyRx 5 | { 6 | public sealed class ScheduledDisposable : ICancelable 7 | { 8 | private readonly IScheduler scheduler; 9 | private volatile IDisposable disposable; 10 | private int isDisposed = 0; 11 | 12 | public ScheduledDisposable(IScheduler scheduler, IDisposable disposable) 13 | { 14 | this.scheduler = scheduler; 15 | this.disposable = disposable; 16 | } 17 | 18 | public IScheduler Scheduler 19 | { 20 | get { return scheduler; } 21 | } 22 | 23 | public IDisposable Disposable 24 | { 25 | get { return disposable; } 26 | } 27 | 28 | public bool IsDisposed 29 | { 30 | get { return isDisposed != 0; } 31 | } 32 | 33 | public void Dispose() 34 | { 35 | Scheduler.Schedule(DisposeInner); 36 | } 37 | 38 | private void DisposeInner() 39 | { 40 | if (Interlocked.Increment(ref isDisposed) == 1) 41 | { 42 | disposable.Dispose(); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/SerialDisposable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | namespace UtyRx 5 | { 6 | public class SerialDisposable : IDisposable, ICancelable 7 | { 8 | readonly object gate = new object(); 9 | IDisposable current; 10 | bool disposed; 11 | 12 | public bool IsDisposed { get { lock (gate) { return disposed; } } } 13 | 14 | public IDisposable Disposable 15 | { 16 | get 17 | { 18 | return current; 19 | } 20 | set 21 | { 22 | var shouldDispose = false; 23 | var old = default(IDisposable); 24 | lock (gate) 25 | { 26 | shouldDispose = disposed; 27 | if (!shouldDispose) 28 | { 29 | old = current; 30 | current = value; 31 | } 32 | } 33 | if (old != null) 34 | { 35 | old.Dispose(); 36 | } 37 | if (shouldDispose && value != null) 38 | { 39 | value.Dispose(); 40 | } 41 | } 42 | } 43 | 44 | public void Dispose() 45 | { 46 | var old = default(IDisposable); 47 | 48 | lock (gate) 49 | { 50 | if (!disposed) 51 | { 52 | disposed = true; 53 | old = current; 54 | current = null; 55 | } 56 | } 57 | 58 | if (old != null) 59 | { 60 | old.Dispose(); 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Disposables/SingleAssignmentDisposable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | 4 | namespace UtyRx 5 | { 6 | // should be use Interlocked.CompareExchange for Threadsafe? 7 | // but CompareExchange cause ExecutionEngineException on iOS. 8 | // AOT... 9 | // use lock instead 10 | 11 | public class SingleAssignmentDisposable : IDisposable, ICancelable 12 | { 13 | readonly object gate = new object(); 14 | IDisposable current; 15 | bool disposed; 16 | 17 | public bool IsDisposed { get { lock (gate) { return disposed; } } } 18 | 19 | public IDisposable Disposable 20 | { 21 | get 22 | { 23 | return current; 24 | } 25 | set 26 | { 27 | var old = default(IDisposable); 28 | bool alreadyDisposed; 29 | lock (gate) 30 | { 31 | alreadyDisposed = disposed; 32 | old = current; 33 | if (!alreadyDisposed) 34 | { 35 | if (value == null) return; 36 | current = value; 37 | } 38 | } 39 | 40 | if (alreadyDisposed && value != null) 41 | { 42 | value.Dispose(); 43 | return; 44 | } 45 | 46 | if (old != null) throw new InvalidOperationException("Disposable is already set"); 47 | } 48 | } 49 | 50 | 51 | public void Dispose() 52 | { 53 | IDisposable old = null; 54 | 55 | lock (gate) 56 | { 57 | if (!disposed) 58 | { 59 | disposed = true; 60 | old = current; 61 | current = null; 62 | } 63 | } 64 | 65 | if (old != null) old.Dispose(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/InternalUtil/AscynLock.cs: -------------------------------------------------------------------------------- 1 | // this code is borrowed from RxOfficial(rx.codeplex.com) and modified 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | namespace UtyRx.InternalUtil 7 | { 8 | /// 9 | /// Asynchronous lock. 10 | /// 11 | internal sealed class AsyncLock : IDisposable 12 | { 13 | private readonly Queue queue = new Queue(); 14 | private bool isAcquired = false; 15 | private bool hasFaulted = false; 16 | 17 | /// 18 | /// Queues the action for execution. If the caller acquires the lock and becomes the owner, 19 | /// the queue is processed. If the lock is already owned, the action is queued and will get 20 | /// processed by the owner. 21 | /// 22 | /// Action to queue for execution. 23 | /// is null. 24 | public void Wait(Action action) 25 | { 26 | if (action == null) 27 | throw new ArgumentNullException("action"); 28 | 29 | var isOwner = false; 30 | lock (queue) 31 | { 32 | if (!hasFaulted) 33 | { 34 | queue.Enqueue(action); 35 | isOwner = !isAcquired; 36 | isAcquired = true; 37 | } 38 | } 39 | 40 | if (isOwner) 41 | { 42 | while (true) 43 | { 44 | var work = default(Action); 45 | lock (queue) 46 | { 47 | if (queue.Count > 0) 48 | work = queue.Dequeue(); 49 | else 50 | { 51 | isAcquired = false; 52 | break; 53 | } 54 | } 55 | 56 | try 57 | { 58 | work(); 59 | } 60 | catch 61 | { 62 | lock (queue) 63 | { 64 | queue.Clear(); 65 | hasFaulted = true; 66 | } 67 | throw; 68 | } 69 | } 70 | } 71 | } 72 | 73 | /// 74 | /// Clears the work items in the queue and drops further work being queued. 75 | /// 76 | public void Dispose() 77 | { 78 | lock (queue) 79 | { 80 | queue.Clear(); 81 | hasFaulted = true; 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /utyrx/UtyRx/InternalUtil/ImmutableList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.InternalUtil 4 | { 5 | public class ImmutableList 6 | { 7 | public static readonly ImmutableList Empty = new ImmutableList(); 8 | 9 | T[] data; 10 | 11 | public T[] Data 12 | { 13 | get { return data; } 14 | } 15 | 16 | ImmutableList() 17 | { 18 | data = new T[0]; 19 | } 20 | 21 | public ImmutableList(T[] data) 22 | { 23 | this.data = data; 24 | } 25 | 26 | public ImmutableList Add(T value) 27 | { 28 | var newData = new T[data.Length + 1]; 29 | Array.Copy(data, newData, data.Length); 30 | newData[data.Length] = value; 31 | return new ImmutableList(newData); 32 | } 33 | 34 | public ImmutableList Remove(T value) 35 | { 36 | var i = IndexOf(value); 37 | if (i < 0) return this; 38 | 39 | var length = data.Length; 40 | if (length == 1) return Empty; 41 | 42 | var newData = new T[length - 1]; 43 | 44 | Array.Copy(data, 0, newData, 0, i); 45 | Array.Copy(data, i + 1, newData, i, length - i - 1); 46 | 47 | return new ImmutableList(newData); 48 | } 49 | 50 | public int IndexOf(T value) 51 | { 52 | for (var i = 0; i < data.Length; ++i) 53 | { 54 | // ImmutableList only use for IObserver(no worry for boxed) 55 | if (object.Equals(data[i], value)) return i; 56 | } 57 | return -1; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Notifiers/BooleanNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace UtyRx 6 | { 7 | /// 8 | /// Notify boolean flag. 9 | /// 10 | public class BooleanNotifier : IObservable 11 | { 12 | readonly Subject boolTrigger = new Subject(); 13 | 14 | bool boolValue; 15 | /// Current flag value 16 | public bool Value 17 | { 18 | get { return boolValue; } 19 | set 20 | { 21 | boolValue = value; 22 | boolTrigger.OnNext(value); 23 | } 24 | } 25 | 26 | /// 27 | /// Setup initial flag. 28 | /// 29 | public BooleanNotifier(bool initialValue = false) 30 | { 31 | this.Value = initialValue; 32 | } 33 | 34 | /// 35 | /// Set and raise true if current value isn't true. 36 | /// 37 | public void TurnOn() 38 | { 39 | if (Value != true) 40 | { 41 | Value = true; 42 | } 43 | } 44 | 45 | /// 46 | /// Set and raise false if current value isn't false. 47 | /// 48 | public void TurnOff() 49 | { 50 | if (Value != false) 51 | { 52 | Value = false; 53 | } 54 | } 55 | 56 | /// 57 | /// Set and raise reverse value. 58 | /// 59 | public void SwitchValue() 60 | { 61 | Value = !Value; 62 | } 63 | 64 | 65 | /// 66 | /// Subscribe observer. 67 | /// 68 | public IDisposable Subscribe(IObserver observer) 69 | { 70 | return boolTrigger.Subscribe(observer); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Notifiers/MessageBroker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx 5 | { 6 | public interface IMessageBroker 7 | { 8 | /// 9 | /// Send Message to all receiver. 10 | /// 11 | void Publish(T message); 12 | 13 | /// 14 | /// Subscribe typed message. 15 | /// 16 | IObservable Receive(); 17 | } 18 | 19 | /// 20 | /// In-Memory PubSub filtered by Type. 21 | /// 22 | public class MessageBroker : IMessageBroker, IDisposable 23 | { 24 | /// 25 | /// MessageBroker in Global scope. 26 | /// 27 | public static readonly IMessageBroker Default = new MessageBroker(); 28 | 29 | bool isDisposed = false; 30 | readonly Dictionary notifiers = new Dictionary(); 31 | 32 | public void Publish(T message) 33 | { 34 | object notifier; 35 | lock (notifiers) 36 | { 37 | if (isDisposed) return; 38 | 39 | if (!notifiers.TryGetValue(typeof(T), out notifier)) 40 | { 41 | return; 42 | } 43 | } 44 | ((Subject)notifier).OnNext(message); 45 | } 46 | 47 | public IObservable Receive() 48 | { 49 | object notifier; 50 | lock (notifiers) 51 | { 52 | if (isDisposed) throw new ObjectDisposedException("MessageBroker"); 53 | 54 | if (!notifiers.TryGetValue(typeof(T), out notifier)) 55 | { 56 | notifier = new Subject(); 57 | notifiers.Add(typeof(T), notifier); 58 | } 59 | } 60 | 61 | return ((IObservable)notifier).AsObservable(); 62 | } 63 | 64 | public void Dispose() 65 | { 66 | lock (notifiers) 67 | { 68 | if (!isDisposed) 69 | { 70 | isDisposed = true; 71 | notifiers.Clear(); 72 | } 73 | } 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Notifiers/ScheduledNotifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | /// 6 | /// Notify value on setuped scheduler. 7 | /// 8 | public class ScheduledNotifier : IObservable, IProgress 9 | { 10 | readonly IScheduler scheduler; 11 | readonly Subject trigger = new Subject(); 12 | 13 | /// 14 | /// Use scheduler is Scheduler.DefaultSchedulers.ConstantTimeOperations. 15 | /// 16 | public ScheduledNotifier() 17 | { 18 | this.scheduler = Scheduler.DefaultSchedulers.ConstantTimeOperations; 19 | } 20 | /// 21 | /// Use scheduler is argument's scheduler. 22 | /// 23 | public ScheduledNotifier(IScheduler scheduler) 24 | { 25 | if (scheduler == null) 26 | { 27 | throw new ArgumentNullException("scheduler"); 28 | } 29 | 30 | this.scheduler = scheduler; 31 | } 32 | 33 | /// 34 | /// Push value to subscribers on setuped scheduler. 35 | /// 36 | public void Report(T value) 37 | { 38 | scheduler.Schedule(() => trigger.OnNext(value)); 39 | } 40 | 41 | /// 42 | /// Push value to subscribers on setuped scheduler. 43 | /// 44 | public IDisposable Report(T value, TimeSpan dueTime) 45 | { 46 | var cancel = scheduler.Schedule(dueTime, () => trigger.OnNext(value)); 47 | return cancel; 48 | } 49 | 50 | /// 51 | /// Push value to subscribers on setuped scheduler. 52 | /// 53 | public IDisposable Report(T value, DateTimeOffset dueTime) 54 | { 55 | var cancel = scheduler.Schedule(dueTime, () => trigger.OnNext(value)); 56 | return cancel; 57 | } 58 | 59 | /// 60 | /// Subscribe observer. 61 | /// 62 | public IDisposable Subscribe(IObserver observer) 63 | { 64 | if (observer == null) 65 | { 66 | throw new ArgumentNullException("observer"); 67 | } 68 | 69 | return trigger.Subscribe(observer); 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Observable/Observable.Aggregate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using UtyRx.Operators; 5 | 6 | namespace UtyRx 7 | { 8 | public static partial class Observable 9 | { 10 | public static IObservable Scan(this IObservable source, Func accumulator) 11 | { 12 | return new ScanObservable(source, accumulator); 13 | } 14 | 15 | public static IObservable Scan(this IObservable source, TAccumulate seed, Func accumulator) 16 | { 17 | return new ScanObservable(source, seed, accumulator); 18 | } 19 | 20 | public static IObservable Aggregate(this IObservable source, Func accumulator) 21 | { 22 | return new AggregateObservable(source, accumulator); 23 | } 24 | 25 | public static IObservable Aggregate(this IObservable source, TAccumulate seed, Func accumulator) 26 | { 27 | return new AggregateObservable(source, seed, accumulator); 28 | } 29 | 30 | public static IObservable Aggregate(this IObservable source, TAccumulate seed, Func accumulator, Func resultSelector) 31 | { 32 | return new AggregateObservable(source, seed, accumulator, resultSelector); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Observable/Observable.Binding.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx 5 | { 6 | public static partial class Observable 7 | { 8 | public static IConnectableObservable Multicast(this IObservable source, ISubject subject) 9 | { 10 | return new ConnectableObservable(source, subject); 11 | } 12 | 13 | public static IConnectableObservable Publish(this IObservable source) 14 | { 15 | return source.Multicast(new Subject()); 16 | } 17 | 18 | public static IConnectableObservable Publish(this IObservable source, T initialValue) 19 | { 20 | return source.Multicast(new BehaviorSubject(initialValue)); 21 | } 22 | 23 | public static IConnectableObservable PublishLast(this IObservable source) 24 | { 25 | return source.Multicast(new AsyncSubject()); 26 | } 27 | 28 | public static IConnectableObservable Replay(this IObservable source) 29 | { 30 | return source.Multicast(new ReplaySubject()); 31 | } 32 | 33 | public static IConnectableObservable Replay(this IObservable source, IScheduler scheduler) 34 | { 35 | return source.Multicast(new ReplaySubject(scheduler)); 36 | } 37 | 38 | public static IConnectableObservable Replay(this IObservable source, int bufferSize) 39 | { 40 | return source.Multicast(new ReplaySubject(bufferSize)); 41 | } 42 | 43 | public static IConnectableObservable Replay(this IObservable source, int bufferSize, IScheduler scheduler) 44 | { 45 | return source.Multicast(new ReplaySubject(bufferSize, scheduler)); 46 | } 47 | 48 | public static IConnectableObservable Replay(this IObservable source, TimeSpan window) 49 | { 50 | return source.Multicast(new ReplaySubject(window)); 51 | } 52 | 53 | public static IConnectableObservable Replay(this IObservable source, TimeSpan window, IScheduler scheduler) 54 | { 55 | return source.Multicast(new ReplaySubject(window, scheduler)); 56 | } 57 | 58 | public static IConnectableObservable Replay(this IObservable source, int bufferSize, TimeSpan window, IScheduler scheduler) 59 | { 60 | return source.Multicast(new ReplaySubject(bufferSize, window, scheduler)); 61 | } 62 | 63 | public static IObservable RefCount(this IConnectableObservable source) 64 | { 65 | return new RefCountObservable(source); 66 | } 67 | 68 | /// 69 | /// same as Publish().RefCount() 70 | /// 71 | public static IObservable Share(this IObservable source) 72 | { 73 | return source.Publish().RefCount(); 74 | } 75 | } 76 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Observable/Observable.Blocking.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | public static partial class Observable 6 | { 7 | public static T Wait(this IObservable source) 8 | { 9 | return new UtyRx.Operators.Wait(source, InfiniteTimeSpan).Run(); 10 | } 11 | 12 | public static T Wait(this IObservable source, TimeSpan timeout) 13 | { 14 | return new UtyRx.Operators.Wait(source, timeout).Run(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Observable/Observable.Conversions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UtyRx.Operators; 4 | 5 | namespace UtyRx 6 | { 7 | public static partial class Observable 8 | { 9 | public static IObservable AsObservable(this IObservable source) 10 | { 11 | if (source == null) throw new ArgumentNullException("source"); 12 | 13 | // optimize, don't double wrap 14 | if (source is UtyRx.Operators.AsObservableObservable) 15 | { 16 | return source; 17 | } 18 | 19 | return new AsObservableObservable(source); 20 | } 21 | 22 | public static IObservable ToObservable(this IEnumerable source) 23 | { 24 | return ToObservable(source, Scheduler.DefaultSchedulers.Iteration); 25 | } 26 | 27 | public static IObservable ToObservable(this IEnumerable source, IScheduler scheduler) 28 | { 29 | return new ToObservableObservable(source, scheduler); 30 | } 31 | 32 | public static IObservable Cast(this IObservable source) 33 | { 34 | return new CastObservable(source); 35 | } 36 | 37 | /// 38 | /// witness is for type inference. 39 | /// 40 | public static IObservable Cast(this IObservable source, TResult witness) 41 | { 42 | return new CastObservable(source); 43 | } 44 | 45 | public static IObservable OfType(this IObservable source) 46 | { 47 | return new OfTypeObservable(source); 48 | } 49 | 50 | /// 51 | /// witness is for type inference. 52 | /// 53 | public static IObservable OfType(this IObservable source, TResult witness) 54 | { 55 | return new OfTypeObservable(source); 56 | } 57 | 58 | /// 59 | /// Converting .Select(_ => Unit.Default) sequence. 60 | /// 61 | public static IObservable AsUnitObservable(this IObservable source) 62 | { 63 | return new AsUnitObservableObservable(source); 64 | } 65 | 66 | /// 67 | /// Same as LastOrDefault().AsUnitObservable(). 68 | /// 69 | public static IObservable AsSingleUnitObservable(this IObservable source) 70 | { 71 | return new AsSingleUnitObservableObservable(source); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Observable/Observable.Events.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx 5 | { 6 | public static partial class Observable 7 | { 8 | public static IObservable> FromEventPattern(Func, TDelegate> conversion, Action addHandler, Action removeHandler) 9 | where TEventArgs : EventArgs 10 | { 11 | return new FromEventPatternObservable(conversion, addHandler, removeHandler); 12 | } 13 | 14 | public static IObservable FromEvent(Func conversion, Action addHandler, Action removeHandler) 15 | { 16 | return new FromEventObservable(conversion, addHandler, removeHandler); 17 | } 18 | 19 | public static IObservable FromEvent(Func, TDelegate> conversion, Action addHandler, Action removeHandler) 20 | { 21 | return new FromEventObservable(conversion, addHandler, removeHandler); 22 | } 23 | 24 | public static IObservable FromEvent(Action addHandler, Action removeHandler) 25 | { 26 | return new FromEventObservable(addHandler, removeHandler); 27 | } 28 | 29 | public static IObservable FromEvent(Action> addHandler, Action> removeHandler) 30 | { 31 | return new FromEventObservable_(addHandler, removeHandler); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Observable/Observable.Joins.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace UtyRx 6 | { 7 | public static partial class Observable 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/AsObservable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class AsObservableObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | 10 | public AsObservableObservable(IObservable source) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | } 15 | 16 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 17 | { 18 | return source.Subscribe(new AsObservable(observer, cancel)); 19 | } 20 | 21 | class AsObservable : OperatorObserverBase 22 | { 23 | public AsObservable(IObserver observer, IDisposable cancel) : base(observer, cancel) 24 | { 25 | } 26 | 27 | public override void OnNext(T value) 28 | { 29 | base.observer.OnNext(value); 30 | } 31 | 32 | public override void OnError(Exception error) 33 | { 34 | try { observer.OnError(error); } 35 | finally { Dispose(); } 36 | } 37 | 38 | public override void OnCompleted() 39 | { 40 | try { observer.OnCompleted(); } 41 | finally { Dispose(); } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/AsSingleUnitObservable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class AsSingleUnitObservableObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | 10 | public AsSingleUnitObservableObservable(IObservable source) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | } 15 | 16 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 17 | { 18 | return source.Subscribe(new AsSingleUnitObservable(observer, cancel)); 19 | } 20 | 21 | class AsSingleUnitObservable : OperatorObserverBase 22 | { 23 | public AsSingleUnitObservable(IObserver observer, IDisposable cancel) : base(observer, cancel) 24 | { 25 | } 26 | 27 | public override void OnNext(T value) 28 | { 29 | } 30 | 31 | public override void OnError(Exception error) 32 | { 33 | try { observer.OnError(error); } 34 | finally { Dispose(); } 35 | } 36 | 37 | public override void OnCompleted() 38 | { 39 | observer.OnNext(Unit.Default); 40 | 41 | try { observer.OnCompleted(); } 42 | finally { Dispose(); } 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/AsUnitObservable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class AsUnitObservableObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | 9 | public AsUnitObservableObservable(IObservable source) 10 | : base(source.IsRequiredSubscribeOnCurrentThread()) 11 | { 12 | this.source = source; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 16 | { 17 | return source.Subscribe(new AsUnitObservable(observer, cancel)); 18 | } 19 | 20 | class AsUnitObservable : OperatorObserverBase 21 | { 22 | public AsUnitObservable(IObserver observer, IDisposable cancel) 23 | : base(observer, cancel) 24 | { 25 | } 26 | 27 | public override void OnNext(T value) 28 | { 29 | base.observer.OnNext(Unit.Default); 30 | } 31 | 32 | public override void OnError(Exception error) 33 | { 34 | try { observer.OnError(error); } 35 | finally { Dispose(); } 36 | } 37 | 38 | public override void OnCompleted() 39 | { 40 | try { observer.OnCompleted(); } 41 | finally { Dispose(); } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Cast.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class CastObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | 9 | public CastObservable(IObservable source) 10 | : base(source.IsRequiredSubscribeOnCurrentThread()) 11 | { 12 | this.source = source; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 16 | { 17 | return source.Subscribe(new Cast(observer, cancel)); 18 | } 19 | 20 | class Cast : OperatorObserverBase 21 | { 22 | public Cast(IObserver observer, IDisposable cancel) 23 | : base(observer, cancel) 24 | { 25 | } 26 | 27 | public override void OnNext(TSource value) 28 | { 29 | var castValue = default(TResult); 30 | try 31 | { 32 | castValue = (TResult)(object)value; 33 | } 34 | catch (Exception ex) 35 | { 36 | try { observer.OnError(ex); } 37 | finally { Dispose(); } 38 | return; 39 | } 40 | 41 | observer.OnNext(castValue); 42 | } 43 | 44 | public override void OnError(Exception error) 45 | { 46 | try { observer.OnError(error); } 47 | finally { Dispose(); } 48 | } 49 | 50 | public override void OnCompleted() 51 | { 52 | try { observer.OnCompleted(); } 53 | finally { Dispose(); } 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/ContinueWith.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class ContinueWithObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | readonly Func> selector; 9 | 10 | public ContinueWithObservable(IObservable source, Func> selector) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | this.selector = selector; 15 | } 16 | 17 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 18 | { 19 | return new ContinueWith(this, observer, cancel).Run(); 20 | } 21 | 22 | class ContinueWith : OperatorObserverBase 23 | { 24 | readonly ContinueWithObservable parent; 25 | readonly SerialDisposable serialDisposable = new SerialDisposable(); 26 | 27 | bool seenValue; 28 | TSource lastValue; 29 | 30 | public ContinueWith(ContinueWithObservable parent, IObserver observer, IDisposable cancel) : base(observer, cancel) 31 | { 32 | this.parent = parent; 33 | } 34 | 35 | public IDisposable Run() 36 | { 37 | var sourceDisposable = new SingleAssignmentDisposable(); 38 | serialDisposable.Disposable = sourceDisposable; 39 | 40 | sourceDisposable.Disposable = parent.source.Subscribe(this); 41 | return serialDisposable; 42 | } 43 | 44 | public override void OnNext(TSource value) 45 | { 46 | this.seenValue = true; 47 | this.lastValue = value; 48 | } 49 | 50 | public override void OnError(Exception error) 51 | { 52 | try { observer.OnError(error); } finally { Dispose(); }; 53 | } 54 | 55 | public override void OnCompleted() 56 | { 57 | if (seenValue) 58 | { 59 | var v = parent.selector(lastValue); 60 | // dispose source subscription 61 | serialDisposable.Disposable = v.Subscribe(observer); 62 | } 63 | else 64 | { 65 | try { observer.OnCompleted(); } finally { Dispose(); }; 66 | } 67 | } 68 | } 69 | } 70 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/DefaultIfEmpty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class DefaultIfEmptyObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | readonly T defaultValue; 10 | 11 | public DefaultIfEmptyObservable(IObservable source, T defaultValue) 12 | : base(source.IsRequiredSubscribeOnCurrentThread()) 13 | { 14 | this.source = source; 15 | this.defaultValue = defaultValue; 16 | } 17 | 18 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 19 | { 20 | return source.Subscribe(new DefaultIfEmpty(this, observer, cancel)); 21 | } 22 | 23 | class DefaultIfEmpty : OperatorObserverBase 24 | { 25 | readonly DefaultIfEmptyObservable parent; 26 | bool hasValue; 27 | 28 | public DefaultIfEmpty(DefaultIfEmptyObservable parent, IObserver observer, IDisposable cancel) : base(observer, cancel) 29 | { 30 | this.parent = parent; 31 | this.hasValue = false; 32 | } 33 | 34 | public override void OnNext(T value) 35 | { 36 | hasValue = true; 37 | observer.OnNext(value); 38 | } 39 | 40 | public override void OnError(Exception error) 41 | { 42 | try { observer.OnError(error); } 43 | finally { Dispose(); } 44 | } 45 | 46 | public override void OnCompleted() 47 | { 48 | if (!hasValue) 49 | { 50 | observer.OnNext(parent.defaultValue); 51 | } 52 | 53 | try { observer.OnCompleted(); } 54 | finally { Dispose(); } 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Defer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class DeferObservable : OperatorObservableBase 6 | { 7 | readonly Func> observableFactory; 8 | 9 | public DeferObservable(Func> observableFactory) 10 | : base(false) 11 | { 12 | this.observableFactory = observableFactory; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 16 | { 17 | observer = new Defer(observer, cancel); 18 | 19 | IObservable source; 20 | try 21 | { 22 | source = observableFactory(); 23 | } 24 | catch (Exception ex) 25 | { 26 | source = Observable.Throw(ex); 27 | } 28 | 29 | return source.Subscribe(observer); 30 | } 31 | 32 | class Defer : OperatorObserverBase 33 | { 34 | public Defer(IObserver observer, IDisposable cancel) : base(observer, cancel) 35 | { 36 | } 37 | 38 | public override void OnNext(T value) 39 | { 40 | try 41 | { 42 | base.observer.OnNext(value); 43 | } 44 | catch 45 | { 46 | Dispose(); 47 | throw; 48 | } 49 | } 50 | 51 | public override void OnError(Exception error) 52 | { 53 | try { observer.OnError(error); } 54 | finally { Dispose(); } 55 | } 56 | 57 | public override void OnCompleted() 58 | { 59 | try { observer.OnCompleted(); } 60 | finally { Dispose(); } 61 | } 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/DelaySubscription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class DelaySubscriptionObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | readonly IScheduler scheduler; 10 | readonly TimeSpan? dueTimeT; 11 | readonly DateTimeOffset? dueTimeD; 12 | 13 | public DelaySubscriptionObservable(IObservable source,TimeSpan dueTime, IScheduler scheduler) 14 | : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread()) 15 | { 16 | this.source = source; 17 | this.scheduler = scheduler; 18 | this.dueTimeT = dueTime; 19 | } 20 | 21 | public DelaySubscriptionObservable(IObservable source, DateTimeOffset dueTime, IScheduler scheduler) 22 | : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread()) 23 | { 24 | this.source = source; 25 | this.scheduler = scheduler; 26 | this.dueTimeD = dueTime; 27 | } 28 | 29 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 30 | { 31 | if (dueTimeT != null) 32 | { 33 | var d = new MultipleAssignmentDisposable(); 34 | var dt = Scheduler.Normalize(dueTimeT.Value); 35 | 36 | d.Disposable = scheduler.Schedule(dt, () => 37 | { 38 | d.Disposable = source.Subscribe(observer); 39 | }); 40 | 41 | return d; 42 | } 43 | else 44 | { 45 | var d = new MultipleAssignmentDisposable(); 46 | 47 | d.Disposable = scheduler.Schedule(dueTimeD.Value, () => 48 | { 49 | d.Disposable = source.Subscribe(observer); 50 | }); 51 | 52 | return d; 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Dematerialize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class DematerializeObservable : OperatorObservableBase 6 | { 7 | readonly IObservable> source; 8 | 9 | public DematerializeObservable(IObservable> source) 10 | : base(source.IsRequiredSubscribeOnCurrentThread()) 11 | { 12 | this.source = source; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 16 | { 17 | return new Dematerialize(this, observer, cancel).Run(); 18 | } 19 | 20 | class Dematerialize : OperatorObserverBase, T> 21 | { 22 | readonly DematerializeObservable parent; 23 | 24 | public Dematerialize(DematerializeObservable parent, IObserver observer, IDisposable cancel) 25 | : base(observer, cancel) 26 | { 27 | this.parent = parent; 28 | } 29 | 30 | public IDisposable Run() 31 | { 32 | return parent.source.Subscribe(this); 33 | } 34 | 35 | public override void OnNext(Notification value) 36 | { 37 | switch (value.Kind) 38 | { 39 | case NotificationKind.OnNext: 40 | observer.OnNext(value.Value); 41 | break; 42 | case NotificationKind.OnError: 43 | try { observer.OnError(value.Exception); } 44 | finally { Dispose(); } 45 | break; 46 | case NotificationKind.OnCompleted: 47 | try { observer.OnCompleted(); } 48 | finally { Dispose(); } 49 | break; 50 | default: 51 | break; 52 | } 53 | } 54 | 55 | public override void OnError(Exception error) 56 | { 57 | try { observer.OnError(error); } finally { Dispose(); } 58 | } 59 | 60 | public override void OnCompleted() 61 | { 62 | try { observer.OnCompleted(); } finally { Dispose(); } 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Empty.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class EmptyObservable : OperatorObservableBase 6 | { 7 | readonly IScheduler scheduler; 8 | 9 | public EmptyObservable(IScheduler scheduler) 10 | : base(false) 11 | { 12 | this.scheduler = scheduler; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 16 | { 17 | observer = new Empty(observer, cancel); 18 | 19 | if (scheduler == Scheduler.Immediate) 20 | { 21 | observer.OnCompleted(); 22 | return Disposable.Empty; 23 | } 24 | else 25 | { 26 | return scheduler.Schedule(observer.OnCompleted); 27 | } 28 | } 29 | 30 | class Empty : OperatorObserverBase 31 | { 32 | public Empty(IObserver observer, IDisposable cancel) : base(observer, cancel) 33 | { 34 | } 35 | 36 | public override void OnNext(T value) 37 | { 38 | try 39 | { 40 | base.observer.OnNext(value); 41 | } 42 | catch 43 | { 44 | Dispose(); 45 | throw; 46 | } 47 | } 48 | 49 | public override void OnError(Exception error) 50 | { 51 | try { observer.OnError(error); } 52 | finally { Dispose(); } 53 | } 54 | 55 | public override void OnCompleted() 56 | { 57 | try { observer.OnCompleted(); } 58 | finally { Dispose(); } 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Finally.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | public class FinallyObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | readonly Action finallyAction; 9 | 10 | public FinallyObservable(IObservable source, Action finallyAction) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | this.finallyAction = finallyAction; 15 | } 16 | 17 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 18 | { 19 | return new Finally(this, observer, cancel).Run(); 20 | } 21 | 22 | class Finally : OperatorObserverBase 23 | { 24 | readonly FinallyObservable parent; 25 | 26 | public Finally(FinallyObservable parent, IObserver observer, IDisposable cancel) 27 | : base(observer, cancel) 28 | { 29 | this.parent = parent; 30 | } 31 | 32 | public IDisposable Run() 33 | { 34 | IDisposable subscription; 35 | try 36 | { 37 | subscription = parent.source.Subscribe(this); 38 | } 39 | catch 40 | { 41 | // This behaviour is not same as .NET Official Rx 42 | parent.finallyAction(); 43 | throw; 44 | } 45 | 46 | return StableCompositeDisposable.Create(subscription, Disposable.Create(() => 47 | { 48 | parent.finallyAction(); 49 | })); 50 | } 51 | 52 | public override void OnNext(T value) 53 | { 54 | base.observer.OnNext(value); 55 | } 56 | 57 | public override void OnError(Exception error) 58 | { 59 | try { observer.OnError(error); } finally { Dispose(); }; 60 | } 61 | 62 | public override void OnCompleted() 63 | { 64 | try { observer.OnCompleted(); } finally { Dispose(); }; 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/IgnoreElements.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class IgnoreElementsObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | 10 | public IgnoreElementsObservable(IObservable source) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | } 15 | 16 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 17 | { 18 | return source.Subscribe(new IgnoreElements(observer, cancel)); 19 | } 20 | 21 | class IgnoreElements : OperatorObserverBase 22 | { 23 | public IgnoreElements(IObserver observer, IDisposable cancel) : base(observer, cancel) 24 | { 25 | } 26 | 27 | public override void OnNext(T value) 28 | { 29 | } 30 | 31 | public override void OnError(Exception error) 32 | { 33 | try { observer.OnError(error); } 34 | finally { Dispose(); } 35 | } 36 | 37 | public override void OnCompleted() 38 | { 39 | try { observer.OnCompleted(); } 40 | finally { Dispose(); } 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Materialize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class MaterializeObservable : OperatorObservableBase> 6 | { 7 | readonly IObservable source; 8 | 9 | public MaterializeObservable(IObservable source) 10 | : base(source.IsRequiredSubscribeOnCurrentThread()) 11 | { 12 | this.source = source; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver> observer, IDisposable cancel) 16 | { 17 | return new Materialize(this, observer, cancel).Run(); 18 | } 19 | 20 | class Materialize : OperatorObserverBase> 21 | { 22 | readonly MaterializeObservable parent; 23 | 24 | public Materialize(MaterializeObservable parent, IObserver> observer, IDisposable cancel) 25 | : base(observer, cancel) 26 | { 27 | this.parent = parent; 28 | } 29 | 30 | public IDisposable Run() 31 | { 32 | return parent.source.Subscribe(this); 33 | } 34 | 35 | public override void OnNext(T value) 36 | { 37 | observer.OnNext(Notification.CreateOnNext(value)); 38 | } 39 | 40 | public override void OnError(Exception error) 41 | { 42 | observer.OnNext(Notification.CreateOnError(error)); 43 | try { observer.OnCompleted(); } finally { Dispose(); } 44 | } 45 | 46 | public override void OnCompleted() 47 | { 48 | observer.OnNext(Notification.CreateOnCompleted()); 49 | try { observer.OnCompleted(); } finally { Dispose(); } 50 | } 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Never.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class NeverObservable : OperatorObservableBase 6 | { 7 | public NeverObservable() 8 | : base(false) 9 | { 10 | } 11 | 12 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 13 | { 14 | return Disposable.Empty; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/OfType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class OfTypeObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | 9 | public OfTypeObservable(IObservable source) 10 | : base(source.IsRequiredSubscribeOnCurrentThread()) 11 | { 12 | this.source = source; 13 | } 14 | 15 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 16 | { 17 | return source.Subscribe(new OfType(observer, cancel)); 18 | } 19 | 20 | class OfType : OperatorObserverBase 21 | { 22 | public OfType(IObserver observer, IDisposable cancel) 23 | : base(observer, cancel) 24 | { 25 | } 26 | 27 | public override void OnNext(TSource value) 28 | { 29 | if (value is TResult) 30 | { 31 | var castValue = (TResult)(object)value; 32 | observer.OnNext(castValue); 33 | } 34 | } 35 | 36 | public override void OnError(Exception error) 37 | { 38 | try { observer.OnError(error); } finally { Dispose(); } 39 | } 40 | 41 | public override void OnCompleted() 42 | { 43 | try { observer.OnCompleted(); } finally { Dispose(); } 44 | } 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/OperatorObservableBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | // implements note : all field must be readonly. 6 | public abstract class OperatorObservableBase : IObservable, IOptimizedObservable 7 | { 8 | readonly bool isRequiredSubscribeOnCurrentThread; 9 | 10 | public OperatorObservableBase(bool isRequiredSubscribeOnCurrentThread) 11 | { 12 | this.isRequiredSubscribeOnCurrentThread = isRequiredSubscribeOnCurrentThread; 13 | } 14 | 15 | public bool IsRequiredSubscribeOnCurrentThread() 16 | { 17 | return isRequiredSubscribeOnCurrentThread; 18 | } 19 | 20 | public IDisposable Subscribe(IObserver observer) 21 | { 22 | var subscription = new SingleAssignmentDisposable(); 23 | 24 | // note: 25 | // does not make the safe observer, it breaks exception durability. 26 | // var safeObserver = Observer.CreateAutoDetachObserver(observer, subscription); 27 | 28 | if (isRequiredSubscribeOnCurrentThread && Scheduler.IsCurrentThreadSchedulerScheduleRequired) 29 | { 30 | Scheduler.CurrentThread.Schedule(() => subscription.Disposable = SubscribeCore(observer, subscription)); 31 | } 32 | else 33 | { 34 | subscription.Disposable = SubscribeCore(observer, subscription); 35 | } 36 | 37 | return subscription; 38 | } 39 | 40 | protected abstract IDisposable SubscribeCore(IObserver observer, IDisposable cancel); 41 | } 42 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/OperatorObserverBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | public abstract class OperatorObserverBase : IDisposable, IObserver 7 | { 8 | protected internal volatile IObserver observer; 9 | IDisposable cancel; 10 | 11 | public OperatorObserverBase(IObserver observer, IDisposable cancel) 12 | { 13 | this.observer = observer; 14 | this.cancel = cancel; 15 | } 16 | 17 | public abstract void OnNext(TSource value); 18 | 19 | public abstract void OnError(Exception error); 20 | 21 | public abstract void OnCompleted(); 22 | 23 | public void Dispose() 24 | { 25 | observer = UtyRx.InternalUtil.EmptyObserver.Instance; 26 | var target = System.Threading.Interlocked.Exchange(ref cancel, null); 27 | if (target != null) 28 | { 29 | target.Dispose(); 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Range.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class RangeObservable : OperatorObservableBase 6 | { 7 | readonly int start; 8 | readonly int count; 9 | readonly IScheduler scheduler; 10 | 11 | public RangeObservable(int start, int count, IScheduler scheduler) 12 | : base(scheduler == Scheduler.CurrentThread) 13 | { 14 | if (count < 0) throw new ArgumentOutOfRangeException("count < 0"); 15 | 16 | this.start = start; 17 | this.count = count; 18 | this.scheduler = scheduler; 19 | } 20 | 21 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 22 | { 23 | observer = new Range(observer, cancel); 24 | 25 | if (scheduler == Scheduler.Immediate) 26 | { 27 | for (int i = 0; i < count; i++) 28 | { 29 | int v = start + i; 30 | observer.OnNext(v); 31 | } 32 | observer.OnCompleted(); 33 | 34 | return Disposable.Empty; 35 | } 36 | else 37 | { 38 | var i = 0; 39 | return scheduler.Schedule((Action self) => 40 | { 41 | if (i < count) 42 | { 43 | int v = start + i; 44 | observer.OnNext(v); 45 | i++; 46 | self(); 47 | } 48 | else 49 | { 50 | observer.OnCompleted(); 51 | } 52 | }); 53 | } 54 | } 55 | 56 | class Range : OperatorObserverBase 57 | { 58 | public Range(IObserver observer, IDisposable cancel) 59 | : base(observer, cancel) 60 | { 61 | } 62 | 63 | public override void OnNext(int value) 64 | { 65 | try 66 | { 67 | base.observer.OnNext(value); 68 | } 69 | catch 70 | { 71 | Dispose(); 72 | throw; 73 | } 74 | } 75 | 76 | public override void OnError(Exception error) 77 | { 78 | try { observer.OnError(error); } 79 | finally { Dispose(); } 80 | } 81 | 82 | public override void OnCompleted() 83 | { 84 | try { observer.OnCompleted(); } 85 | finally { Dispose(); } 86 | } 87 | } 88 | } 89 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/RefCount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class RefCountObservable : OperatorObservableBase 7 | { 8 | readonly IConnectableObservable source; 9 | readonly object gate = new object(); 10 | int refCount = 0; 11 | IDisposable connection; 12 | 13 | public RefCountObservable(IConnectableObservable source) 14 | : base(source.IsRequiredSubscribeOnCurrentThread()) 15 | { 16 | this.source = source; 17 | } 18 | 19 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 20 | { 21 | return new RefCount(this, observer, cancel).Run(); 22 | } 23 | 24 | class RefCount : OperatorObserverBase 25 | { 26 | readonly RefCountObservable parent; 27 | 28 | public RefCount(RefCountObservable parent, IObserver observer, IDisposable cancel) : base(observer, cancel) 29 | { 30 | this.parent = parent; 31 | } 32 | 33 | public IDisposable Run() 34 | { 35 | var subcription = parent.source.Subscribe(this); 36 | 37 | lock (parent.gate) 38 | { 39 | if (++parent.refCount == 1) 40 | { 41 | parent.connection = parent.source.Connect(); 42 | } 43 | } 44 | 45 | return Disposable.Create(() => 46 | { 47 | subcription.Dispose(); 48 | 49 | lock (parent.gate) 50 | { 51 | if (--parent.refCount == 0) 52 | { 53 | parent.connection.Dispose(); 54 | } 55 | } 56 | }); 57 | } 58 | 59 | public override void OnNext(T value) 60 | { 61 | base.observer.OnNext(value); 62 | } 63 | 64 | public override void OnError(Exception error) 65 | { 66 | try { observer.OnError(error); } 67 | finally { Dispose(); } 68 | } 69 | 70 | public override void OnCompleted() 71 | { 72 | try { observer.OnCompleted(); } 73 | finally { Dispose(); } 74 | } 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Return.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class ReturnObservable : OperatorObservableBase 6 | { 7 | readonly T value; 8 | readonly IScheduler scheduler; 9 | 10 | public ReturnObservable(T value, IScheduler scheduler) 11 | : base(scheduler == Scheduler.CurrentThread) 12 | { 13 | this.value = value; 14 | this.scheduler = scheduler; 15 | } 16 | 17 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 18 | { 19 | observer = new Return(observer, cancel); 20 | 21 | if (scheduler == Scheduler.Immediate) 22 | { 23 | observer.OnNext(value); 24 | observer.OnCompleted(); 25 | return Disposable.Empty; 26 | } 27 | else 28 | { 29 | return scheduler.Schedule(() => 30 | { 31 | observer.OnNext(value); 32 | observer.OnCompleted(); 33 | }); 34 | } 35 | } 36 | 37 | class Return : OperatorObserverBase 38 | { 39 | public Return(IObserver observer, IDisposable cancel) 40 | : base(observer, cancel) 41 | { 42 | } 43 | 44 | public override void OnNext(T value) 45 | { 46 | try 47 | { 48 | base.observer.OnNext(value); 49 | } 50 | catch 51 | { 52 | Dispose(); 53 | throw; 54 | } 55 | } 56 | 57 | public override void OnError(Exception error) 58 | { 59 | try { observer.OnError(error); } 60 | finally { Dispose(); } 61 | } 62 | 63 | public override void OnCompleted() 64 | { 65 | try { observer.OnCompleted(); } 66 | finally { Dispose(); } 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/StartWith.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class StartWithObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | readonly T value; 9 | readonly Func valueFactory; 10 | 11 | public StartWithObservable(IObservable source, T value) 12 | : base(source.IsRequiredSubscribeOnCurrentThread()) 13 | { 14 | this.source = source; 15 | this.value = value; 16 | } 17 | 18 | public StartWithObservable(IObservable source, Func valueFactory) 19 | : base(source.IsRequiredSubscribeOnCurrentThread()) 20 | { 21 | this.source = source; 22 | this.valueFactory = valueFactory; 23 | } 24 | 25 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 26 | { 27 | return new StartWith(this, observer, cancel).Run(); 28 | } 29 | 30 | class StartWith : OperatorObserverBase 31 | { 32 | readonly StartWithObservable parent; 33 | 34 | public StartWith(StartWithObservable parent, IObserver observer, IDisposable cancel) : base(observer, cancel) 35 | { 36 | this.parent = parent; 37 | } 38 | 39 | public IDisposable Run() 40 | { 41 | T t; 42 | if (parent.valueFactory == null) 43 | { 44 | t = parent.value; 45 | } 46 | else 47 | { 48 | try 49 | { 50 | t = parent.valueFactory(); 51 | } 52 | catch (Exception ex) 53 | { 54 | try { observer.OnError(ex); } 55 | finally { Dispose(); } 56 | return Disposable.Empty; 57 | } 58 | } 59 | 60 | OnNext(t); 61 | return parent.source.Subscribe(base.observer); // good bye StartWithObserver 62 | } 63 | 64 | public override void OnNext(T value) 65 | { 66 | base.observer.OnNext(value); 67 | } 68 | 69 | public override void OnError(Exception error) 70 | { 71 | try { observer.OnError(error); } 72 | finally { Dispose(); } 73 | } 74 | 75 | public override void OnCompleted() 76 | { 77 | try { observer.OnCompleted(); } 78 | finally { Dispose(); } 79 | } 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/SubscribeOn.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class SubscribeOnObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | readonly IScheduler scheduler; 10 | 11 | public SubscribeOnObservable(IObservable source, IScheduler scheduler) 12 | : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread()) 13 | { 14 | this.source = source; 15 | this.scheduler = scheduler; 16 | } 17 | 18 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 19 | { 20 | var m = new SingleAssignmentDisposable(); 21 | var d = new SerialDisposable(); 22 | d.Disposable = m; 23 | 24 | m.Disposable = scheduler.Schedule(() => 25 | { 26 | d.Disposable = new ScheduledDisposable(scheduler, source.Subscribe(observer)); 27 | }); 28 | 29 | return d; 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Synchronize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UtyRx.Operators; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class SynchronizeObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | readonly object gate; 10 | 11 | public SynchronizeObservable(IObservable source, object gate) 12 | : base(source.IsRequiredSubscribeOnCurrentThread()) 13 | { 14 | this.source = source; 15 | this.gate = gate; 16 | } 17 | 18 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 19 | { 20 | return source.Subscribe(new Synchronize(this, observer, cancel)); 21 | } 22 | 23 | class Synchronize : OperatorObserverBase 24 | { 25 | readonly SynchronizeObservable parent; 26 | 27 | public Synchronize(SynchronizeObservable parent, IObserver observer, IDisposable cancel) : base(observer, cancel) 28 | { 29 | this.parent = parent; 30 | } 31 | 32 | public override void OnNext(T value) 33 | { 34 | lock (parent.gate) 35 | { 36 | base.observer.OnNext(value); 37 | } 38 | } 39 | 40 | public override void OnError(Exception error) 41 | { 42 | lock (parent.gate) 43 | { 44 | try { observer.OnError(error); } finally { Dispose(); }; 45 | } 46 | } 47 | 48 | public override void OnCompleted() 49 | { 50 | lock (parent.gate) 51 | { 52 | try { observer.OnCompleted(); } finally { Dispose(); }; 53 | } 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/SynchronizedObserver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class SynchronizedObserver : IObserver 6 | { 7 | readonly IObserver observer; 8 | readonly object gate; 9 | 10 | public SynchronizedObserver(IObserver observer, object gate) 11 | { 12 | this.observer = observer; 13 | this.gate = gate; 14 | } 15 | 16 | public void OnNext(T value) 17 | { 18 | lock (gate) 19 | { 20 | observer.OnNext(value); 21 | } 22 | } 23 | 24 | public void OnError(Exception error) 25 | { 26 | lock (gate) 27 | { 28 | observer.OnError(error); 29 | } 30 | } 31 | 32 | public void OnCompleted() 33 | { 34 | lock (gate) 35 | { 36 | observer.OnCompleted(); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/ThrottleFirst.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class ThrottleFirstObservable : OperatorObservableBase 6 | { 7 | readonly IObservable source; 8 | readonly TimeSpan dueTime; 9 | readonly IScheduler scheduler; 10 | 11 | public ThrottleFirstObservable(IObservable source, TimeSpan dueTime, IScheduler scheduler) 12 | : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread()) 13 | { 14 | this.source = source; 15 | this.dueTime = dueTime; 16 | this.scheduler = scheduler; 17 | } 18 | 19 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 20 | { 21 | return new ThrottleFirst(this, observer, cancel).Run(); 22 | } 23 | 24 | class ThrottleFirst : OperatorObserverBase 25 | { 26 | readonly ThrottleFirstObservable parent; 27 | readonly object gate = new object(); 28 | bool open = true; 29 | SerialDisposable cancelable; 30 | 31 | public ThrottleFirst(ThrottleFirstObservable parent, IObserver observer, IDisposable cancel) : base(observer, cancel) 32 | { 33 | this.parent = parent; 34 | } 35 | 36 | public IDisposable Run() 37 | { 38 | cancelable = new SerialDisposable(); 39 | var subscription = parent.source.Subscribe(this); 40 | 41 | return StableCompositeDisposable.Create(cancelable, subscription); 42 | } 43 | 44 | void OnNext() 45 | { 46 | lock (gate) 47 | { 48 | open = true; 49 | } 50 | } 51 | 52 | public override void OnNext(T value) 53 | { 54 | lock (gate) 55 | { 56 | if (!open) return; 57 | observer.OnNext(value); 58 | open = false; 59 | } 60 | 61 | var d = new SingleAssignmentDisposable(); 62 | cancelable.Disposable = d; 63 | d.Disposable = parent.scheduler.Schedule(parent.dueTime, OnNext); 64 | } 65 | 66 | public override void OnError(Exception error) 67 | { 68 | cancelable.Dispose(); 69 | 70 | lock (gate) 71 | { 72 | try { observer.OnError(error); } finally { Dispose(); } 73 | } 74 | } 75 | 76 | public override void OnCompleted() 77 | { 78 | cancelable.Dispose(); 79 | 80 | lock (gate) 81 | { 82 | try { observer.OnCompleted(); } finally { Dispose(); } 83 | } 84 | } 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Throw.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class ThrowObservable : OperatorObservableBase 6 | { 7 | readonly Exception error; 8 | readonly IScheduler scheduler; 9 | 10 | public ThrowObservable(Exception error, IScheduler scheduler) 11 | : base(scheduler == Scheduler.CurrentThread) 12 | { 13 | this.error = error; 14 | this.scheduler = scheduler; 15 | } 16 | 17 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 18 | { 19 | observer = new Throw(observer, cancel); 20 | 21 | if (scheduler == Scheduler.Immediate) 22 | { 23 | observer.OnError(error); 24 | return Disposable.Empty; 25 | } 26 | else 27 | { 28 | return scheduler.Schedule(() => 29 | { 30 | observer.OnError(error); 31 | observer.OnCompleted(); 32 | }); 33 | } 34 | } 35 | 36 | class Throw : OperatorObserverBase 37 | { 38 | public Throw(IObserver observer, IDisposable cancel) 39 | : base(observer, cancel) 40 | { 41 | } 42 | 43 | public override void OnNext(T value) 44 | { 45 | try 46 | { 47 | base.observer.OnNext(value); 48 | } 49 | catch 50 | { 51 | Dispose(); 52 | throw; 53 | } 54 | } 55 | 56 | public override void OnError(Exception error) 57 | { 58 | try { observer.OnError(error); } 59 | finally { Dispose(); } 60 | } 61 | 62 | public override void OnCompleted() 63 | { 64 | try { observer.OnCompleted(); } 65 | finally { Dispose(); } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/TimeInterval.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class TimeIntervalObservable : OperatorObservableBase> 6 | { 7 | readonly IObservable source; 8 | readonly IScheduler scheduler; 9 | 10 | public TimeIntervalObservable(IObservable source, IScheduler scheduler) 11 | : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | this.scheduler = scheduler; 15 | } 16 | 17 | protected override IDisposable SubscribeCore(IObserver> observer, IDisposable cancel) 18 | { 19 | return source.Subscribe(new TimeInterval(this, observer, cancel)); 20 | } 21 | 22 | class TimeInterval : OperatorObserverBase> 23 | { 24 | readonly TimeIntervalObservable parent; 25 | DateTimeOffset lastTime; 26 | 27 | public TimeInterval(TimeIntervalObservable parent, IObserver> observer, IDisposable cancel) 28 | : base(observer, cancel) 29 | { 30 | this.parent = parent; 31 | this.lastTime = parent.scheduler.Now; 32 | } 33 | 34 | public override void OnNext(T value) 35 | { 36 | var now = parent.scheduler.Now; 37 | var span = now.Subtract(lastTime); 38 | lastTime = now; 39 | 40 | base.observer.OnNext(new UtyRx.TimeInterval(value, span)); 41 | } 42 | 43 | public override void OnError(Exception error) 44 | { 45 | try { observer.OnError(error); } 46 | finally { Dispose(); } 47 | } 48 | 49 | public override void OnCompleted() 50 | { 51 | try { observer.OnCompleted(); } 52 | finally { Dispose(); } 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Timestamp.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class TimestampObservable : OperatorObservableBase> 6 | { 7 | readonly IObservable source; 8 | readonly IScheduler scheduler; 9 | 10 | public TimestampObservable(IObservable source, IScheduler scheduler) 11 | : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | this.scheduler = scheduler; 15 | } 16 | 17 | protected override IDisposable SubscribeCore(IObserver> observer, IDisposable cancel) 18 | { 19 | return source.Subscribe(new Timestamp(this, observer, cancel)); 20 | } 21 | 22 | class Timestamp : OperatorObserverBase> 23 | { 24 | readonly TimestampObservable parent; 25 | 26 | public Timestamp(TimestampObservable parent, IObserver> observer, IDisposable cancel) 27 | : base(observer, cancel) 28 | { 29 | this.parent = parent; 30 | } 31 | 32 | public override void OnNext(T value) 33 | { 34 | base.observer.OnNext(new Timestamped(value, parent.scheduler.Now)); 35 | } 36 | 37 | public override void OnError(Exception error) 38 | { 39 | try { observer.OnError(error); } 40 | finally { Dispose(); } 41 | } 42 | 43 | public override void OnCompleted() 44 | { 45 | try { observer.OnCompleted(); } 46 | finally { Dispose(); } 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/ToArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class ToArrayObservable : OperatorObservableBase 7 | { 8 | readonly IObservable source; 9 | 10 | public ToArrayObservable(IObservable source) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | } 15 | 16 | protected override IDisposable SubscribeCore(IObserver observer, IDisposable cancel) 17 | { 18 | return source.Subscribe(new ToArray(observer, cancel)); 19 | } 20 | 21 | class ToArray : OperatorObserverBase 22 | { 23 | readonly List list = new List(); 24 | 25 | public ToArray(IObserver observer, IDisposable cancel) 26 | : base(observer, cancel) 27 | { 28 | } 29 | 30 | public override void OnNext(TSource value) 31 | { 32 | try 33 | { 34 | list.Add(value); // sometimes cause error on multithread 35 | } 36 | catch (Exception ex) 37 | { 38 | try { observer.OnError(ex); } finally { Dispose(); } 39 | return; 40 | } 41 | } 42 | 43 | public override void OnError(Exception error) 44 | { 45 | try { observer.OnError(error); } finally { Dispose(); } 46 | } 47 | 48 | public override void OnCompleted() 49 | { 50 | TSource[] result; 51 | try 52 | { 53 | result = list.ToArray(); 54 | } 55 | catch (Exception ex) 56 | { 57 | try { observer.OnError(ex); } finally { Dispose(); } 58 | return; 59 | } 60 | 61 | base.observer.OnNext(result); 62 | try { observer.OnCompleted(); } finally { Dispose(); }; 63 | } 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/ToList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx.Operators 5 | { 6 | internal class ToListObservable : OperatorObservableBase> 7 | { 8 | readonly IObservable source; 9 | 10 | public ToListObservable(IObservable source) 11 | : base(source.IsRequiredSubscribeOnCurrentThread()) 12 | { 13 | this.source = source; 14 | } 15 | 16 | protected override IDisposable SubscribeCore(IObserver> observer, IDisposable cancel) 17 | { 18 | return source.Subscribe(new ToList(observer, cancel)); 19 | } 20 | 21 | class ToList : OperatorObserverBase> 22 | { 23 | readonly List list = new List(); 24 | 25 | public ToList(IObserver> observer, IDisposable cancel) 26 | : base(observer, cancel) 27 | { 28 | } 29 | 30 | public override void OnNext(TSource value) 31 | { 32 | try 33 | { 34 | list.Add(value); // sometimes cause error on multithread 35 | } 36 | catch (Exception ex) 37 | { 38 | try { observer.OnError(ex); } finally { Dispose(); } 39 | return; 40 | } 41 | } 42 | 43 | public override void OnError(Exception error) 44 | { 45 | try { observer.OnError(error); } finally { Dispose(); } 46 | } 47 | 48 | public override void OnCompleted() 49 | { 50 | base.observer.OnNext(list); 51 | try { observer.OnCompleted(); } finally { Dispose(); }; 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Operators/Wait.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx.Operators 4 | { 5 | internal class Wait : IObserver 6 | { 7 | static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, -1); // from .NET 4.5 8 | 9 | readonly IObservable source; 10 | readonly TimeSpan timeout; 11 | 12 | System.Threading.ManualResetEvent semaphore; 13 | 14 | bool seenValue = false; 15 | T value = default(T); 16 | Exception ex = default(Exception); 17 | 18 | public Wait(IObservable source, TimeSpan timeout) 19 | { 20 | this.source = source; 21 | this.timeout = timeout; 22 | } 23 | 24 | public T Run() 25 | { 26 | semaphore = new System.Threading.ManualResetEvent(false); 27 | using (source.Subscribe(this)) 28 | { 29 | var waitComplete = (timeout == InfiniteTimeSpan) 30 | ? semaphore.WaitOne() 31 | : semaphore.WaitOne(timeout); 32 | 33 | if (!waitComplete) 34 | { 35 | throw new TimeoutException("OnCompleted not fired."); 36 | } 37 | } 38 | 39 | if (ex != null) throw ex; 40 | if (!seenValue) throw new InvalidOperationException("No Elements."); 41 | 42 | return value; 43 | } 44 | 45 | public void OnNext(T value) 46 | { 47 | seenValue = true; 48 | this.value = value; 49 | } 50 | 51 | public void OnError(Exception error) 52 | { 53 | this.ex = error; 54 | semaphore.Set(); 55 | } 56 | 57 | public void OnCompleted() 58 | { 59 | semaphore.Set(); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UtyRx")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UtyRx")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("87a66a4c-1061-4fc9-96a7-33145c818858")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Schedulers/IScheduler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | public interface IScheduler 6 | { 7 | DateTimeOffset Now { get; } 8 | 9 | // Interface is changed from official Rx for avoid iOS AOT problem (state is dangerous). 10 | 11 | IDisposable Schedule(Action action); 12 | 13 | IDisposable Schedule(TimeSpan dueTime, Action action); 14 | } 15 | 16 | public interface ISchedulerPeriodic 17 | { 18 | IDisposable SchedulePeriodic(TimeSpan period, Action action); 19 | } 20 | 21 | public interface ISchedulerLongRunning 22 | { 23 | IDisposable ScheduleLongRunning(Action action); 24 | } 25 | 26 | public interface ISchedulerQueueing 27 | { 28 | void ScheduleQueueing(ICancelable cancel, T state, Action action); 29 | } 30 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Schedulers/Scheduler.Immediate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | namespace UtyRx 8 | { 9 | public static partial class Scheduler 10 | { 11 | public static readonly IScheduler Immediate = new ImmediateScheduler(); 12 | 13 | class ImmediateScheduler : IScheduler 14 | { 15 | public ImmediateScheduler() 16 | { 17 | } 18 | 19 | public DateTimeOffset Now 20 | { 21 | get { return Scheduler.Now; } 22 | } 23 | 24 | public IDisposable Schedule(Action action) 25 | { 26 | action(); 27 | return Disposable.Empty; 28 | } 29 | 30 | public IDisposable Schedule(TimeSpan dueTime, Action action) 31 | { 32 | var wait = Scheduler.Normalize(dueTime); 33 | if (wait.Ticks > 0) 34 | { 35 | Thread.Sleep(wait); 36 | } 37 | 38 | action(); 39 | return Disposable.Empty; 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Schedulers/Scheduler.Main.cs: -------------------------------------------------------------------------------- 1 | namespace UtyRx 2 | { 3 | public partial class Scheduler 4 | { 5 | // NOTE Client app is responsible for setting the proper Scheduler 6 | public static IScheduler MainThread; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /utyrx/UtyRx/Subjects/ConnectableObservable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | public interface IConnectableObservable : IObservable 6 | { 7 | IDisposable Connect(); 8 | } 9 | 10 | public static partial class Observable 11 | { 12 | class ConnectableObservable : IConnectableObservable 13 | { 14 | readonly IObservable source; 15 | readonly ISubject subject; 16 | readonly object gate = new object(); 17 | Connection connection; 18 | 19 | public ConnectableObservable(IObservable source, ISubject subject) 20 | { 21 | this.source = source.AsObservable(); 22 | this.subject = subject; 23 | } 24 | 25 | public IDisposable Connect() 26 | { 27 | lock (gate) 28 | { 29 | // don't subscribe twice 30 | if (connection == null) 31 | { 32 | var subscription = source.Subscribe(subject); 33 | connection = new Connection(this, subscription); 34 | } 35 | 36 | return connection; 37 | } 38 | } 39 | 40 | public IDisposable Subscribe(IObserver observer) 41 | { 42 | return subject.Subscribe(observer); 43 | } 44 | 45 | class Connection : IDisposable 46 | { 47 | readonly ConnectableObservable parent; 48 | IDisposable subscription; 49 | 50 | public Connection(ConnectableObservable parent, IDisposable subscription) 51 | { 52 | this.parent = parent; 53 | this.subscription = subscription; 54 | } 55 | 56 | public void Dispose() 57 | { 58 | lock (parent.gate) 59 | { 60 | if (subscription != null) 61 | { 62 | subscription.Dispose(); 63 | subscription = null; 64 | parent.connection = null; 65 | } 66 | } 67 | } 68 | } 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Subjects/ISubject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace UtyRx 6 | { 7 | public interface ISubject : IObserver, IObservable 8 | { 9 | } 10 | 11 | public interface ISubject : ISubject, IObserver, IObservable 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/Subjects/SubjectExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | public static class SubjectExtensions 6 | { 7 | public static ISubject Synchronize(this ISubject subject) 8 | { 9 | return new AnonymousSubject((subject as IObserver).Synchronize(), subject); 10 | } 11 | 12 | public static ISubject Synchronize(this ISubject subject, object gate) 13 | { 14 | return new AnonymousSubject((subject as IObserver).Synchronize(gate), subject); 15 | } 16 | 17 | class AnonymousSubject : ISubject 18 | { 19 | readonly IObserver observer; 20 | readonly IObservable observable; 21 | 22 | public AnonymousSubject(IObserver observer, IObservable observable) 23 | { 24 | this.observer = observer; 25 | this.observable = observable; 26 | } 27 | 28 | public void OnCompleted() 29 | { 30 | observer.OnCompleted(); 31 | } 32 | 33 | public void OnError(Exception error) 34 | { 35 | if (error == null) throw new ArgumentNullException("error"); 36 | 37 | observer.OnError(error); 38 | } 39 | 40 | public void OnNext(T value) 41 | { 42 | observer.OnNext(value); 43 | } 44 | 45 | public IDisposable Subscribe(IObserver observer) 46 | { 47 | if (observer == null) throw new ArgumentNullException("observer"); 48 | 49 | return observable.Subscribe(observer); 50 | } 51 | } 52 | 53 | class AnonymousSubject : AnonymousSubject, ISubject 54 | { 55 | public AnonymousSubject(IObserver observer, IObservable observable) 56 | : base(observer, observable) 57 | { 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/System/CancellationToken.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | public class CancellationToken 6 | { 7 | private readonly ICancelable _source; 8 | 9 | public static CancellationToken Empty = new CancellationToken(new BooleanDisposable()); 10 | 11 | public CancellationToken(ICancelable source) 12 | { 13 | if (source == null) throw new ArgumentNullException("source"); 14 | 15 | this._source = source; 16 | } 17 | 18 | public bool IsCancellationRequested 19 | { 20 | get 21 | { 22 | return _source.IsDisposed; 23 | } 24 | } 25 | 26 | public void ThrowIfCancellationRequested() 27 | { 28 | if (IsCancellationRequested) 29 | { 30 | throw new OperationCanceledException(); 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /utyrx/UtyRx/System/IObservable.cs: -------------------------------------------------------------------------------- 1 | // defined from .NET Framework 4.0 and NETFX_CORE 2 | 3 | using System; 4 | 5 | #if !NETFX_CORE 6 | 7 | namespace UtyRx 8 | { 9 | public interface IObservable 10 | { 11 | IDisposable Subscribe(IObserver observer); 12 | } 13 | } 14 | 15 | #endif 16 | 17 | namespace UtyRx 18 | { 19 | public interface IGroupedObservable : IObservable 20 | { 21 | TKey Key { get; } 22 | } 23 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/System/IObserver.cs: -------------------------------------------------------------------------------- 1 | // defined from .NET Framework 4.0 and NETFX_CORE 2 | 3 | #if !NETFX_CORE 4 | 5 | using System; 6 | 7 | namespace UtyRx 8 | { 9 | public interface IObserver 10 | { 11 | void OnCompleted(); 12 | void OnError(Exception error); 13 | void OnNext(T value); 14 | } 15 | } 16 | 17 | #endif -------------------------------------------------------------------------------- /utyrx/UtyRx/System/IOptimizedObservable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UtyRx 4 | { 5 | public interface IOptimizedObservable : IObservable 6 | { 7 | bool IsRequiredSubscribeOnCurrentThread(); 8 | } 9 | 10 | public static class OptimizedObservableExtensions 11 | { 12 | public static bool IsRequiredSubscribeOnCurrentThread(this IObservable source) 13 | { 14 | var obs = source as IOptimizedObservable; 15 | if (obs == null) return true; 16 | 17 | return obs.IsRequiredSubscribeOnCurrentThread(); 18 | } 19 | 20 | public static bool IsRequiredSubscribeOnCurrentThread(this IObservable source, IScheduler scheduler) 21 | { 22 | if (scheduler == Scheduler.CurrentThread) return true; 23 | 24 | return IsRequiredSubscribeOnCurrentThread(source); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/System/IProgress.cs: -------------------------------------------------------------------------------- 1 | // defined from .NET Framework 4.5 and NETFX_CORE 2 | 3 | #if !NETFX_CORE 4 | 5 | using System; 6 | 7 | namespace UtyRx 8 | { 9 | public interface IProgress 10 | { 11 | void Report(T value); 12 | } 13 | 14 | public class Progress : IProgress 15 | { 16 | readonly Action report; 17 | 18 | public Progress(Action report) 19 | { 20 | this.report = report; 21 | } 22 | 23 | public void Report(T value) 24 | { 25 | report(value); 26 | } 27 | } 28 | } 29 | 30 | #endif -------------------------------------------------------------------------------- /utyrx/UtyRx/System/Pair.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace UtyRx 5 | { 6 | // Pair is used for Observable.Pairwise 7 | [Serializable] 8 | public struct Pair : IEquatable> 9 | { 10 | readonly T previous; 11 | readonly T current; 12 | 13 | public T Previous 14 | { 15 | get { return previous; } 16 | } 17 | 18 | public T Current 19 | { 20 | get { return current; } 21 | } 22 | 23 | public Pair(T previous, T current) 24 | { 25 | this.previous = previous; 26 | this.current = current; 27 | } 28 | 29 | public override int GetHashCode() 30 | { 31 | var comparer = EqualityComparer.Default; 32 | 33 | int h0; 34 | h0 = comparer.GetHashCode(previous); 35 | h0 = (h0 << 5) + h0 ^ comparer.GetHashCode(current); 36 | return h0; 37 | } 38 | 39 | public override bool Equals(object obj) 40 | { 41 | if (!(obj is Pair)) return false; 42 | 43 | return Equals((Pair)obj); 44 | } 45 | 46 | public bool Equals(Pair other) 47 | { 48 | var comparer = EqualityComparer.Default; 49 | 50 | return comparer.Equals(previous, other.Previous) && 51 | comparer.Equals(current, other.Current); 52 | } 53 | 54 | public override string ToString() 55 | { 56 | return string.Format("({0}, {1})", previous, current); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /utyrx/UtyRx/System/Unit.cs: -------------------------------------------------------------------------------- 1 | // from Rx Official, but convert struct to class(for iOS AOT issue) 2 | 3 | using System; 4 | 5 | namespace UtyRx 6 | { 7 | [Serializable] 8 | public struct Unit : IEquatable 9 | { 10 | static readonly Unit @default = new Unit(); 11 | 12 | public static Unit Default { get { return @default; } } 13 | 14 | public static bool operator ==(Unit first, Unit second) 15 | { 16 | return true; 17 | } 18 | 19 | public static bool operator !=(Unit first, Unit second) 20 | { 21 | return false; 22 | } 23 | 24 | public bool Equals(Unit other) 25 | { 26 | return true; 27 | } 28 | public override bool Equals(object obj) 29 | { 30 | return obj is Unit; 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | return 0; 36 | } 37 | 38 | public override string ToString() 39 | { 40 | return "()"; 41 | } 42 | } 43 | } --------------------------------------------------------------------------------