diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..1e8d0c9
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,46 @@
+version: 2.1
+
+defaults: &defaults
+  working_directory: ~/repo
+  docker:
+    - image: mcr.microsoft.com/dotnet/core/sdk:2.2
+      environment:
+        DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
+        DOTNET_CLI_TELEMETRY_OPTOUT: 1
+
+jobs:
+  test:
+    <<: *defaults
+    steps:
+      - checkout
+      - run: dotnet restore
+      - run: dotnet build -c Release
+      - run: dotnet test -c Release
+      - persist_to_workspace:
+          root: .
+          paths: ./encompass-cs/bin
+
+  deploy:
+    <<: *defaults
+    steps:
+      - checkout
+      - attach_workspace:
+          at: .
+      - run: dotnet nuget push ./encompass-cs/bin/Release/EncompassECS.Framework.*.nupkg -k $API_KEY -s $NUGET_SOURCE
+
+workflows:
+  version: 2
+  test_and_deploy:
+    jobs:
+      - test:
+          filters:
+            tags:
+              only: /.*/
+      - deploy:
+          requires:
+            - test
+          filters:
+            branches:
+              ignore: /.*/
+            tags:
+              only: /^\d+\.\d+\.\d+$/
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 22fb9ab..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-dist: xenial
-language: csharp
-solution: encompass-cs.sln
-mono: none
-dotnet: 2.1.502
-
-script:
-  - dotnet restore
-  - dotnet build -c Release
-  - dotnet test -c Release
-
-deploy:
-  skip_cleanup: true
-  provider: script
-  script: dotnet nuget push ./encompass-cs/bin/Release/EncompassECS.Framework.*.nupkg -k $API_KEY -s $NUGET_SOURCE
-  on:
-    tags: true
-    repo: encompass-ecs/encompass-cs
diff --git a/TODO b/TODO
index 8afe268..ff167bf 100644
--- a/TODO
+++ b/TODO
@@ -6,4 +6,6 @@
 
 - maybe AddEngine should take a constructed engine similarly to AddComponent?
 
+- component getters should return ValueTuple instead of KeyValuePair so we can do destructuring assignments
+
 - docs
diff --git a/encompass-cs/ComponentManager.cs b/encompass-cs/ComponentManager.cs
index 8ba9fa6..2e386ee 100644
--- a/encompass-cs/ComponentManager.cs
+++ b/encompass-cs/ComponentManager.cs
@@ -81,38 +81,38 @@ namespace Encompass
                 Enumerable.Empty<Guid>();
         }
 
-        internal IEnumerable<KeyValuePair<Guid, IComponent>> GetComponentsByEntity(Guid entityID)
+        internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntity(Guid entityID)
         {
-            return GetComponentIDsByEntityID(entityID).Intersect(activeComponents).Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id]));
+            return GetComponentIDsByEntityID(entityID).Intersect(activeComponents).Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id]));
         }
 
-        internal IEnumerable<KeyValuePair<Guid, TComponent>> GetActiveComponentsByType<TComponent>() where TComponent : struct, IComponent
+        internal IEnumerable<ValueTuple<Guid, TComponent>> GetActiveComponentsByType<TComponent>() where TComponent : struct, IComponent
         {
             return typeToComponentIDs.ContainsKey(typeof(TComponent)) ?
-                typeToComponentIDs[typeof(TComponent)].Select((id) => new KeyValuePair<Guid, TComponent>(id, (TComponent)IDToComponent[id])) :
-                Enumerable.Empty<KeyValuePair<Guid, TComponent>>();
+                typeToComponentIDs[typeof(TComponent)].Select((id) => new ValueTuple<Guid, TComponent>(id, (TComponent)IDToComponent[id])) :
+                Enumerable.Empty<ValueTuple<Guid, TComponent>>();
         }
 
-        internal IEnumerable<KeyValuePair<Guid, IComponent>> GetActiveComponentsByType(Type type)
+        internal IEnumerable<ValueTuple<Guid, IComponent>> GetActiveComponentsByType(Type type)
         {
             return typeToComponentIDs.ContainsKey(type) ?
-                typeToComponentIDs[type].Select((id) => new KeyValuePair<Guid, IComponent>(id, IDToComponent[id])) :
-                Enumerable.Empty<KeyValuePair<Guid, IComponent>>();
+                typeToComponentIDs[type].Select((id) => new ValueTuple<Guid, IComponent>(id, IDToComponent[id])) :
+                Enumerable.Empty<ValueTuple<Guid, IComponent>>();
         }
 
