diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd5204b --- /dev/null +++ b/.gitignore @@ -0,0 +1,183 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +build/ +bld/ +[Bb]in/ +[Oo]bj/ + +# Roslyn cache directories +*.ide/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +#NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding addin-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# If using the old MSBuild-Integrated Package Restore, uncomment this: +#!**/packages/repositories.config + +# Windows Azure Build Output +csx/ +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/BootstrapperTests.cs b/AppBoot/iQuarc.AppBoot.UnitTests/BootstrapperTests.cs index cf7d887..1cb3549 100644 --- a/AppBoot/iQuarc.AppBoot.UnitTests/BootstrapperTests.cs +++ b/AppBoot/iQuarc.AppBoot.UnitTests/BootstrapperTests.cs @@ -43,6 +43,7 @@ public void Run_RegistrationBehaviorReturnsOneService_TypeRegistered() IRegistrationBehavior regBehaviorStub = GetRegBehaviorStub(testSi); Mock containerMock = GetFakeContainer(); + Bootstrapper bootstrapper = GetTargetWithAssembly(containerMock); bootstrapper.AddRegistrationBehavior(regBehaviorStub); @@ -51,12 +52,16 @@ public void Run_RegistrationBehaviorReturnsOneService_TypeRegistered() containerMock.Verify(c => c.RegisterService(testSi), Times.AtLeastOnce); } - private Bootstrapper GetTargetWithAssemblyAndFakeContainer() + [Fact] + public void Dispose_DisposableDependencyContainer_DisposesContainer() { - Assembly[] assemblies = {typeof (BootstrapperTests).Assembly}; - IDependencyContainer container = GetFakeContainer().Object; + Mock containerMock = GetFakeContainer(); + Mock disposable = containerMock.As(); - return new Bootstrapper(assemblies, container); + Bootstrapper bootstrapper = GetTargetWithAssembly(containerMock); + + bootstrapper.Dispose(); + disposable.Verify(c => c.Dispose(), Times.Once); } private static Bootstrapper GetTarget(Mock fakeContainer) @@ -91,6 +96,9 @@ private static Mock GetFakeContainer(IServiceLocator servi Mock containerStub = new Mock(); containerStub.Setup(c => c.AsServiceLocator).Returns(serviceLocator); + + containerStub.As(); + return containerStub; } diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/ConventionRegistrationBehaviorTests.cs b/AppBoot/iQuarc.AppBoot.UnitTests/ConventionRegistrationBehaviorTests.cs new file mode 100644 index 0000000..6f4b472 --- /dev/null +++ b/AppBoot/iQuarc.AppBoot.UnitTests/ConventionRegistrationBehaviorTests.cs @@ -0,0 +1,122 @@ +using System.Linq; +using iQuarc.xUnitEx; +using Xunit; + +namespace iQuarc.AppBoot.UnitTests +{ + public class ConventionRegistrationBehaviorTests + { + private readonly ServiceEqualityComparer comparer = new ServiceEqualityComparer(); + + [Fact] + public void GetServicesFrom_TwoConventionsForType_BothExported() + { + ConventionRegistrationBehavior conventions = GetTarget(); + conventions.ForType().Export(b => b.AsContractName("Configuration 1")); + conventions.ForType().Export(b => b.AsContractName("Configuration 2")); + + conventions.GetServicesFrom(typeof (MyService)); + + var services = conventions.GetServicesFrom(typeof (MyService)); + + ServiceInfo[] expected = + { + new ServiceInfo(typeof (MyService), typeof (MyService), "Configuration 1", Lifetime.Instance), + new ServiceInfo(typeof (MyService), typeof (MyService), "Configuration 2", Lifetime.Instance) + }; + AssertEx.AreEquivalent(services, comparer.Equals, expected); + } + + [Fact] + public void GetServicesFrom_NoConventions_NothingExported() + { + ConventionRegistrationBehavior conventions = GetTarget(); + + conventions.GetServicesFrom(typeof (MyService)); + + ServiceInfo[] services = conventions.GetServicesFrom(typeof (MyService)).ToArray(); + Assert.Equal(0, services.Length); + } + + [Fact] + public void ForType_ConfigurationForMatchingType_OneMatches() + { + ConventionRegistrationBehavior behavior = GetTarget(); + + ServiceBuilder serviceBuilder = behavior.ForType(); + + Assert.True(serviceBuilder.IsMatch(typeof (MyService))); + } + + [Fact] + public void ForType_ConfigurationForNonMatchingType_MatchIsFalse() + { + ConventionRegistrationBehavior behavior = GetTarget(); + + ServiceBuilder serviceBuilder = behavior.ForType(); + + Assert.False(serviceBuilder.IsMatch(typeof (MyOtherService))); + } + + [Fact] + public void ForTypesDerivedFrom_ConfigurationWithBaseAndInheritedTypes_MatchIsTrue() + { + ConventionRegistrationBehavior behavior = GetTarget(); + + ServiceBuilder serviceBuilder = behavior.ForTypesDerivedFrom(); + + Assert.True(serviceBuilder.IsMatch(typeof (MyService))); + } + + [Fact] + public void ForTypesDerivedFrom_ConfigurationUnrelatedTypes_MatchIsFalse() + { + ConventionRegistrationBehavior behavior = GetTarget(); + + ServiceBuilder serviceBuilder = behavior.ForTypesDerivedFrom(); + + Assert.False(serviceBuilder.IsMatch(typeof (MyOtherService))); + } + + [Fact] + public void ForTypesMatching_ConfigurationWithServiceSuffix_MatchIsTrue() + { + ConventionRegistrationBehavior behavior = GetTarget(); + + ServiceBuilder serviceBuilder = behavior.ForTypesMatching(t => t.Name.EndsWith("Service")); + + Assert.True(serviceBuilder.IsMatch(typeof(MyService))); + } + + [Fact] + public void ForTypesMatching_ConfigurationWithNoServiceSuffix_MatchIsFalse() + { + ConventionRegistrationBehavior behavior = GetTarget(); + + ServiceBuilder serviceBuilder = behavior.ForTypesMatching(t => t.Name.EndsWith("Service")); + + Assert.False(serviceBuilder.IsMatch(typeof(Repository))); + } + + private class MyService : MyBaseService + { + } + + private class MyOtherService + { + } + + private class MyBaseService + { + } + + private class Repository + { + } + + private static ConventionRegistrationBehavior GetTarget() + { + return new ConventionRegistrationBehavior(); + } + } +} \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/ServiceBuilderTests.cs b/AppBoot/iQuarc.AppBoot.UnitTests/ServiceBuilderTests.cs new file mode 100644 index 0000000..bb5bf60 --- /dev/null +++ b/AppBoot/iQuarc.AppBoot.UnitTests/ServiceBuilderTests.cs @@ -0,0 +1,189 @@ +using System.Collections.Generic; +using System.Linq; +using iQuarc.xUnitEx; +using Xunit; + +namespace iQuarc.AppBoot.UnitTests +{ + public class ServiceBuilderTests + { + private readonly ServiceEqualityComparer comparer = new ServiceEqualityComparer(); + + [Fact] + public void GetServicesFrom_NoExportConfiguration_RegisterService() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(); + + List services = builder.GetServicesFrom(typeof(MyService)).ToList(); + Assert.Equal(1, services.Count); + } + + [Fact] + public void GetServicesFrom_NoExportConfiguration_RegisterSameTypeAsContract() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(); + + ServiceInfo service = builder.GetServicesFrom(typeof(MyService)).First(); + + ServiceInfo expected = new ServiceInfo(typeof(MyService), typeof(MyService), Lifetime.Instance); + + Assert.Equal(expected, service, comparer); + } + + [Fact] + public void GetServicesFrom_ConfigureContractType_RegisterContractType() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(c => c.AsContractType()); + + ServiceInfo service = builder.GetServicesFrom(typeof(MyService)).First(); + + ServiceInfo expected = new ServiceInfo(typeof(MyService), typeof(IMyService1), Lifetime.Instance); + + Assert.Equal(expected, service, comparer); + } + + [Fact] + public void GetServicesFrom_ConfigureContractName_RegisterContractName() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(c => c.AsContractName("MyContract")); + + ServiceInfo service = builder.GetServicesFrom(typeof(MyService)).First(); + + ServiceInfo expected = new ServiceInfo(typeof(MyService), typeof(MyService), "MyContract", Lifetime.Instance); + + Assert.Equal(expected, service, comparer); + } + + [Fact] + public void GetServicesFrom_ConfigureLifetime_RegisterLifetime() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(c => c.WithLifetime(Lifetime.Application)); + + ServiceInfo service = builder.GetServicesFrom(typeof(MyService)).First(); + + ServiceInfo expected = new ServiceInfo(typeof(MyService), typeof(MyService), Lifetime.Application); + + Assert.Equal(expected, service, comparer); + } + + [Fact] + public void GetServicesFrom_ExportInterfacesNoInterfaces_NothingRegistered() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof (MyOtherService)); + builder.ExportInterfaces(); + + ServiceInfo[] service = builder.GetServicesFrom(typeof (MyOtherService)).ToArray(); + + Assert.Equal(0, service.Length); + } + + [Fact] + public void GetServicesFrom_ExportInterfacesMultipleInterfaces_RegisterMultipleContractTypes() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.ExportInterfaces(); + + List services = builder.GetServicesFrom(typeof(MyService)).ToList(); + + ServiceInfo[] expected = + { + new ServiceInfo(typeof (MyService), typeof (IMyService1), Lifetime.Instance), + new ServiceInfo(typeof (MyService), typeof (IMyService2), Lifetime.Instance), + }; + + AssertEx.AreEquivalent(services, comparer.Equals, expected); + } + + [Fact] + public void GetServicesFrom_ExportInterfacesWithFilter_RegisterContractType() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.ExportInterfaces(x => x == typeof(IMyService2)); + + List services = builder.GetServicesFrom(typeof(MyService)).ToList(); + + ServiceInfo expected = new ServiceInfo(typeof (MyService), typeof (IMyService2), Lifetime.Instance); + + AssertEx.AreEquivalent(services, comparer.Equals, expected); + } + + [Fact] + public void GetServicesFrom_ExportInterfacesMultipleInterfacesWithExportConfig_RegisterConfig() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.ExportInterfaces(c => true, b => b.WithLifetime(Lifetime.Application)); + + List services = builder.GetServicesFrom(typeof(MyService)).ToList(); + + ServiceInfo[] expected = + { + new ServiceInfo(typeof (MyService), typeof (IMyService1), Lifetime.Application), + new ServiceInfo(typeof (MyService), typeof (IMyService2), Lifetime.Application), + }; + + AssertEx.AreEquivalent(services, comparer.Equals, expected); + } + + [Fact] + public void GetServicesFrom_MultipleConfigurations_AllConfigurationsExported() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(c => c.AsContractType()); + builder.Export(c => c.AsContractType()); + + var services = builder.GetServicesFrom(typeof(MyService)); + + + ServiceInfo[] expected = new[] + { + new ServiceInfo(typeof (MyService), typeof (IMyService1), Lifetime.Instance), + new ServiceInfo(typeof (MyService), typeof (IMyService2), Lifetime.Instance), + }; + AssertEx.AreEquivalent(services, comparer.Equals, expected); + } + + [Fact] + public void GetServicesFrom_ExportBuilderWithMultipleConfigs_AllConfigurationsExported() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof (MyService)); + builder.Export(c => c.AsContractType().AsContractName("IMyService1").WithLifetime(Lifetime.Application)); + + var services = builder.GetServicesFrom(typeof (MyService)); + + + ServiceInfo[] expected = {new ServiceInfo(typeof (MyService), typeof (IMyService1), "IMyService1", Lifetime.Application)}; + AssertEx.AreEquivalent(services, comparer.Equals, expected); + } + + [Fact] + public void GetServicesFrom_NoTypeMatch_DoesNotExport() + { + ServiceBuilder builder = new ServiceBuilder(t => t == typeof(MyService)); + builder.Export(); + + ServiceInfo actual = builder.GetServicesFrom(typeof(IMyService1)).FirstOrDefault(); + + Assert.Null(actual); + } + + private class MyService : IMyService1, IMyService2 + { + } + + internal interface IMyService1 + { + } + + internal interface IMyService2 + { + } + + private class MyOtherService + { } + } +} diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/ServiceEqualityComparer.cs b/AppBoot/iQuarc.AppBoot.UnitTests/ServiceEqualityComparer.cs new file mode 100644 index 0000000..d6a0f14 --- /dev/null +++ b/AppBoot/iQuarc.AppBoot.UnitTests/ServiceEqualityComparer.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace iQuarc.AppBoot.UnitTests +{ + internal class ServiceEqualityComparer : IEqualityComparer + { + public bool Equals(ServiceInfo x, ServiceInfo y) + { + return x.ContractName == y.ContractName && + x.From == y.From && + x.To == y.To && + x.InstanceLifetime == y.InstanceLifetime; + } + + public int GetHashCode(ServiceInfo obj) + { + return obj.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/ServiceRegistrationBehaviorTests.cs b/AppBoot/iQuarc.AppBoot.UnitTests/ServiceRegistrationBehaviorTests.cs index 7066107..75deab6 100644 --- a/AppBoot/iQuarc.AppBoot.UnitTests/ServiceRegistrationBehaviorTests.cs +++ b/AppBoot/iQuarc.AppBoot.UnitTests/ServiceRegistrationBehaviorTests.cs @@ -100,12 +100,4 @@ private class MyDoubleService : IMyService { } } - - public static class Extensions - { - public static T[] AsArray(this T o) - { - return new[] {o}; - } - } } \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/app.config b/AppBoot/iQuarc.AppBoot.UnitTests/app.config new file mode 100644 index 0000000..4fc378d --- /dev/null +++ b/AppBoot/iQuarc.AppBoot.UnitTests/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/iQuarc.AppBoot.UnitTests.csproj b/AppBoot/iQuarc.AppBoot.UnitTests/iQuarc.AppBoot.UnitTests.csproj index cf2bdc5..7580ec9 100644 --- a/AppBoot/iQuarc.AppBoot.UnitTests/iQuarc.AppBoot.UnitTests.csproj +++ b/AppBoot/iQuarc.AppBoot.UnitTests/iQuarc.AppBoot.UnitTests.csproj @@ -42,11 +42,14 @@ ..\packages\iQuarc.xUnitEx.1.0.0.0\lib\net35\iQuarc.xUnitEx.dll - - ..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll + + False + ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll - - ..\packages\Moq.4.2.1312.1622\lib\net40\Moq.dll + + + False + ..\packages\Moq.4.2.1502.0911\lib\net40\Moq.dll @@ -63,12 +66,16 @@ + + + + diff --git a/AppBoot/iQuarc.AppBoot.UnitTests/packages.config b/AppBoot/iQuarc.AppBoot.UnitTests/packages.config index 0819a72..faafa01 100644 --- a/AppBoot/iQuarc.AppBoot.UnitTests/packages.config +++ b/AppBoot/iQuarc.AppBoot.UnitTests/packages.config @@ -1,8 +1,8 @@  - + - + \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/iQuarc.AppBoot.Unity.ExploratoryTests.csproj b/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/iQuarc.AppBoot.Unity.ExploratoryTests.csproj index 249fb3a..fffd0ef 100644 --- a/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/iQuarc.AppBoot.Unity.ExploratoryTests.csproj +++ b/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/iQuarc.AppBoot.Unity.ExploratoryTests.csproj @@ -39,13 +39,17 @@ False ..\packages\iQuarc.xUnitEx.1.0.0.0\lib\net35\iQuarc.xUnitEx.dll - + False - ..\packages\Unity.3.0.1304.1\lib\Net45\Microsoft.Practices.Unity.dll + ..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll - + False - ..\packages\Unity.3.0.1304.1\lib\Net45\Microsoft.Practices.Unity.Configuration.dll + ..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll + + + False + ..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll diff --git a/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/packages.config b/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/packages.config index 80b22f1..d418a2e 100644 --- a/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/packages.config +++ b/AppBoot/iQuarc.AppBoot.Unity.ExplorationTests/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot/Container/ConventionRegistrationBehavior.cs b/AppBoot/iQuarc.AppBoot/Container/ConventionRegistrationBehavior.cs new file mode 100644 index 0000000..e4c17c2 --- /dev/null +++ b/AppBoot/iQuarc.AppBoot/Container/ConventionRegistrationBehavior.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; + +namespace iQuarc.AppBoot +{ + public class ConventionRegistrationBehavior : IRegistrationBehavior + { + private readonly IList builders = new List(); + + public IEnumerable GetServicesFrom(Type type) + { + IEnumerable services = builders.SelectMany(x => x.GetServicesFrom(type)); + return services; + } + + public ServiceBuilder ForType(Type type) + { + ServiceBuilder builder = CreateServiceBuilder(x => x == type); + builders.Add(builder); + return builder; + } + + [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Convenience call")] + public ServiceBuilder ForType() + { + return this.ForType(typeof (T)); + } + + public ServiceBuilder ForTypesDerivedFrom(Type type) + { + ServiceBuilder builder = CreateServiceBuilder(x => type.IsAssignableFrom(x)); + builders.Add(builder); + return builder; + } + + [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Convenience call")] + public ServiceBuilder ForTypesDerivedFrom() + { + return ForTypesDerivedFrom(typeof (T)); + } + + public ServiceBuilder ForTypesMatching(Predicate typeFilter) + { + ServiceBuilder builder = CreateServiceBuilder(typeFilter); + builders.Add(builder); + return builder; + } + + + private static ServiceBuilder CreateServiceBuilder(Predicate typeFilter) + { + return new ServiceBuilder(typeFilter); + } + } +} \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot/Container/ExportBuilder.cs b/AppBoot/iQuarc.AppBoot/Container/ExportBuilder.cs new file mode 100644 index 0000000..ac2ebc8 --- /dev/null +++ b/AppBoot/iQuarc.AppBoot/Container/ExportBuilder.cs @@ -0,0 +1,41 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace iQuarc.AppBoot +{ + public class ExportBuilder + { + private Type contractType; + private string contractName; + private Lifetime life = Lifetime.Instance; + + public ExportBuilder AsContractName(string name) + { + this.contractName = name; + return this; + } + + public ExportBuilder AsContractType(Type type) + { + this.contractType = type; + return this; + } + + [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Convenience call")] + public ExportBuilder AsContractType() + { + return AsContractType(typeof (T)); + } + + public ExportBuilder WithLifetime(Lifetime lifetime) + { + this.life = lifetime; + return this; + } + + internal ServiceInfo GetServiceInfo(Type type) + { + return new ServiceInfo(type, contractType ?? type, contractName, life); + } + } +} \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot/Container/ServiceBuilder.cs b/AppBoot/iQuarc.AppBoot/Container/ServiceBuilder.cs new file mode 100644 index 0000000..f8e175a --- /dev/null +++ b/AppBoot/iQuarc.AppBoot/Container/ServiceBuilder.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace iQuarc.AppBoot +{ + public class ServiceBuilder + { + private readonly Predicate filter; + private readonly IList configs = new List(); + + internal ServiceBuilder(Predicate filter) + { + this.filter = filter; + } + + public void Export() + { + this.Export(c => {}); + } + + public void Export(Action exportConfiguration) + { + RegisterConfig(new ExportConfig { ContractsProvider = t => new[] { t }, ExportConfiguration = exportConfiguration }); + } + + public void ExportInterfaces() + { + this.ExportInterfaces(x => true); + } + + public void ExportInterfaces(Predicate interfaceFilter) + { + this.ExportInterfaces(interfaceFilter, c => {}); + } + + public void ExportInterfaces(Predicate interfaceFilter, Action exportConfiguration) + { + Func> interfaces = t => t.GetInterfaces().Where(x => interfaceFilter(x)); + + RegisterConfig(new ExportConfig { ExportConfiguration = exportConfiguration, ContractsProvider = interfaces }); + } + + public bool IsMatch(Type type) + { + return filter(type); + } + + internal IEnumerable GetServicesFrom(Type type) + { + if (!IsMatch(type)) + yield break; + + foreach (ExportConfig config in configs) + { + IEnumerable contracts = config.ContractsProvider(type); + + foreach (Type contract in contracts) + { + ExportBuilder builder = new ExportBuilder(); + builder.AsContractType(contract); + + config.ExportConfiguration(builder); + + yield return builder.GetServiceInfo(type); + } + } + } + + private void RegisterConfig(ExportConfig config) + { + this.configs.Add(config); + } + + private class ExportConfig + { + internal Action ExportConfiguration { get; set; } + + internal Func> ContractsProvider { get; set; } + } + } +} \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot/GlobalSuppressions.cs b/AppBoot/iQuarc.AppBoot/GlobalSuppressions.cs new file mode 100644 index 0000000..0b11a84 Binary files /dev/null and b/AppBoot/iQuarc.AppBoot/GlobalSuppressions.cs differ diff --git a/AppBoot/iQuarc.AppBoot/Properties/AssemblyInfo.cs b/AppBoot/iQuarc.AppBoot/Properties/AssemblyInfo.cs index 051f9c4..8528636 100644 --- a/AppBoot/iQuarc.AppBoot/Properties/AssemblyInfo.cs +++ b/AppBoot/iQuarc.AppBoot/Properties/AssemblyInfo.cs @@ -45,5 +45,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot/app.config b/AppBoot/iQuarc.AppBoot/app.config new file mode 100644 index 0000000..4fc378d --- /dev/null +++ b/AppBoot/iQuarc.AppBoot/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.csproj b/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.csproj index d1caaba..765ef3c 100644 --- a/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.csproj +++ b/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.csproj @@ -35,16 +35,18 @@ False ..\packages\iQuarc.SystemEx.1.0.0.0\lib\net40\iQuarc.SystemEx.dll - - ..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll - - + False - ..\packages\Unity.3.0.1304.1\lib\Net45\Microsoft.Practices.Unity.dll + ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll - - False - ..\packages\Unity.3.0.1304.1\lib\Net45\Microsoft.Practices.Unity.Configuration.dll + + ..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.dll + + + ..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.Configuration.dll + + + ..\packages\Unity.3.5.1404.0\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll @@ -57,8 +59,12 @@ + + + + @@ -72,6 +78,7 @@ + diff --git a/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.nuspec b/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.nuspec index 6f5d194..d2f3418 100644 --- a/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.nuspec +++ b/AppBoot/iQuarc.AppBoot/iQuarc.AppBoot.nuspec @@ -9,7 +9,7 @@ false $description$ $description$ - Basic functionality for hiding the DI Container and for defining a modular application. + Adds registrations by convention support. Copyright 2014 Dependency Injection Modularity Bootstrap Configuration https://raw.githubusercontent.com/iQuarc/AppBoot/master/MIT.md diff --git a/AppBoot/iQuarc.AppBoot/packages.config b/AppBoot/iQuarc.AppBoot/packages.config index 1a6f383..2a12d3e 100644 --- a/AppBoot/iQuarc.AppBoot/packages.config +++ b/AppBoot/iQuarc.AppBoot/packages.config @@ -1,6 +1,6 @@  - + - + \ No newline at end of file