Permalink
Browse files

+ Tiko.csproj with implemented TikoContainer

+ UnitTests.csproj
  • Loading branch information...
GSerjo committed Feb 26, 2012
1 parent 3afc496 commit ee0c185c1da1216d57e466a49443b6a4358b6041
View
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{542F5FA5-7435-4466-A776-ECFE06CEF0C2}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>Tiko</RootNamespace>
+ <AssemblyName>Tiko</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <Compile Include="TikoContainer.cs" />
+ </ItemGroup>
+</Project>
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Concurrent;
+using System.Reflection;
+
+namespace Tiko
+{
+ public static class TikoContainer
+ {
+ private static readonly ConcurrentDictionary<Type, RegisteredObject> _registeredObjects =
+ new ConcurrentDictionary<Type, RegisteredObject>();
+
+ /// <summary>
+ /// Resolve dependencies on existing object.
+ /// </summary>
+ /// <typeparam name="T">Type of object.</typeparam>
+ /// <param name="existing">Instance of the object.</param>
+ /// <exception cref="DependencyMissingException">Throw exception if unable to resove a dependency.</exception>
+ /// <returns>Result object.</returns>
+ public static T BuildUp<T>(T existing)
+ {
+ return DoBuildUp(existing);
+ }
+
+ /// <summary>
+ /// Clear the container.
+ /// </summary>
+ public static void Clear()
+ {
+ _registeredObjects.Clear();
+ }
+
+ /// <summary>
+ /// Register class.
+ /// </summary>
+ /// <typeparam name="T">Type of class.</typeparam>
+ public static void Register<T>()
+ where T : new()
+ {
+ Register<T, T>();
+ }
+
+ /// <summary>
+ /// Register object.
+ /// </summary>
+ /// <typeparam name="TFrom">That will be requested.</typeparam>
+ /// <typeparam name="TTo">That will actually be returned.</typeparam>
+ public static void Register<TFrom, TTo>()
+ where TTo : TFrom, new()
+ {
+ var registeredObject = new RegisteredObject(() => new TTo());
+ _registeredObjects[typeof (TFrom)] = registeredObject;
+ }
+
+ /// <summary>
+ /// Resolve an instance and dependencies.
+ /// </summary>
+ /// <typeparam name="T">Type of object.</typeparam>
+ /// <exception cref="DependencyMissingException">Throw exception if unable to resove a dependency.</exception>
+ /// <returns>Result object.</returns>
+ public static T Resolve<T>()
+ {
+ object resolvedObject;
+ bool isResolved = ResolveObject(typeof (T), out resolvedObject);
+ if (isResolved)
+ {
+ return (T) resolvedObject;
+ }
+ var instance = Activator.CreateInstance<T>();
+ return DoBuildUp(instance);
+ }
+
+ private static T DoBuildUp<T>(T instance)
+ {
+ PropertyInfo[] properties = typeof (T).GetProperties();
+ foreach (PropertyInfo property in properties)
+ {
+ if (!IsResolveProperty(property))
+ {
+ continue;
+ }
+ object resolvedObject;
+ bool isResolved = ResolveObject(property.PropertyType, out resolvedObject);
+ if (!isResolved)
+ {
+ throw new DependencyMissingException(string.Format(
+ "Could not resolve dependency for {0}", typeof (T).Name));
+ }
+ property.SetValue(instance, resolvedObject, null);
+ }
+ return instance;
+ }
+
+ private static bool IsResolveProperty(PropertyInfo property)
+ {
+ object[] attributes = property.GetCustomAttributes(typeof (DependencyAttribute), false);
+ return attributes.Length != 0;
+ }
+
+ private static bool ResolveObject(Type typeToResolve, out object resolvedObject)
+ {
+ RegisteredObject result;
+ if (!_registeredObjects.TryGetValue(typeToResolve, out result))
+ {
+ resolvedObject = null;
+ return false;
+ }
+ resolvedObject = result.Instance;
+ return true;
+ }
+
+ private sealed class RegisteredObject
+ {
+ private readonly Lazy<object> _concreteValue;
+
+ public RegisteredObject(Func<object> func)
+ {
+ _concreteValue = new Lazy<object>(func);
+ }
+
+ public object Instance
+ {
+ get { return _concreteValue.Value; }
+ }
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
+ public sealed class DependencyAttribute : Attribute
+ {
+ }
+
+ [Serializable]
+ public sealed class DependencyMissingException : Exception
+ {
+ public DependencyMissingException()
+ {
+ }
+
+ public DependencyMissingException(string message) : base(message)
+ {
+ }
+
+ public DependencyMissingException(string message, Exception inner) : base(message, inner)
+ {
+ }
+ }
+}
@@ -0,0 +1,80 @@
+using System;
+using NUnit.Framework;
+using Tiko;
+
+namespace UnitTests
+{
+ [TestFixture]
+ public sealed class TikoContainerTest
+ {
+ [Test]
+ public void BuildUp()
+ {
+ TikoContainer.Register<TestProperty>();
+ var result = new TestClass();
+ TikoContainer.BuildUp(result);
+ Assert.IsNull(result.TestProperty1);
+ Assert.IsNotNull(result.TestProperty);
+ }
+
+ [Test]
+ public void Register()
+ {
+ TikoContainer.Register<ITestClass, TestClass>();
+ var result = TikoContainer.Resolve<ITestClass>();
+ Assert.IsNotNull(result);
+ }
+
+ [Test]
+ public void RegisterAsSingleton()
+ {
+ TikoContainer.Register<ITestClass, TestClass>();
+ var result = TikoContainer.Resolve<ITestClass>();
+ var result1 = TikoContainer.Resolve<ITestClass>();
+ Assert.IsNotNull(result1);
+ Assert.IsNotNull(result);
+ Assert.AreEqual(result, result1);
+ }
+
+ [Test]
+ public void Resolve()
+ {
+ TikoContainer.Register<TestProperty>();
+ var result = TikoContainer.Resolve<TestClass>();
+ Assert.IsNotNull(result);
+ Assert.IsNull(result.TestProperty1);
+ Assert.IsNotNull(result.TestProperty);
+ var result1 = TikoContainer.Resolve<TestClass>();
+ Assert.AreEqual(result.TestProperty1, result1.TestProperty1);
+ }
+
+ [Test, ExpectedException(typeof (DependencyMissingException))]
+ public void Resolve_MissingDependency()
+ {
+ TikoContainer.Resolve<TestClass>();
+ }
+
+ [SetUp]
+ public void SetUp()
+ {
+ TikoContainer.Clear();
+ }
+ }
+
+ public interface ITestClass
+ {
+ }
+
+ public sealed class TestClass : ITestClass
+ {
+ [Dependency]
+ public TestProperty TestProperty { get; set; }
+
+ public TestProperty TestProperty1 { get; set; }
+ }
+
+ public sealed class TestProperty
+ {
+ }
+}
+
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>10.0.0</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{32231D9E-EAF6-4607-82B1-2BFE20081E5E}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <RootNamespace>UnitTests</RootNamespace>
+ <AssemblyName>UnitTests</AssemblyName>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug</OutputPath>
+ <DefineConstants>DEBUG;</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>none</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Release</OutputPath>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <ConsolePause>false</ConsolePause>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="nunit.core, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77" />
+ <Reference Include="nunit.framework, Version=2.4.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="TikoContainerTest.cs" />
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <ItemGroup>
+ <ProjectReference Include="..\Tiko\Tiko.csproj">
+ <Project>{542F5FA5-7435-4466-A776-ECFE06CEF0C2}</Project>
+ <Name>Tiko</Name>
+ </ProjectReference>
+ </ItemGroup>
+</Project>
View
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTests", "Source\UnitTests\UnitTests.csproj", "{32231D9E-EAF6-4607-82B1-2BFE20081E5E}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tiko", "Source\Tiko\Tiko.csproj", "{542F5FA5-7435-4466-A776-ECFE06CEF0C2}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Default|Any CPU = Default|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {32231D9E-EAF6-4607-82B1-2BFE20081E5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {32231D9E-EAF6-4607-82B1-2BFE20081E5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {32231D9E-EAF6-4607-82B1-2BFE20081E5E}.Default|Any CPU.ActiveCfg = Debug|Any CPU
+ {32231D9E-EAF6-4607-82B1-2BFE20081E5E}.Default|Any CPU.Build.0 = Debug|Any CPU
+ {32231D9E-EAF6-4607-82B1-2BFE20081E5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {32231D9E-EAF6-4607-82B1-2BFE20081E5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {542F5FA5-7435-4466-A776-ECFE06CEF0C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {542F5FA5-7435-4466-A776-ECFE06CEF0C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {542F5FA5-7435-4466-A776-ECFE06CEF0C2}.Default|Any CPU.ActiveCfg = Debug|Any CPU
+ {542F5FA5-7435-4466-A776-ECFE06CEF0C2}.Default|Any CPU.Build.0 = Debug|Any CPU
+ {542F5FA5-7435-4466-A776-ECFE06CEF0C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {542F5FA5-7435-4466-A776-ECFE06CEF0C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = Source\UnitTests\UnitTests.csproj
+ EndGlobalSection
+EndGlobal

0 comments on commit ee0c185

Please sign in to comment.