-        internal KeyValuePair<Guid, TComponent> GetActiveComponentByType<TComponent>() where TComponent : struct, IComponent
+        internal ValueTuple<Guid, TComponent> GetActiveComponentByType<TComponent>() where TComponent : struct, IComponent
         {
             return GetActiveComponentsByType<TComponent>().Single();
         }
 
-        internal IEnumerable<KeyValuePair<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent
+        internal IEnumerable<ValueTuple<Guid, TComponent>> GetComponentsByEntityAndType<TComponent>(Guid entityID) where TComponent : struct, IComponent
         {
-            var entityComponentsByType = GetComponentsByEntity(entityID).Where((pair) => componentIDToType[pair.Key] == typeof(TComponent)).Select((pair) => new KeyValuePair<Guid, TComponent>(pair.Key, (TComponent)pair.Value));
+            var entityComponentsByType = GetComponentsByEntity(entityID).Where((pair) => componentIDToType[pair.Item1] == typeof(TComponent)).Select((pair) => new ValueTuple<Guid, TComponent>(pair.Item1, (TComponent)pair.Item2));
             var activeComponentsByType = GetActiveComponentsByType<TComponent>();
             return activeComponentsByType.Intersect(entityComponentsByType);
         }
 
-        internal IEnumerable<KeyValuePair<Guid, IComponent>> GetComponentsByEntityAndType(Guid entityID, Type type)
+        internal IEnumerable<ValueTuple<Guid, IComponent>> GetComponentsByEntityAndType(Guid entityID, Type type)
         {
             var entityComponents = GetComponentsByEntity(entityID);
             var activeComponentsByType = GetActiveComponentsByType(type);
@@ -151,7 +151,6 @@ namespace Encompass
 
         internal void UpdateComponent<TComponent>(Guid componentID, TComponent newComponentValue) where TComponent : struct, IComponent
         {
-            var entityID = GetEntityIDByComponentID(componentID);
             IDToComponent[componentID] = newComponentValue;
         }
 
diff --git a/encompass-cs/Engine.cs b/encompass-cs/Engine.cs
index 2257b39..89aa8db 100644
--- a/encompass-cs/Engine.cs
+++ b/encompass-cs/Engine.cs
@@ -86,12 +86,12 @@ namespace Encompass
             }
         }
 
-        protected IEnumerable<KeyValuePair<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
+        protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
         {
             return componentManager.GetActiveComponentsByType<TComponent>();
         }
 
-        protected KeyValuePair<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
+        protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
         {
             return componentManager.GetActiveComponentByType<TComponent>();
         }
diff --git a/encompass-cs/Entity.cs b/encompass-cs/Entity.cs
index c39ce78..20b3101 100644
--- a/encompass-cs/Entity.cs
+++ b/encompass-cs/Entity.cs
@@ -26,12 +26,12 @@ namespace Encompass
             return componentManager.AddDrawComponent(id, component, layer);
         }
 
-        public IEnumerable<KeyValuePair<Guid, TComponent>> GetComponents<TComponent>() where TComponent : struct, IComponent
+        public IEnumerable<ValueTuple<Guid, TComponent>> GetComponents<TComponent>() where TComponent : struct, IComponent
         {
             return componentManager.GetComponentsByEntityAndType<TComponent>(id);
         }
 
-        public KeyValuePair<Guid, TComponent> GetComponent<TComponent>() where TComponent : struct, IComponent
+        public ValueTuple<Guid, TComponent> GetComponent<TComponent>() where TComponent : struct, IComponent
         {
             return GetComponents<TComponent>().First();
         }
diff --git a/encompass-cs/Renderer.cs b/encompass-cs/Renderer.cs
index 1cf3351..9f4c860 100644
--- a/encompass-cs/Renderer.cs
+++ b/encompass-cs/Renderer.cs
@@ -24,12 +24,12 @@ namespace Encompass
             return entityManager.GetEntity(entityID);
         }
 
-        protected IEnumerable<KeyValuePair<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
+        protected IEnumerable<ValueTuple<Guid, TComponent>> ReadComponents<TComponent>() where TComponent : struct, IComponent
         {
             return componentManager.GetActiveComponentsByType<TComponent>();
         }
 
-        protected KeyValuePair<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
+        protected ValueTuple<Guid, TComponent> ReadComponent<TComponent>() where TComponent : struct, IComponent
         {
             return componentManager.GetActiveComponentByType<TComponent>();
         }
diff --git a/encompass-cs/WorldBuilder.cs b/encompass-cs/WorldBuilder.cs
index 1c18b9b..2d1157d 100644
--- a/encompass-cs/WorldBuilder.cs
+++ b/encompass-cs/WorldBuilder.cs
@@ -102,9 +102,8 @@ namespace Encompass
             return engine;
         }
 
