Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dependency Injection Code And Documentation #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\PostSharp.5.0.37\build\PostSharp.props" Condition="Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.props')" />
<Import Project="..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props" Condition="Exists('..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{232F6D41-893E-4526-9C4A-94C57EF12B6F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PostSharp.Samples.DependencyResolution.Contextual.Test</RootNamespace>
<AssemblyName>PostSharp.Samples.DependencyResolution.Contextual.Test</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath>
<IsCodedUITest>False</IsCodedUITest>
<TestProjectType>UnitTest</TestProjectType>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\MSTest.TestFramework.1.3.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
</Reference>
<Reference Include="PostSharp, Version=5.0.37.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL">
<HintPath>..\..\packages\PostSharp.Redist.5.0.37\lib\net45\PostSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="TestLogAspect.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PostSharp.Samples.DependencyResolution.Contextual\PostSharp.Samples.DependencyResolution.Contextual.csproj">
<Project>{9dfd9bdb-fb8b-4066-a62e-670c20ce1213}</Project>
<Name>PostSharp.Samples.DependencyResolution.Contextual</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.props'))" />
<Error Condition="!Exists('..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets'))" />
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.37\build\PostSharp.props'))" />
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.37\build\PostSharp.targets'))" />
</Target>
<Import Project="..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets" Condition="Exists('..\..\packages\MSTest.TestAdapter.1.3.2\build\net45\MSTest.TestAdapter.targets')" />
<Import Project="..\..\packages\PostSharp.5.0.37\build\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.targets')" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyTitle("PostSharp.Samples.DependencyResolution.Contextual.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PostSharp.Samples.DependencyResolution.Contextual.Test")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

[assembly: ComVisible(false)]

[assembly: Guid("232f6d41-893e-4526-9c4a-94c57ef12b6f")]

// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace PostSharp.Samples.DependencyResolution.Contextual.Test
{
[TestClass]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please split all files into single-type files because it's our convention.

public class TestLogAspect
{
[TestMethod]
public void TestMethod()
{
// The ServiceLocator can be initialized for each test.
using (
AspectServiceLocator.AddRule<ILogger>(
(type, member) =>
type == typeof(LogAspect) && member.Name == "TargetMethod" ? new TestLogger() : null)
)
{
TestLogger.Clear();
TargetMethod();
Assert.AreEqual("OnEntry" + Environment.NewLine, TestLogger.GetLog());
}
}

[LogAspect]
public void TargetMethod()
{
}
}

internal class TestLogger : ILogger
{
public static readonly StringBuilder stringBuilder = new StringBuilder();

public void Log(string message)
{
stringBuilder.AppendLine(message);
}

public static string GetLog()
{
return stringBuilder.ToString();
}

public static void Clear()
{
stringBuilder.Clear();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MSTest.TestAdapter" version="1.3.2" targetFramework="net472" />
<package id="MSTest.TestFramework" version="1.3.2" targetFramework="net472" />
<package id="PostSharp" version="5.0.37" targetFramework="net472" developmentDependency="true" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the same version of PostSharp as other projects.

<package id="PostSharp.Redist" version="5.0.37" targetFramework="net472" />
</packages>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\packages\PostSharp.5.0.37\build\PostSharp.props" Condition="Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9DFD9BDB-FB8B-4066-A62E-670C20CE1213}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>PostSharp.Samples.DependencyResolution.Contextual</RootNamespace>
<AssemblyName>PostSharp.Samples.DependencyResolution.Contextual</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="PostSharp, Version=5.0.37.0, Culture=neutral, PublicKeyToken=b13fd38b8f9c99d7, processorArchitecture=MSIL">
<HintPath>..\..\packages\PostSharp.Redist.5.0.37\lib\net45\PostSharp.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.37\build\PostSharp.props'))" />
<Error Condition="!Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\PostSharp.5.0.37\build\PostSharp.targets'))" />
</Target>
<Import Project="..\..\packages\PostSharp.5.0.37\build\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp.5.0.37\build\PostSharp.targets')" />
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Reflection;
using PostSharp.Aspects;
using PostSharp.Extensibility;
using PostSharp.Serialization;

namespace PostSharp.Samples.DependencyResolution.Contextual
{
public interface ILogger
{
void Log(string message);
}

public static class AspectServiceLocator
{
private static CompositionContainer container;
private static HashSet<object> rules = new HashSet<object>();

public static void Initialize(ComposablePartCatalog catalog)
{
container = new CompositionContainer(catalog);
}

public static Lazy<T> GetService<T>(Type aspectType, MemberInfo targetElement) where T : class
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure Lazy is the right thing here. We need to cope with the problem of random initialization order, i.e. your aspect may be executed before the catalogue is initialized (especially with logging). One way would be to return an object of type say Service<T> where service.Value would return null before initialization, but after initialization, the value would be cached.

return new Lazy<T>(() => GetServiceImpl<T>(aspectType, targetElement));
}

private static T GetServiceImpl<T>(Type aspectType, MemberInfo targetElement) where T : class
{
// The rule implementation is naive but this is for testing purpose only.
foreach (object rule in rules)
{
DependencyRule<T> typedRule = rule as DependencyRule<T>;
if (typedRule == null) continue;

T service = typedRule.Rule(aspectType, targetElement);
if (service != null) return service;
}

if (container == null)
throw new InvalidOperationException();

// Fallback to the container, which should be the default and production behavior.
return container.GetExport<T>().Value;
}

public static IDisposable AddRule<T>(Func<Type, MemberInfo, T> rule)
{
DependencyRule<T> dependencyRule = new DependencyRule<T>(rule);
rules.Add(dependencyRule);
return dependencyRule;
}

private class DependencyRule<T> : IDisposable
{
public DependencyRule(Func<Type, MemberInfo, T> rule)
{
this.Rule = rule;
}

public Func<Type, MemberInfo, T> Rule { get; private set; }

public void Dispose()
{
rules.Remove(this);
}
}
}

[PSerializable]
public class LogAspect : OnMethodBoundaryAspect
{
private Lazy<ILogger> logger;


public override void RuntimeInitialize(MethodBase method)
{
logger = AspectServiceLocator.GetService<ILogger>(this.GetType(), method);
}


public override void OnEntry(MethodExecutionArgs args)
{
logger.Value.Log("OnEntry");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you would do logger.Value?.Log, i.e. at runtime the Value could be null.

}

internal class Program
{
private static void Main(string[] args)
{
AspectServiceLocator.Initialize(new TypeCatalog(typeof(ConsoleLogger)));

LoggedMethod();

Console.ReadLine();
}

[LogAspect]
public static void LoggedMethod()
{
Console.WriteLine("Hello, world.");
}
}


[Export(typeof(ILogger))]
internal class ConsoleLogger : ILogger
{
public void Log(string message)
{
Console.WriteLine(message);
}
}
}
Loading