-        public TRenderer AddEntityRenderer<TRenderer>() where TRenderer : Renderer, new()
+        public TRenderer AddEntityRenderer<TRenderer>(TRenderer renderer) where TRenderer : Renderer
         {
-            var renderer = new TRenderer();
             renderer.AssignEntityManager(entityManager);
             renderer.AssignComponentManager(componentManager);
 
@@ -117,9 +116,8 @@ namespace Encompass
             return renderer;
         }
 
-        public TRenderer AddGeneralRenderer<TRenderer>(int layer) where TRenderer : GeneralRenderer, new()
+        public TRenderer AddGeneralRenderer<TRenderer>(TRenderer renderer, int layer) where TRenderer : GeneralRenderer
         {
-            var renderer = new TRenderer();
             renderer.AssignEntityManager(entityManager);
             renderer.AssignComponentManager(componentManager);
 
diff --git a/encompass-cs/encompass-cs.csproj b/encompass-cs/encompass-cs.csproj
index 1d1dbdd..8f1ba02 100644
--- a/encompass-cs/encompass-cs.csproj
+++ b/encompass-cs/encompass-cs.csproj
@@ -4,7 +4,7 @@
     <TargetFramework>netstandard2.0</TargetFramework>
     <RootNamespace>Encompass</RootNamespace>
     <PackageId>EncompassECS.Framework</PackageId>
-    <Version>0.4.0</Version>
+    <Version>0.5.0</Version>
     <Authors>Evan Hemsley</Authors>
     <PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
     <Company>Moonside Games</Company>
diff --git a/encompass-cs/exceptions/ComponentTypeMismatchException.cs b/encompass-cs/exceptions/ComponentTypeMismatchException.cs
index d28e7c4..17caf96 100644
--- a/encompass-cs/exceptions/ComponentTypeMismatchException.cs
+++ b/encompass-cs/exceptions/ComponentTypeMismatchException.cs
@@ -1,6 +1,6 @@
 using System;
 
-namespace Encompass
+namespace Encompass.Exceptions
 {
     public class ComponentTypeMismatchException : Exception
     {
diff --git a/test/EngineTest.cs b/test/EngineTest.cs
index 50f2b22..88b58ec 100644
--- a/test/EngineTest.cs
+++ b/test/EngineTest.cs
@@ -12,7 +12,7 @@ namespace Tests
 {
     public class EngineTest
     {
-        static List<KeyValuePair<Guid, MockComponent>> resultComponents;
+        static List<ValueTuple<Guid, MockComponent>> resultComponents;
         static MockComponent resultComponent;
 
         static List<MockMessage> resultMessages;
@@ -21,7 +21,7 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                resultComponents = this.ReadComponents<MockComponent>().ToList();
+                resultComponents = ReadComponents<MockComponent>().ToList();
             }
         }
 
@@ -29,7 +29,7 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                resultComponent = this.ReadComponent<MockComponent>().Value;
+                resultComponent = ReadComponent<MockComponent>().Item2;
             }
         }
 
@@ -56,7 +56,7 @@ namespace Tests
 
             world.Update(0.01f);
 
-            var resultComponentValues = resultComponents.Select((kv) => kv.Value);
+            var resultComponentValues = resultComponents.Select((kv) => kv.Item2);
             resultComponentValues.Should().Contain(mockComponent);
             resultComponentValues.Should().Contain(mockComponentB);
         }
@@ -111,13 +111,13 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                (var componentID, var component) = this.ReadComponent<MockComponent>();
+                (var componentID, var component) = ReadComponent<MockComponent>();
 
                 component.myInt = 420;
                 component.myString = "blaze it";
-                this.UpdateComponent(componentID, component);
+                UpdateComponent(componentID, component);
 
-                resultComponent = this.ReadComponent<MockComponent>().Value;
+                resultComponent = ReadComponent<MockComponent>().Item2;
             }
         }
 
@@ -151,9 +151,9 @@ namespace Tests
 
                 component.myInt = 420;
                 component.myString = "blaze it";
-                this.UpdateComponent(componentID, component);
+                UpdateComponent(componentID, component);
 
-                component = this.ReadComponent<MockComponent>().Value;
+                component = ReadComponent<MockComponent>().Item2;
             }
         }
 
@@ -320,8 +320,8 @@ namespace Tests
             Assert.Throws<IllegalMessageReadException>(() => world.Update(0.01f));
         }
 
-        static KeyValuePair<Guid, MockComponent> pairA;
-        static KeyValuePair<Guid, MockComponent> pairB;
+        static ValueTuple<Guid, MockComponent> pairA;
+        static ValueTuple<Guid, MockComponent> pairB;
 
         class SameValueComponentReadEngine : Engine
         {
@@ -357,10 +357,10 @@ namespace Tests
             world.Update(0.01f);
 
             Assert.That(pairA, Is.Not.EqualTo(pairB));
-            Assert.That(pairA.Value, Is.EqualTo(pairB.Value));
+            Assert.That(pairA.Item2, Is.EqualTo(pairB.Item2));
         }
 
-        static IEnumerable<KeyValuePair<Guid, MockComponent>> emptyComponentReadResult;
+        static IEnumerable<ValueTuple<Guid, MockComponent>> emptyComponentReadResult;
 
         class ReadEmptyMockComponentsEngine : Engine
         {
@@ -388,18 +388,16 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                var componentPairs = ReadComponents<DestroyerComponent>();
-
-                foreach (var componentPair in componentPairs)
+                foreach (var componentPair in ReadComponents<DestroyerComponent>())
                 {
-                    var componentID = componentPair.Key;
+                    var componentID = componentPair.Item1;
                     var entityID = GetEntityIDByComponentID(componentID);
                     Destroy(entityID);
                 }
             }
         }
 
-        static IEnumerable<KeyValuePair<Guid, MockComponent>> results;
+        static IEnumerable<ValueTuple<Guid, MockComponent>> results;
         class ReaderEngine : Engine
         {
             public override void Update(double dt)
@@ -442,7 +440,7 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                var componentID = ReadComponent<MockComponent>().Key;
+                var componentID = ReadComponent<MockComponent>().Item1;
                 entityFromComponentIDResult = GetEntityByComponentID(componentID);
             }
         }
@@ -471,7 +469,7 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                var componentID = ReadComponent<MockComponent>().Key;
+                var componentID = ReadComponent<MockComponent>().Item1;
                 mockComponentByIDResult = GetComponentByID<MockComponent>(componentID);
             }
         }
@@ -500,7 +498,7 @@ namespace Tests
         {
             public override void Update(double dt)
             {
-                var componentID = ReadComponent<MockComponent>().Key;
+                var componentID = ReadComponent<MockComponent>().Item1;
                 GetComponentByID<OtherComponent>(componentID);
             }
         }
diff --git a/test/EntityRendererTest.cs b/test/EntityRendererTest.cs
index ceaf243..75367cf 100644
--- a/test/EntityRendererTest.cs
+++ b/test/EntityRendererTest.cs
@@ -25,7 +25,7 @@ namespace Tests
         public void CheckAndTrackEntities()
         {
             var worldBuilder = new WorldBuilder();
-            var renderer = worldBuilder.AddEntityRenderer<TestRenderer>();
+            var renderer = worldBuilder.AddEntityRenderer(new TestRenderer());
 
             AComponent aComponent;
             BComponent bComponent;
@@ -68,7 +68,7 @@ namespace Tests
         public void InactiveDrawComponent()
         {
             var worldBuilder = new WorldBuilder();
-            var renderer = worldBuilder.AddEntityRenderer<TestRenderer>();
+            var renderer = worldBuilder.AddEntityRenderer(new TestRenderer());
 
             AComponent aComponent;
             BComponent bComponent;
@@ -95,7 +95,7 @@ namespace Tests
         }
 
         static bool calledOnDraw = false;
-        static IEnumerable<KeyValuePair<Guid, TestDrawComponent>> resultComponents;
+        static IEnumerable<ValueTuple<Guid, TestDrawComponent>> resultComponents;
         [Renders(typeof(TestDrawComponent), typeof(AComponent), typeof(CComponent))]
         class CalledRenderer : EntityRenderer
         {
@@ -110,7 +110,7 @@ namespace Tests
         public void RenderMethodCalledOnWorldDraw()
         {
             var worldBuilder = new WorldBuilder();
-            var renderer = worldBuilder.AddEntityRenderer<CalledRenderer>();
+            var renderer = worldBuilder.AddEntityRenderer(new CalledRenderer());
 
             AComponent aComponent;
             CComponent cComponent;
@@ -128,7 +128,7 @@ namespace Tests
 
             Assert.IsTrue(renderer.IsTracking(entity.id));
             Assert.IsTrue(calledOnDraw);
-            resultComponents.Should().Contain(new KeyValuePair<Guid, TestDrawComponent>(testDrawComponentID, testDrawComponent));
+            resultComponents.Should().Contain(new ValueTuple<Guid, TestDrawComponent>(testDrawComponentID, testDrawComponent));
         }
     }
 }
diff --git a/test/EntityTest.cs b/test/EntityTest.cs
index 445bc51..bbd4d9e 100644
--- a/test/EntityTest.cs
+++ b/test/EntityTest.cs
@@ -30,7 +30,7 @@ namespace Tests
             var world = worldBuilder.Build();
 
             Assert.IsTrue(entity.HasComponent<MockComponent>());
-            Assert.That(entity.GetComponent<MockComponent>().Value, Is.EqualTo(mockComponent));
+            Assert.That(entity.GetComponent<MockComponent>().Item2, Is.EqualTo(mockComponent));
         }
 
         [Test]
@@ -58,9 +58,9 @@ namespace Tests
             var world = worldBuilder.Build();
 
             var components = entity.GetComponents<MockComponent>();
-            components.Should().Contain(new KeyValuePair<Guid, MockComponent>(componentAID, mockComponentA));
-            components.Should().Contain(new KeyValuePair<Guid, MockComponent>(componentBID, mockComponentB));
-            components.Should().Contain(new KeyValuePair<Guid, MockComponent>(componentCID, mockComponentC));
+            components.Should().Contain(new ValueTuple<Guid, MockComponent>(componentAID, mockComponentA));
+            components.Should().Contain(new ValueTuple<Guid, MockComponent>(componentBID, mockComponentB));
+            components.Should().Contain(new ValueTuple<Guid, MockComponent>(componentCID, mockComponentC));
         }
 
         [Test]
@@ -77,7 +77,7 @@ namespace Tests
 
             var world = worldBuilder.Build();
 
-            Assert.AreEqual(new KeyValuePair<Guid, MockComponent>(componentID, mockComponent), entity.GetComponent<MockComponent>());
+            Assert.AreEqual(new ValueTuple<Guid, MockComponent>(componentID, mockComponent), entity.GetComponent<MockComponent>());
         }
 
         [Test]
diff --git a/test/GeneralRendererTest.cs b/test/GeneralRendererTest.cs
index 3ada80c..fd0e099 100644
--- a/test/GeneralRendererTest.cs
+++ b/test/GeneralRendererTest.cs
@@ -7,13 +7,13 @@ using Encompass;
 
 namespace Tests
 {
-    public class GeneralRendererTest
+    public static class GeneralRendererTest
     {
         struct AComponent : IComponent { }
 
         public class SingletonRead
         {
-            static KeyValuePair<Guid, AComponent> result;
+            static ValueTuple<Guid, AComponent> result;
 
             class TestRenderer : GeneralRenderer
             {
@@ -27,7 +27,7 @@ namespace Tests
             public void SingletonComponent()
             {
                 var worldBuilder = new WorldBuilder();
-                worldBuilder.AddGeneralRenderer<TestRenderer>(1);
+                worldBuilder.AddGeneralRenderer(new TestRenderer(), 1);
 
                 AComponent aComponent;
 
@@ -39,14 +39,14 @@ namespace Tests
                 world.Update(0.01f);
                 world.Draw();
 
-                Assert.That(result, Is.EqualTo(new KeyValuePair<Guid, AComponent>(componentID, aComponent)));
+                Assert.That(result, Is.EqualTo(new ValueTuple<Guid, AComponent>(componentID, aComponent)));
             }
 
             [Test]
             public void MultipleComponents()
             {
                 var worldBuilder = new WorldBuilder();
-                worldBuilder.AddGeneralRenderer<TestRenderer>(1);
+                worldBuilder.AddGeneralRenderer(new TestRenderer(), 1);
 
                 AComponent aComponent;
                 AComponent aComponentTwo;
diff --git a/test/WorldTest.cs b/test/WorldTest.cs
index f403608..675a75e 100644
--- a/test/WorldTest.cs
+++ b/test/WorldTest.cs
@@ -37,8 +37,8 @@ namespace Tests
         public void DrawOrder()
         {
             var worldBuilder = new WorldBuilder();
-            worldBuilder.AddEntityRenderer<TestEntityRenderer>();
-            var testGeneralRenderer = worldBuilder.AddGeneralRenderer<TestGeneralRenderer>(7);
+            worldBuilder.AddEntityRenderer(new TestEntityRenderer());
+            var testGeneralRenderer = worldBuilder.AddGeneralRenderer(new TestGeneralRenderer(), 7);
 
             TestComponent testComponent;
             TestDrawComponent testDrawComponent = default(TestDrawComponent);