This commit is contained in:
Eugene Sadovoi 2018-02-21 13:06:09 -05:00
Родитель 7b1f3108da
Коммит 961d68a925
127 изменённых файлов: 3102 добавлений и 5802 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -141,4 +141,3 @@ _NCrunch*
project.lock.json project.lock.json
testresults.xml testresults.xml
testresults.xml testresults.xml
BenchmarkDotNet.Artifacts

Просмотреть файл

@ -17,8 +17,15 @@ build:
parallel: true parallel: true
verbosity: minimal verbosity: minimal
after_build:
- choco install opencover.portable
- choco install codecov
test_script: test_script:
- cmd: dotnet test --framework net47 --verbosity q - OpenCover.Console.exe -register:user -target:"C:\Program Files\dotnet\dotnet.exe" -targetargs:"test --framework net47 --verbosity q"
after_test:
- codecov -f "results.xml"
artifacts: artifacts:
- path: '**\Unity.*.nupkg' - path: '**\Unity.*.nupkg'

Просмотреть файл

@ -1,12 +1,12 @@
<Project> <Project>
<PropertyGroup> <PropertyGroup>
<Version>5.5.8</Version> <Version>5.6.0</Version>
<PackageReleaseNotes>This package is distributed as .NET Standard 1.0, .NET 4.0, 4.5, 4.7 package.</PackageReleaseNotes> <PackageReleaseNotes>This package is distributed as .NET Standard 1.0, .NET 4.0, 4.5, 4.7 package.</PackageReleaseNotes>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<UnityAbstractionsVersion>3.1.*</UnityAbstractionsVersion> <UnityAbstractionsVersion>3.2.*</UnityAbstractionsVersion>
</PropertyGroup> </PropertyGroup>
</Project> </Project>

Просмотреть файл

@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unity.Container", "src\Unit
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{13CA431F-C840-429D-A83D-BFDEDCCA0F6F}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{13CA431F-C840-429D-A83D-BFDEDCCA0F6F}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unity.Tests", "tests\Unity.Tests\Unity.Tests.csproj", "{29D42A07-017E-4E9C-A87D-0ABBCAE53798}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unity.Tests", "tests\Unity.Tests\Unity.Tests.csproj", "{25E09D23-F407-4A61-8446-E5FBD6F689B8}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -19,16 +19,16 @@ Global
{EE1F752C-1FAB-41AD-AD63-857D0E62AB6B}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE1F752C-1FAB-41AD-AD63-857D0E62AB6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EE1F752C-1FAB-41AD-AD63-857D0E62AB6B}.Release|Any CPU.ActiveCfg = Release|Any CPU {EE1F752C-1FAB-41AD-AD63-857D0E62AB6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EE1F752C-1FAB-41AD-AD63-857D0E62AB6B}.Release|Any CPU.Build.0 = Release|Any CPU {EE1F752C-1FAB-41AD-AD63-857D0E62AB6B}.Release|Any CPU.Build.0 = Release|Any CPU
{29D42A07-017E-4E9C-A87D-0ABBCAE53798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {25E09D23-F407-4A61-8446-E5FBD6F689B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29D42A07-017E-4E9C-A87D-0ABBCAE53798}.Debug|Any CPU.Build.0 = Debug|Any CPU {25E09D23-F407-4A61-8446-E5FBD6F689B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29D42A07-017E-4E9C-A87D-0ABBCAE53798}.Release|Any CPU.ActiveCfg = Release|Any CPU {25E09D23-F407-4A61-8446-E5FBD6F689B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29D42A07-017E-4E9C-A87D-0ABBCAE53798}.Release|Any CPU.Build.0 = Release|Any CPU {25E09D23-F407-4A61-8446-E5FBD6F689B8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution GlobalSection(NestedProjects) = preSolution
{29D42A07-017E-4E9C-A87D-0ABBCAE53798} = {13CA431F-C840-429D-A83D-BFDEDCCA0F6F} {25E09D23-F407-4A61-8446-E5FBD6F689B8} = {13CA431F-C840-429D-A83D-BFDEDCCA0F6F}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {7D864CD1-AEA6-4EDF-B8F8-071CE7F88251} SolutionGuid = {7D864CD1-AEA6-4EDF-B8F8-071CE7F88251}

Просмотреть файл

@ -1,9 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using Unity.Builder;
using Unity.Container;
using Unity.Exceptions; using Unity.Exceptions;
using Unity.Lifetime; using Unity.Lifetime;
using Unity.Policy; using Unity.Policy;
@ -11,21 +7,49 @@ using Unity.Resolution;
using Unity.Strategy; using Unity.Strategy;
using Unity.Utility; using Unity.Utility;
namespace Unity.ObjectBuilder namespace Unity.Builder
{ {
/// <summary> /// <summary>
/// Represents the context in which a build-up or tear-down operation runs. /// Represents the context in which a build-up or tear-down operation runs.
/// </summary> /// </summary>
public class BuilderContext : IBuilderContext public class BuilderContext : IBuilderContext
{ {
#region Fields
private readonly IStrategyChain _chain; private readonly IStrategyChain _chain;
private CompositeResolverOverride _resolverOverrides; private CompositeResolverOverride _resolverOverrides;
private bool _ownsOverrides; private bool _ownsOverrides;
#endregion
#region Constructors
public BuilderContext(IUnityContainer container, ILifetimeContainer lifetime, IStrategyChain chain,
IPolicyList persistentPolicies, IPolicyList policies, INamedType buildKey, object existing, params ResolverOverride[] resolverOverrides)
{
_chain = chain;
Container = container;
Lifetime = lifetime;
Existing = existing;
OriginalBuildKey = buildKey;
BuildKey = OriginalBuildKey;
Policies = policies;
PersistentPolicies = persistentPolicies;
_ownsOverrides = true;
_resolverOverrides = new CompositeResolverOverride();
if (null != resolverOverrides && 0 != resolverOverrides.Length)
_resolverOverrides.AddRange(resolverOverrides);
}
public BuilderContext(IBuilderContext original, IStrategyChain chain, object existing) public BuilderContext(IBuilderContext original, IStrategyChain chain, object existing)
{ {
Container = original.Container;
_chain = chain; _chain = chain;
Container = original.Container;
ParentContext = original;
Lifetime = original.Lifetime; Lifetime = original.Lifetime;
OriginalBuildKey = original.OriginalBuildKey; OriginalBuildKey = original.OriginalBuildKey;
BuildKey = original.BuildKey; BuildKey = original.BuildKey;
@ -36,89 +60,27 @@ namespace Unity.ObjectBuilder
_ownsOverrides = true; _ownsOverrides = true;
} }
/// <summary>
/// Initialize a new instance of the <see cref="BuilderContext"/> class with a <see cref="IStrategyChain"/>,
/// <see cref="ILifetimeContainer"/>, <see cref="IPolicyList"/> and the
/// build key used to start this build operation.
/// </summary>
/// <param name="container"></param>
/// <param name="chain">The <see cref="IStrategyChain"/> to use for this context.</param>
/// <param name="lifetime">The <see cref="ILifetimeContainer"/> to use for this context.</param>
/// <param name="policies">The <see cref="IPolicyList"/> to use for this context.</param>
/// <param name="originalBuildKey">Build key to start building.</param>
/// <param name="existing">The existing object to build up.</param>
public BuilderContext(IUnityContainer container, IStrategyChain chain,
ILifetimeContainer lifetime,
IPolicyList policies,
INamedType originalBuildKey,
object existing)
{
Container = container ?? throw new ArgumentNullException(nameof(container));
_chain = chain;
Lifetime = lifetime;
OriginalBuildKey = originalBuildKey;
BuildKey = originalBuildKey;
PersistentPolicies = policies;
Policies = new PolicyList(PersistentPolicies);
Existing = existing;
_resolverOverrides = new CompositeResolverOverride();
_ownsOverrides = true;
}
/// <summary> protected BuilderContext(IBuilderContext original, Type type, string name)
/// Create a new <see cref="BuilderContext"/> using the explicitly provided
/// values.
/// </summary>
/// <param name="container"></param>
/// <param name="chain">The <see cref="IStrategyChain"/> to use for this context.</param>
/// <param name="lifetime">The <see cref="ILifetimeContainer"/> to use for this context.</param>
/// <param name="persistentPolicies">The set of persistent policies to use for this context.</param>
/// <param name="transientPolicies">The set of transient policies to use for this context. It is
/// the caller's responsibility to ensure that the transient and persistent policies are properly
/// combined.</param>
/// <param name="buildKey">Build key for this context.</param>
/// <param name="existing">Existing object to build up.</param>
public BuilderContext(IUnityContainer container, IStrategyChain chain, ILifetimeContainer lifetime, IPolicyList persistentPolicies, IPolicyList transientPolicies, INamedType buildKey, object existing)
{ {
Container = container ?? throw new ArgumentNullException(nameof(container)); var parent = (BuilderContext) original;
_chain = chain;
Lifetime = lifetime;
PersistentPolicies = persistentPolicies;
Policies = transientPolicies;
OriginalBuildKey = buildKey;
BuildKey = buildKey;
Existing = existing;
_resolverOverrides = new CompositeResolverOverride();
_ownsOverrides = true;
}
/// <summary> _chain = parent._chain;
/// Create a new <see cref="BuilderContext"/> using the explicitly provided ParentContext = original;
/// values. Container = original.Container;
/// </summary> Lifetime = parent.Lifetime;
/// <param name="container"></param>
/// <param name="chain">The <see cref="IStrategyChain"/> to use for this context.</param>
/// <param name="lifetime">The <see cref="ILifetimeContainer"/> to use for this context.</param>
/// <param name="persistentPolicies">The set of persistent policies to use for this context.</param>
/// <param name="transientPolicies">The set of transient policies to use for this context. It is
/// the caller's responsibility to ensure that the transient and persistent policies are properly
/// combined.</param>
/// <param name="buildKey">Build key for this context.</param>
/// <param name="resolverOverrides">The resolver overrides.</param>
protected BuilderContext(IUnityContainer container, IStrategyChain chain, ILifetimeContainer lifetime, IPolicyList persistentPolicies, IPolicyList transientPolicies, INamedType buildKey, CompositeResolverOverride resolverOverrides)
{
Container = container ?? throw new ArgumentNullException(nameof(container));
_chain = chain;
Lifetime = lifetime;
PersistentPolicies = persistentPolicies;
Policies = transientPolicies;
OriginalBuildKey = buildKey;
BuildKey = buildKey;
Existing = null; Existing = null;
_resolverOverrides = resolverOverrides; _resolverOverrides = parent._resolverOverrides;
_ownsOverrides = false; _ownsOverrides = false;
Policies = parent.Policies;
PersistentPolicies = parent.PersistentPolicies;
OriginalBuildKey = new NamedTypeBuildKey(type, name);
BuildKey = OriginalBuildKey;
} }
#endregion
#region IBuilderContext #region IBuilderContext
public IUnityContainer Container { get; } public IUnityContainer Container { get; }
@ -221,7 +183,6 @@ namespace Unity.ObjectBuilder
_ownsOverrides = true; _ownsOverrides = true;
} }
if (null != newOverrides)
_resolverOverrides.AddRange(newOverrides); _resolverOverrides.AddRange(newOverrides);
} }
@ -236,6 +197,8 @@ namespace Unity.ObjectBuilder
return _resolverOverrides.GetResolver(this, dependencyType); return _resolverOverrides.GetResolver(this, dependencyType);
} }
#endregion
/// <summary> /// <summary>
/// A method to do a new buildup operation on an existing context. /// A method to do a new buildup operation on an existing context.
/// </summary> /// </summary>
@ -247,20 +210,14 @@ namespace Unity.ObjectBuilder
/// <returns>Resolved object</returns> /// <returns>Resolved object</returns>
public object NewBuildUp(Type type, string name, Action<IBuilderContext> childCustomizationBlock = null) public object NewBuildUp(Type type, string name, Action<IBuilderContext> childCustomizationBlock = null)
{ {
ChildContext = ChildContext = new BuilderContext(this, type, name);
new BuilderContext(Container, _chain, Lifetime, PersistentPolicies,
Policies, new NamedTypeBuildKey(type, name), _resolverOverrides)
{ ParentContext = this};
childCustomizationBlock?.Invoke(ChildContext); childCustomizationBlock?.Invoke(ChildContext);
var result = ChildContext.Strategies.ExecuteBuildUp(ChildContext);
object result = ChildContext.Strategies.ExecuteBuildUp(ChildContext);
ChildContext = null; ChildContext = null;
return result; return result;
} }
#endregion
} }
} }

Просмотреть файл

@ -0,0 +1,62 @@
using System;
namespace Unity.Builder
{
public class NamedTypeBase : INamedType
{
#region Fields
private readonly int _hash;
#endregion
#region Constructors
protected NamedTypeBase(Type type, string name)
{
Type = type;
Name = name;
_hash = (Type?.GetHashCode() ?? 0 + 37) ^ (Name?.GetHashCode() ?? 0 + 17);
}
#endregion
#region INamedType
public Type Type { get; }
public string Name { get; }
#endregion
#region Object
public override bool Equals(object obj)
{
return obj is INamedType namedType &&
Type == namedType.Type &&
Name == namedType.Name;
}
public override int GetHashCode()
{
return _hash;
}
#endregion
#region NamedTypeBuildKey
public static implicit operator NamedTypeBuildKey(NamedTypeBase namedType)
{
return new NamedTypeBuildKey(namedType.Type, namedType.Name);
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,25 @@
using Unity.Lifetime;
namespace Unity.Container.Lifetime
{
/// <summary>
/// Internal container lifetime manager.
/// This manager distinguishes internal registration from user mode registration.
/// </summary>
/// <remarks>
/// Works like the ExternallyControlledLifetimeManager, but uses
/// regular instead of weak references
/// </remarks>
internal class ContainerLifetimeManager : LifetimeManager
{
public override object GetValue(ILifetimeContainer container = null)
{
return container.Container;
}
protected override LifetimeManager OnCreateLifetimeManager()
{
return new ContainerLifetimeManager();
}
}
}

Просмотреть файл

@ -3,6 +3,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using Unity.Lifetime; using Unity.Lifetime;
namespace Unity.Container.Lifetime namespace Unity.Container.Lifetime
@ -19,6 +20,18 @@ namespace Unity.Container.Lifetime
{ {
private readonly List<object> _items = new List<object>(); private readonly List<object> _items = new List<object>();
public LifetimeContainer(IUnityContainer parent = null)
{
Container = parent;
}
/// <summary>
/// The IUnityContainer this container is associated with.
/// </summary>
/// <value>The <see cref="IUnityContainer"/> object.</value>
public IUnityContainer Container { get; }
/// <summary> /// <summary>
/// Gets the number of references in the lifetime container /// Gets the number of references in the lifetime container
/// </summary> /// </summary>
@ -87,15 +100,9 @@ namespace Unity.Container.Lifetime
{ {
lock (_items) lock (_items)
{ {
var itemsCopy = new List<object>(_items); foreach (var disposable in _items.OfType<IDisposable>().Reverse())
itemsCopy.Reverse();
foreach (object o in itemsCopy)
{ {
if (o is IDisposable d) disposable.Dispose();
{
d.Dispose();
}
} }
_items.Clear(); _items.Clear();

Просмотреть файл

@ -1,66 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Reflection;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Policy;
using Unity.Registration;
namespace Unity.Container.Registration
{
/// <summary>
/// Class that returns information about the types registered in a container.
/// </summary>
public class ContainerRegistration : IContainerRegistration
{
private readonly NamedTypeBuildKey buildKey;
private static readonly TransientLifetimeManager Transient = new TransientLifetimeManager();
internal ContainerRegistration(Type registeredType, string name, IPolicyList policies)
{
this.buildKey = new NamedTypeBuildKey(registeredType, name);
MappedToType = GetMappedType(policies);
LifetimeManager = GetLifetimeManager(policies) ?? Transient;
}
/// <summary>
/// The type that was passed to the <see cref="IUnityContainer.RegisterType"/> method
/// as the "from" type, or the only type if type mapping wasn't done.
/// </summary>
public Type RegisteredType { get { return this.buildKey.Type; } }
/// <summary>
/// The type that this registration is mapped to. If no type mapping was done, the
/// <see cref="RegisteredType"/> property and this one will have the same value.
/// </summary>
public Type MappedToType { get; private set; }
/// <summary>
/// Name the type was registered under. Null for default registration.
/// </summary>
public string Name { get { return this.buildKey.Name; } }
/// <summary>
/// The lifetime manager for this registration.
/// </summary>
/// <remarks>
/// This property will be null if this registration is for an open generic.</remarks>
public LifetimeManager LifetimeManager { get; private set; }
private Type GetMappedType(IPolicyList policies)
{
var mappingPolicy = policies.Get<IBuildKeyMappingPolicy>(this.buildKey);
if (mappingPolicy != null)
{
return mappingPolicy.Map(this.buildKey, null).Type;
}
return this.buildKey.Type;
}
private LifetimeManager GetLifetimeManager(IPolicyList policies)
{
return (LifetimeManager)policies.Get<ILifetimePolicy>(buildKey);
}
}
}

Просмотреть файл

@ -1,79 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Unity.Container.Registration
{
/// <summary>
/// A helper class to manage the names that get registered in the container
/// </summary>
internal class NamedTypesRegistry
{
private readonly Dictionary<Type, List<string>> registeredKeys;
private readonly NamedTypesRegistry parent;
public NamedTypesRegistry()
: this(null)
{
}
public NamedTypesRegistry(NamedTypesRegistry parent)
{
this.parent = parent;
registeredKeys = new Dictionary<Type, List<string>>();
}
public void RegisterType(Type t, string name)
{
if (!registeredKeys.ContainsKey(t))
{
registeredKeys[t] = new List<string>();
}
RemoveMatchingKeys(t, name);
registeredKeys[t].Add(name);
}
public IEnumerable<string> GetKeys(Type t)
{
var keys = Enumerable.Empty<string>();
if (parent != null)
{
keys = keys.Concat(parent.GetKeys(t));
}
if (registeredKeys.ContainsKey(t))
{
keys = keys.Concat(registeredKeys[t]);
}
return keys;
}
public IEnumerable<Type> RegisteredTypes
{
get
{
return registeredKeys.Keys;
}
}
public void Clear()
{
registeredKeys.Clear();
}
// We need to do this the long way - Silverlight doesn't support List<T>.RemoveAll(Predicate)
private void RemoveMatchingKeys(Type t, string name)
{
var uniqueNames = from registeredName in registeredKeys[t]
where registeredName != name
select registeredName;
registeredKeys[t] = uniqueNames.ToList();
}
}
}

Просмотреть файл

@ -34,18 +34,19 @@ namespace Unity.Container
public void BuildUp(IBuilderContext builderContext) public void BuildUp(IBuilderContext builderContext)
{ {
var context = builderContext ?? throw new ArgumentNullException(nameof(builderContext)); var context = builderContext ?? throw new ArgumentNullException(nameof(builderContext));
var i = 0; var i = -1;
var values = new object[_strategies.Length]; // TODO: Store in struct
try try
{ {
while (!context.BuildComplete && i < _strategies.Length) while (!context.BuildComplete && ++i < _strategies.Length)
{ {
_strategies[i++].PreBuildUp(context); values[i] = _strategies[i].PreBuildUp(context);
} }
while (--i >= 0) while (--i >= 0)
{ {
_strategies[i].PostBuildUp(context); _strategies[i].PostBuildUp(context, values[i]);
} }
} }
catch (Exception) catch (Exception)

Просмотреть файл

@ -14,7 +14,7 @@ using Unity.Container.Lifetime;
using Unity.Lifetime; using Unity.Lifetime;
using Unity.Policy; using Unity.Policy;
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod.Creation
{ {
/// <summary> /// <summary>
/// A <see cref="BuilderStrategy"/> that emits IL to call constructors /// A <see cref="BuilderStrategy"/> that emits IL to call constructors
@ -93,7 +93,10 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
} }
IConstructorSelectorPolicy selector = IConstructorSelectorPolicy selector =
context.Policies.Get<IConstructorSelectorPolicy>(context.OriginalBuildKey, out var resolverPolicyDestination); context.Policies.GetPolicy<IConstructorSelectorPolicy>(context.OriginalBuildKey, out var resolverPolicyDestination);
context.Policies.Get<IConstructorSelectorPolicy>(null, null, out resolverPolicyDestination);
SelectedConstructor selectedConstructor = selector.SelectConstructor(context, resolverPolicyDestination); SelectedConstructor selectedConstructor = selector.SelectConstructor(context, resolverPolicyDestination);
@ -122,7 +125,9 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
{ {
if (selectedConstructor.Constructor.GetParameters().Any(p => p.ParameterType.GetTypeInfo() == target)) if (selectedConstructor.Constructor.GetParameters().Any(p => p.ParameterType.GetTypeInfo() == target))
{ {
var policy = context.Policies.Get<ILifetimePolicy>(context.BuildKey, out var _); var policy = (ILifetimePolicy)context.Policies.Get(context.BuildKey.Type,
context.BuildKey.Name,
typeof(ILifetimePolicy), out var _);
if (null == policy?.GetValue()) if (null == policy?.GetValue())
return true; return true;
} }
@ -199,13 +204,17 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
/// if the current object is such. /// if the current object is such.
/// </summary> /// </summary>
/// <param name="context">Current build context.</param> /// <param name="context">Current build context.</param>
private static void SetPerBuildSingleton(IBuilderContext context) public static void SetPerBuildSingleton(IBuilderContext context)
{ {
var lifetime = (context ?? throw new ArgumentNullException(nameof(context))).Policies.Get<ILifetimePolicy>(context.OriginalBuildKey); var lifetime = (context ?? throw new ArgumentNullException(nameof(context)))
.Policies.GetOrDefault(typeof(ILifetimePolicy), context.OriginalBuildKey, out _);
if (lifetime is PerResolveLifetimeManager) if (lifetime is PerResolveLifetimeManager)
{ {
var perBuildLifetime = new InternalPerResolveLifetimeManager(context.Existing); var perBuildLifetime = new InternalPerResolveLifetimeManager(context.Existing);
context.Policies.Set<ILifetimePolicy>(perBuildLifetime, context.OriginalBuildKey); context.Policies.Set(context.OriginalBuildKey.Type,
context.OriginalBuildKey.Name,
typeof(ILifetimePolicy), perBuildLifetime);
} }
} }

Просмотреть файл

@ -27,7 +27,6 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
typeof(IBuilderContext).GetTypeInfo() typeof(IBuilderContext).GetTypeInfo()
.DeclaredMembers .DeclaredMembers
.First(m => m.Name == nameof(IBuilderContext.Existing)); .First(m => m.Name == nameof(IBuilderContext.Existing));
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>

Просмотреть файл

@ -35,12 +35,10 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
/// <returns>The created build plan.</returns> /// <returns>The created build plan.</returns>
public IBuildPlanPolicy CreatePlan(IBuilderContext context, INamedType buildKey) public IBuildPlanPolicy CreatePlan(IBuilderContext context, INamedType buildKey)
{ {
DynamicBuildPlanGenerationContext generatorContext = var generatorContext =
new DynamicBuildPlanGenerationContext((buildKey ?? throw new ArgumentNullException(nameof(buildKey))).Type); new DynamicBuildPlanGenerationContext((buildKey ?? throw new ArgumentNullException(nameof(buildKey))).Type);
IBuilderContext planContext = new BuilderContext(context ?? throw new ArgumentNullException(nameof(context)), IBuilderContext planContext = new BuilderContext(context ?? throw new ArgumentNullException(nameof(context)), new StrategyChain(_strategies), generatorContext);
((StagedStrategyChain<BuilderStage>)_strategies).MakeStrategyChain(),
generatorContext);
planContext.Strategies.ExecuteBuildUp(planContext); planContext.Strategies.ExecuteBuildUp(planContext);

Просмотреть файл

@ -13,7 +13,7 @@ using Unity.Builder.Strategy;
using Unity.Exceptions; using Unity.Exceptions;
using Unity.Policy; using Unity.Policy;
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod.Method
{ {
/// <summary> /// <summary>
/// A <see cref="BuilderStrategy"/> that generates IL to call /// A <see cref="BuilderStrategy"/> that generates IL to call
@ -46,7 +46,7 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
{ {
var dynamicBuildContext = (DynamicBuildPlanGenerationContext)(context ?? throw new ArgumentNullException(nameof(context))).Existing; var dynamicBuildContext = (DynamicBuildPlanGenerationContext)(context ?? throw new ArgumentNullException(nameof(context))).Existing;
var selector = context.Policies.Get<IMethodSelectorPolicy>(context.OriginalBuildKey, out var resolverPolicyDestination); var selector = context.Policies.GetPolicy<IMethodSelectorPolicy>(context.OriginalBuildKey, out var resolverPolicyDestination);
bool shouldClearOperation = false; bool shouldClearOperation = false;

Просмотреть файл

@ -9,7 +9,7 @@ using Unity.Builder.Operation;
using Unity.Builder.Strategy; using Unity.Builder.Strategy;
using Unity.Policy; using Unity.Policy;
namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod.Property
{ {
/// <summary> /// <summary>
/// A <see cref="BuilderStrategy"/> that generates IL to resolve properties /// A <see cref="BuilderStrategy"/> that generates IL to resolve properties
@ -39,7 +39,7 @@ namespace Unity.ObjectBuilder.BuildPlan.DynamicMethod
{ {
var dynamicBuildContext = (DynamicBuildPlanGenerationContext)(context ?? throw new ArgumentNullException(nameof(context))).Existing; var dynamicBuildContext = (DynamicBuildPlanGenerationContext)(context ?? throw new ArgumentNullException(nameof(context))).Existing;
var selector = context.Policies.Get<IPropertySelectorPolicy>(context.OriginalBuildKey, out var resolverPolicyDestination); var selector = context.Policies.GetPolicy<IPropertySelectorPolicy>( context.OriginalBuildKey, out var resolverPolicyDestination);
bool shouldClearOperation = false; bool shouldClearOperation = false;

Просмотреть файл

@ -1,70 +0,0 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod;
using Unity.Policy;
namespace Unity.ObjectBuilder.BuildPlan
{
/// <summary>
/// An <see cref="IEnumerable{T}"/> implementation
/// that constructs a build plan for creating <see cref="IBuildPlanCreatorPolicy"/> objects.
/// </summary>
public class EnumerableDynamicMethodBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy
{
private static readonly MethodInfo ResolveMethod =
typeof(EnumerableDynamicMethodBuildPlanCreatorPolicy).GetTypeInfo()
.GetDeclaredMethod(nameof(BuildResolveEnumerable));
private static readonly MethodInfo CastMethod = typeof(System.Linq.Enumerable).GetTypeInfo()
.DeclaredMethods
.First(m => Equals(m.Name, "Cast"));
public IBuildPlanPolicy CreatePlan(IBuilderContext context, INamedType buildKey)
{
var itemType = (context ?? throw new ArgumentNullException(nameof(context))).BuildKey
.Type
.GetTypeInfo()
.GenericTypeArguments
.First();
var buildMethod = ResolveMethod.MakeGenericMethod(itemType)
.CreateDelegate(typeof(DynamicBuildPlanMethod));
return new DynamicMethodBuildPlan((DynamicBuildPlanMethod)buildMethod);
}
private static void BuildResolveEnumerable<T>(IBuilderContext context)
{
if (null == context.Existing)
{
var itemType = typeof(T);
var itemTypeInfo = itemType.GetTypeInfo();
var container = context.Container ?? context.NewBuildUp<IUnityContainer>();
if (itemTypeInfo.IsGenericTypeDefinition)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Constants.MustHaveOpenGenericType,
itemType.GetTypeInfo().Name));
}
var generic = new Lazy<Type>(() => itemType.GetGenericTypeDefinition());
IEnumerable<object> enumerable = container.Registrations
.Where(r => r.RegisteredType == itemType || (itemTypeInfo.IsGenericType &&
r.RegisteredType.GetTypeInfo().IsGenericTypeDefinition &&
r.RegisteredType == generic.Value))
.Select(r => context.NewBuildUp(new NamedTypeBuildKey(itemType, r.Name)))
.ToArray();
context.Existing = CastMethod.MakeGenericMethod(itemType).Invoke(null, new object[] { enumerable });
context.BuildComplete = true;
}
context.SetPerBuildSingleton();
}
}
}

Просмотреть файл

@ -28,9 +28,10 @@ namespace Unity.ObjectBuilder.BuildPlan.Selection
protected override IResolverPolicy CreateResolver(ParameterInfo parameter) protected override IResolverPolicy CreateResolver(ParameterInfo parameter)
{ {
// Resolve all DependencyAttributes on this parameter, if any // Resolve all DependencyAttributes on this parameter, if any
var attrs = (parameter ?? throw new ArgumentNullException(nameof(parameter))).GetCustomAttributes(false).OfType<DependencyResolutionAttribute>().ToList(); var attrs = (parameter ?? throw new ArgumentNullException(nameof(parameter))).GetCustomAttributes(false)
.OfType<DependencyResolutionAttribute>()
if (attrs.Count > 0) .ToArray();
if (attrs.Length > 0)
{ {
// Since this attribute is defined with MultipleUse = false, the compiler will // Since this attribute is defined with MultipleUse = false, the compiler will
// enforce at most one. So we don't need to check for more. // enforce at most one. So we don't need to check for more.

Просмотреть файл

@ -1,72 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Reflection;
using Unity.Builder;
using Unity.Policy;
namespace Unity.ObjectBuilder.Policies
{
/// <summary>
/// An implementation of <see cref="IBuildKeyMappingPolicy"/> that can map
/// generic types.
/// </summary>
public class GenericTypeBuildKeyMappingPolicy : IBuildKeyMappingPolicy
{
private readonly NamedTypeBuildKey _destinationKey;
/// <summary>
/// Create a new <see cref="GenericTypeBuildKeyMappingPolicy"/> instance
/// that will map generic types.
/// </summary>
/// <param name="destinationKey">Build key to map to. This must be or contain an open generic type.</param>
public GenericTypeBuildKeyMappingPolicy(NamedTypeBuildKey destinationKey)
{
if (!(destinationKey ?? throw new ArgumentNullException(nameof(destinationKey))).Type.GetTypeInfo().IsGenericTypeDefinition)
{
throw new ArgumentException(
string.Format(CultureInfo.CurrentCulture,
Constants.MustHaveOpenGenericType,
destinationKey.Type.GetTypeInfo().Name));
}
_destinationKey = destinationKey;
}
/// <summary>
/// Maps the build key.
/// </summary>
/// <param name="buildKey">The build key to map.</param>
/// <param name="context">Current build context. Used for contextual information
/// if writing a more sophisticated mapping.</param>
/// <returns>The new build key.</returns>
public INamedType Map(INamedType buildKey, IBuilderContext context)
{
var originalTypeInfo = (buildKey ?? throw new ArgumentNullException(nameof(buildKey))).Type.GetTypeInfo();
if (originalTypeInfo.IsGenericTypeDefinition)
{
// No need to perform a mapping - the source type is an open generic
return _destinationKey;
}
GuardSameNumberOfGenericArguments(originalTypeInfo);
Type[] genericArguments = originalTypeInfo.GenericTypeArguments;
Type resultType = _destinationKey.Type.MakeGenericType(genericArguments);
return new NamedTypeBuildKey(resultType, _destinationKey.Name);
}
private void GuardSameNumberOfGenericArguments(TypeInfo sourceTypeInfo)
{
if (sourceTypeInfo.GenericTypeArguments.Length != DestinationType.GetTypeInfo().GenericTypeParameters.Length)
{
throw new ArgumentException(
string.Format(CultureInfo.CurrentCulture,
Constants.MustHaveSameNumberOfGenericArguments,
sourceTypeInfo.Name, DestinationType.Name),
nameof(sourceTypeInfo));
}
}
private Type DestinationType => _destinationKey.Type;
}
}

Просмотреть файл

@ -1,22 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Unity.Builder;
using Unity.Policy;
namespace Unity.ObjectBuilder.Policies
{
/// <summary>
/// Provides access to the names registered for a container.
/// </summary>
public interface IRegisteredNamesPolicy : IBuilderPolicy
{
/// <summary>
/// Gets the names registered for a type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The names registered for <paramref name="type"/>.</returns>
IEnumerable<string> GetRegisteredNames(Type type);
}
}

Просмотреть файл

@ -1,24 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Container.Registration;
namespace Unity.ObjectBuilder.Policies
{
internal class RegisteredNamesPolicy : IRegisteredNamesPolicy
{
private readonly NamedTypesRegistry _registry;
public RegisteredNamesPolicy(NamedTypesRegistry registry)
{
_registry = registry;
}
public IEnumerable<string> GetRegisteredNames(Type type)
{
return _registry.GetKeys(type).Where(s => !string.IsNullOrEmpty(s));
}
}
}

Просмотреть файл

@ -1,63 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.ObjectBuilder.Policies;
using Unity.Policy;
namespace Unity.ObjectBuilder.Strategies
{
/// <summary>
/// This strategy implements the logic that will call container.ResolveAll
/// when an array parameter is detected.
/// </summary>
public class ArrayResolutionStrategy : BuilderStrategy
{
private delegate object ArrayResolver(IBuilderContext context);
private static readonly MethodInfo GenericResolveArrayMethod = typeof(ArrayResolutionStrategy)
.GetTypeInfo().GetDeclaredMethod(nameof(ResolveArray));
/// <summary>
/// Do the PreBuildUp stage of construction. This is where the actual work is performed.
/// </summary>
/// <param name="context">Current build context.</param>
public override object PreBuildUp(IBuilderContext context)
{
Type typeToBuild = context.BuildKey.Type;
if (typeToBuild.IsArray && typeToBuild.GetArrayRank() == 1)
{
Type elementType = typeToBuild.GetElementType();
MethodInfo resolverMethod = GenericResolveArrayMethod.MakeGenericMethod(elementType);
ArrayResolver resolver = (ArrayResolver)resolverMethod.CreateDelegate(typeof(ArrayResolver));
context.Existing = resolver(context);
context.BuildComplete = true;
}
return null;
}
private static object ResolveArray<T>(IBuilderContext context)
{
var registeredNamesPolicy = context.Policies.Get<IRegisteredNamesPolicy>(null);
if (registeredNamesPolicy != null)
{
var registeredNames = registeredNamesPolicy.GetRegisteredNames(typeof(T));
if (typeof(T).GetTypeInfo().IsGenericType)
{
registeredNames = registeredNames.Concat(registeredNamesPolicy.GetRegisteredNames(typeof(T).GetGenericTypeDefinition()));
}
registeredNames = registeredNames.Distinct();
return registeredNames.Select(context.NewBuildUp<T>).ToArray();
}
return new T[0];
}
}
}

Просмотреть файл

@ -1,60 +0,0 @@
using System;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Injection;
using Unity.Lifetime;
using Unity.ObjectBuilder.Policies;
using Unity.Policy;
using Unity.Registration;
using Unity.Strategy;
namespace Unity.ObjectBuilder.Strategies
{
/// <summary>
/// Represents a strategy for mapping build keys in the build up operation.
/// </summary>
public class BuildKeyMappingStrategy : BuilderStrategy, IRegisterTypeStrategy
{
/// <summary>
/// Called during the chain of responsibility for a build operation. Looks for the <see cref="IBuildKeyMappingPolicy"/>
/// and if found maps the build key for the current operation.
/// </summary>
/// <param name="context">The context for the operation.</param>
public override object PreBuildUp(IBuilderContext context)
{
var policy = context.Policies.Get<IBuildKeyMappingPolicy>(context.BuildKey, out _);
if (null == policy) return null;
context.BuildKey = policy.Map(context.BuildKey, context);
return null;
}
public void RegisterType(IContainerContext context, Type typeFrom, Type typeTo, string name,
LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
{
if (null == typeFrom || typeFrom == typeTo)
{
context.Policies.Clear(typeTo, name, typeof(IBuildKeyMappingPolicy));
return;
}
if (typeFrom.GetTypeInfo().IsGenericTypeDefinition && typeTo.GetTypeInfo().IsGenericTypeDefinition)
{
context.Policies.Set<IBuildKeyMappingPolicy>(new GenericTypeBuildKeyMappingPolicy(new NamedTypeBuildKey(typeTo, name)),
new NamedTypeBuildKey(typeFrom, name));
}
else
{
context.Policies.Set(typeFrom, name, typeof(IBuildKeyMappingPolicy),
new BuildKeyMappingPolicy(new NamedTypeBuildKey(typeTo, name)));
}
var members = null == injectionMembers ? new InjectionMember[0] : injectionMembers;
if (!members.Where(m => m is InjectionConstructor || m is InjectionMethod || m is InjectionProperty).Any() && !(lifetimeManager is IRequireBuildUpPolicy))
context.Policies.Set(typeFrom, name, typeof(IBuildPlanPolicy), new ResolveBuildUpPolicy());
}
}
}

Просмотреть файл

@ -1,40 +0,0 @@
using System;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Lifetime;
using Unity.ObjectBuilder.Policies;
using Unity.Policy;
using Unity.Registration;
using Unity.Strategy;
namespace Unity.ObjectBuilder.Strategies
{
/// <summary>
/// A <see cref="BuilderStrategy"/> that will look for a build plan
/// in the current context. If it exists, it invokes it, otherwise
/// it creates one and stores it for later, and invokes it.
/// </summary>
public class BuildPlanStrategy : BuilderStrategy
{
/// <summary>
/// Called during the chain of responsibility for a build operation.
/// </summary>
/// <param name="context">The context for the operation.</param>
public override object PreBuildUp(IBuilderContext context)
{
var plan = context.Policies.Get<IBuildPlanPolicy>(context.OriginalBuildKey, out var buildPlanLocation);
if (plan == null || plan is OverriddenBuildPlanMarkerPolicy)
{
var planCreator = context.Policies.Get<IBuildPlanCreatorPolicy>(context.BuildKey, out var creatorLocation);
if (planCreator != null)
{
plan = planCreator.CreatePlan(context, context.BuildKey);
(buildPlanLocation ?? creatorLocation).Set(plan, context.OriginalBuildKey);
}
}
plan?.BuildUp(context);
return null;
}
}
}

Просмотреть файл

@ -1,160 +0,0 @@
using System;
using System.Reflection;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Exceptions;
using Unity.Extension;
using Unity.Lifetime;
using Unity.Policy;
using Unity.Registration;
using Unity.Strategy;
namespace Unity.ObjectBuilder.Strategies
{
/// <summary>
/// An <see cref="IBuilderStrategy"/> implementation that uses
/// a <see cref="ILifetimePolicy"/> to figure out if an object
/// has already been created and to update or remove that
/// object from some backing store.
/// </summary>
public class LifetimeStrategy : BuilderStrategy, IRegisterTypeStrategy
{
#region Fields
private readonly object _genericLifetimeManagerLock = new object();
#endregion
#region BuilderStrategy
/// <summary>
/// Called during the chain of responsibility for a build operation. The
/// PreBuildUp method is called when the chain is being executed in the
/// forward direction.
/// </summary>
/// <param name="context">Context of the build operation.</param>
public override object PreBuildUp(IBuilderContext context)
{
if (context.Existing != null) return null;
var lifetimePolicy = GetLifetimePolicy(context, out var _);
if (lifetimePolicy is IRequiresRecovery recovery)
{
context.RecoveryStack.Add(recovery);
}
var existing = lifetimePolicy?.GetValue(context.Lifetime);
if (existing != null)
{
context.Existing = existing;
context.BuildComplete = true;
}
return null;
}
/// <summary>
/// Called during the chain of responsibility for a build operation. The
/// PostBuildUp method is called when the chain has finished the PreBuildUp
/// phase and executes in reverse order from the PreBuildUp calls.
/// </summary>
/// <param name="context">Context of the build operation.</param>
public override void PostBuildUp(IBuilderContext context, object pre = null)
{
// If we got to this method, then we know the lifetime policy didn't
// find the object. So we go ahead and store it.
ILifetimePolicy lifetimePolicy = GetLifetimePolicy(context, out IPolicyList _);
lifetimePolicy.SetValue(context.Existing, context.Lifetime);
}
private ILifetimePolicy GetLifetimePolicy(IBuilderContext context, out IPolicyList source)
{
ILifetimePolicy policy = context.Policies.GetNoDefault<ILifetimePolicy>(context.OriginalBuildKey, false, out source);
if (policy == null && context.OriginalBuildKey.Type.GetTypeInfo().IsGenericType)
{
policy = GetLifetimePolicyForGenericType(context, out source);
}
if (policy == null)
{
policy = TransientLifetimeManager.Instance;
context.PersistentPolicies.Set(policy, context.OriginalBuildKey);
}
return policy;
}
private ILifetimePolicy GetLifetimePolicyForGenericType(IBuilderContext context, out IPolicyList factorySource)
{
var typeToBuild = context.OriginalBuildKey.Type;
object openGenericBuildKey = new NamedTypeBuildKey(typeToBuild.GetGenericTypeDefinition(),
context.OriginalBuildKey.Name);
var factoryPolicy = context.Policies
.Get<ILifetimeFactoryPolicy>(openGenericBuildKey, out factorySource);
if (factoryPolicy != null)
{
// creating the lifetime policy can result in arbitrary code execution
// in particular it will likely result in a Resolve call, which could result in locking
// to avoid deadlocks the new lifetime policy is created outside the lock
// multiple instances might be created, but only one instance will be used
ILifetimePolicy newLifetime = factoryPolicy.CreateLifetimePolicy();
lock (_genericLifetimeManagerLock)
{
// check whether the policy for closed-generic has been added since first checked
var lifetime = factorySource.GetNoDefault<ILifetimePolicy>(context.BuildKey);
if (lifetime == null)
{
factorySource.Set(newLifetime, context.BuildKey);
lifetime = newLifetime;
}
return lifetime;
}
}
return null;
}
#endregion
#region IRegisterTypeStrategy
public void RegisterType(IContainerContext context, Type typeFrom, Type typeTo, string name,
LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
{
var lifetimeType = typeFrom ?? typeTo;
if (null == lifetimeManager)
{
context.Policies.Clear(lifetimeType, name, typeof(ILifetimePolicy));
return;
}
if (lifetimeManager.InUse)
{
throw new InvalidOperationException(Constants.LifetimeManagerInUse);
}
if (lifetimeType.GetTypeInfo().IsGenericTypeDefinition)
{
LifetimeManagerFactory factory = new LifetimeManagerFactory((ExtensionContext)context, lifetimeManager);
context.Policies.Set<ILifetimeFactoryPolicy>(factory, new NamedTypeBuildKey(lifetimeType, name));
}
else
{
lifetimeManager.InUse = true;
context.Policies.Set<ILifetimePolicy>(lifetimeManager, new NamedTypeBuildKey(lifetimeType, name));
if (lifetimeManager is IDisposable)
{
context.Lifetime.Add(lifetimeManager);
}
}
}
#endregion
}
}

Просмотреть файл

@ -4,15 +4,15 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Unity.Builder; using Unity.Builder;
using Unity.Policy; using Unity.ObjectBuilder.BuildPlan.DynamicMethod.Creation;
namespace Unity.ObjectBuilder.BuildPlan namespace Unity.Policy.BuildPlanCreator
{ {
/// <summary> /// <summary>
/// Build plan for <see cref="Func{TResult}"/> that will return a Func that will resolve the requested type /// Build plan for <see cref="Func{TResult}"/> that will return a Func that will resolve the requested type
/// through this container later. /// through this container later.
/// </summary> /// </summary>
internal class DeferredResolveBuildPlanPolicy : IBuildPlanPolicy internal class DeferredResolveCreatorPolicy : IBuildPlanPolicy
{ {
public void BuildUp(IBuilderContext context) public void BuildUp(IBuilderContext context)
{ {
@ -34,7 +34,7 @@ namespace Unity.ObjectBuilder.BuildPlan
context.Existing = resolveMethod; context.Existing = resolveMethod;
context.SetPerBuildSingleton(); DynamicMethodConstructorStrategy.SetPerBuildSingleton(context);
} }
} }

Просмотреть файл

@ -0,0 +1,41 @@
using System;
using System.Reflection;
using Unity.Builder;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod;
namespace Unity.Policy.BuildPlanCreator
{
public class DelegateBasedBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy
{
#region Fields
private readonly MethodInfo _resolveMethod;
private readonly Func<IBuilderContext, Type> _getTypeFunc;
#endregion
#region Constructors
public DelegateBasedBuildPlanCreatorPolicy(MethodInfo resolveMethod, Func<IBuilderContext, Type> getTypeFunc)
{
_resolveMethod = resolveMethod;
_getTypeFunc = getTypeFunc;
}
#endregion
#region IBuildPlanCreatorPolicy
public IBuildPlanPolicy CreatePlan(IBuilderContext context, INamedType buildKey)
{
var buildMethod = _resolveMethod.MakeGenericMethod(_getTypeFunc(context))
.CreateDelegate(typeof(DynamicBuildPlanMethod));
return new DynamicMethodBuildPlan((DynamicBuildPlanMethod)buildMethod);
}
#endregion
}
}

Просмотреть файл

@ -5,22 +5,21 @@ using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Unity.Builder; using Unity.Builder;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod; using Unity.ObjectBuilder.BuildPlan.DynamicMethod;
using Unity.Policy;
namespace Unity.ObjectBuilder.BuildPlan namespace Unity.Policy.BuildPlanCreator
{ {
/// <summary> /// <summary>
/// An <see cref="IBuildPlanCreatorPolicy"/> implementation /// An <see cref="IBuildPlanCreatorPolicy"/> implementation
/// that constructs a build plan for creating <see cref="Lazy{T}"/> objects. /// that constructs a build plan for creating <see cref="Lazy{T}"/> objects.
/// </summary> /// </summary>
public class LazyDynamicMethodBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy public class GenericLazyBuildPlanCreatorPolicy : IBuildPlanCreatorPolicy
{ {
private static readonly MethodInfo BuildResolveLazyMethod; private static readonly MethodInfo BuildResolveLazyMethod;
private static readonly MethodInfo BuildResolveAllLazyMethod; private static readonly MethodInfo BuildResolveAllLazyMethod;
static LazyDynamicMethodBuildPlanCreatorPolicy() static GenericLazyBuildPlanCreatorPolicy()
{ {
var info = typeof(LazyDynamicMethodBuildPlanCreatorPolicy).GetTypeInfo(); var info = typeof(GenericLazyBuildPlanCreatorPolicy).GetTypeInfo();
BuildResolveLazyMethod = BuildResolveLazyMethod =
info.GetDeclaredMethod(nameof(BuildResolveLazy)); info.GetDeclaredMethod(nameof(BuildResolveLazy));

Просмотреть файл

@ -1,26 +1,35 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. using System;
using Unity.Builder; using Unity.Builder;
using Unity.Policy;
namespace Unity.ObjectBuilder.Policies namespace Unity.Policy.Mapping
{ {
/// <summary> /// <summary>
/// Represents a builder policy for mapping build keys. /// Represents a builder policy for mapping build keys.
/// </summary> /// </summary>
public class BuildKeyMappingPolicy : IBuildKeyMappingPolicy public class BuildKeyMappingPolicy : NamedTypeBase, IBuildKeyMappingPolicy
{ {
private readonly NamedTypeBuildKey _newBuildKey; #region Constructors
/// <summary> /// <summary>
/// Initialize a new instance of the <see cref="BuildKeyMappingPolicy"/> with the new build key. /// Initialize a new instance of the <see cref="BuildKeyMappingPolicy"/> with the new build key.
/// </summary> /// </summary>
/// <param name="newBuildKey">The new build key.</param> /// <param name="newBuildKey">The new build key.</param>
public BuildKeyMappingPolicy(NamedTypeBuildKey newBuildKey) public BuildKeyMappingPolicy(INamedType newBuildKey)
: base(newBuildKey.Type, newBuildKey.Name)
{ {
_newBuildKey = newBuildKey;
} }
public BuildKeyMappingPolicy(Type type, string name)
: base(type, name)
{
}
#endregion
#region IBuildKeyMappingPolicy
/// <summary> /// <summary>
/// Maps the build key. /// Maps the build key.
/// </summary> /// </summary>
@ -30,7 +39,9 @@ namespace Unity.ObjectBuilder.Policies
/// <returns>The new build key.</returns> /// <returns>The new build key.</returns>
public INamedType Map(INamedType buildKey, IBuilderContext context) public INamedType Map(INamedType buildKey, IBuilderContext context)
{ {
return _newBuildKey; return this;
} }
#endregion
} }
} }

Просмотреть файл

@ -0,0 +1,73 @@
using System;
using System.Globalization;
using System.Reflection;
using Unity.Builder;
namespace Unity.Policy.Mapping
{
/// <summary>
/// An implementation of <see cref="IBuildKeyMappingPolicy"/> that can map
/// generic types.
/// </summary>
public class GenericTypeBuildKeyMappingPolicy : NamedTypeBase, IBuildKeyMappingPolicy
{
#region Constructors
/// <summary>
/// Create a new <see cref="GenericTypeBuildKeyMappingPolicy"/> instance
/// that will map generic types.
/// </summary>
/// <param name="type">Type mapped to</param>
/// <param name="name">Name</param>
public GenericTypeBuildKeyMappingPolicy(Type type, string name)
: base(type, name)
{
}
/// <summary>
/// Create a new <see cref="GenericTypeBuildKeyMappingPolicy"/> instance
/// that will map generic types.
/// </summary>
/// <param name="destinationKey">Build key to map to. This must be or contain an open generic type.</param>
public GenericTypeBuildKeyMappingPolicy(INamedType destinationKey)
: base(destinationKey.Type, destinationKey.Name)
{
}
#endregion
#region IBuildKeyMappingPolicy
/// <summary>
/// Maps the build key.
/// </summary>
/// <param name="buildKey">The build key to map.</param>
/// <param name="context">Current build context. Used for contextual information
/// if writing a more sophisticated mapping.</param>
/// <returns>The new build key.</returns>
public INamedType Map(INamedType buildKey, IBuilderContext context)
{
var targetTypeInfo = buildKey.Type.GetTypeInfo();
if (targetTypeInfo.IsGenericTypeDefinition)
{
// No need to perform a mapping - the source type is an open generic
return this;
}
if (targetTypeInfo.GenericTypeArguments.Length != Type.GetTypeInfo().GenericTypeParameters.Length)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Constants.MustHaveSameNumberOfGenericArguments,
buildKey.Type.Name, Type.Name),
nameof(buildKey.Type));
}
Type[] genericArguments = targetTypeInfo.GenericTypeArguments;
Type resultType = Type.MakeGenericType(genericArguments);
return new NamedTypeBuildKey(resultType, Name);
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,161 @@
using System;
using System.Globalization;
using System.Reflection;
using Unity.Builder;
using Unity.Lifetime;
using Unity.Policy;
using Unity.Storage;
namespace Unity.Registration
{
/// <summary>
/// This class holds instance registration
/// </summary>
public class InstanceRegistration : NamedTypeBase,
IContainerRegistration,
IBuildPlanCreatorPolicy,
IBuildPlanPolicy,
IPolicySet,
IDisposable
{
#region Constructors
/// <summary>
/// Instance registration with the container.
/// </summary>
/// <remarks> <para>
/// Instance registration is much like setting a type as a singleton, except that instead
/// of the container creating the instance the first time it is requested, the user
/// creates the instance ahead of type and adds that instance to the container.
/// </para></remarks>
/// <param name="registrationType">Type of instance to register (may be an implemented interface instead of the full type).</param>
/// <param name="instance">Object to be returned.</param>
/// <param name="registrationName">Name for registration.</param>
/// <param name="lifetimeManager">
/// <para>If null or <see cref="ContainerControlledLifetimeManager"/>, the container will take over the lifetime of the instance,
/// calling Dispose on it (if it's <see cref="IDisposable"/>) when the container is Disposed.</para>
/// <para>
/// If <see cref="ExternallyControlledLifetimeManager"/>, container will not maintain a strong reference to <paramref name="instance"/>.
/// User is responsible for disposing instance, and for keeping the instance typeFrom being garbage collected.</para></param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public InstanceRegistration(Type registrationType, string registrationName, object instance, LifetimeManager lifetimeManager)
: base(registrationType ?? (instance ?? throw new ArgumentNullException(nameof(instance))).GetType(),
string.IsNullOrEmpty(registrationName) ? null : registrationName)
{
// Validate input
if (null != registrationType) InstanceIsAssignable(registrationType, instance, nameof(instance));
LifetimeManager = lifetimeManager;
MappedToType = registrationType ?? instance.GetType();
}
#endregion
#region IPolicySet
public IBuilderPolicy Get(Type policyInterface)
{
if (typeof(ILifetimePolicy) == policyInterface)
return LifetimeManager;
if (typeof(IBuildPlanPolicy) == policyInterface ||
typeof(IBuildPlanCreatorPolicy) == policyInterface)
return this;
return null;
}
public void Set(Type policyInterface, IBuilderPolicy policy)
{
}
public void Clear(Type policyInterface)
{
}
public void ClearAll()
{
}
#endregion
#region IContainerRegistration
public Type RegisteredType => Type;
public Type MappedToType { get; }
public LifetimeManager LifetimeManager { get; }
#endregion
#region IBuildPlanCreatorPolicy
public IBuildPlanPolicy CreatePlan(IBuilderContext context, INamedType buildKey)
{
return this;
}
#endregion
#region IBuildPlanPolicy
public void BuildUp(IBuilderContext context)
{
context.Existing = LifetimeManager.GetValue();
context.BuildComplete = true;
}
#endregion
#region Implementation
private static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName)
{
if (!(assignmentTargetType ?? throw new ArgumentNullException(nameof(assignmentTargetType)))
.GetTypeInfo().IsAssignableFrom((assignmentInstance ?? throw new ArgumentNullException(nameof(assignmentInstance))).GetType().GetTypeInfo()))
{
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Constants.TypesAreNotAssignable,
assignmentTargetType, GetTypeName(assignmentInstance)),
argumentName);
}
}
private static string GetTypeName(object assignmentInstance)
{
string assignmentInstanceType;
try
{
assignmentInstanceType = assignmentInstance.GetType().FullName;
}
catch (Exception)
{
assignmentInstanceType = Constants.UnknownType;
}
return assignmentInstanceType;
}
#endregion
#region IDisposable
public void Dispose()
{
if (LifetimeManager is IDisposable disposable)
disposable.Dispose();
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,132 @@
using System;
using Unity.Builder;
using Unity.Policy;
using Unity.Storage;
namespace Unity.Registration
{
public class InternalRegistration : LinkedNode<Type, IBuilderPolicy>,
IPolicySet,
INamedType
{
#region Fields
private readonly int _hash;
#endregion
#region Constructors
public InternalRegistration(Type type, string name)
{
Name = name;
Type = type;
_hash = (Type?.GetHashCode() ?? 0 + 37) ^ (Name?.GetHashCode() ?? 0 + 17);
}
#endregion
#region IPolicySet
public virtual IBuilderPolicy Get(Type policyInterface)
{
for (var node = (LinkedNode<Type, IBuilderPolicy>)this; node != null; node = node.Next)
{
if (node.Key == policyInterface)
return node.Value;
}
return null;
}
public virtual void Set(Type policyInterface, IBuilderPolicy policy)
{
LinkedNode<Type, IBuilderPolicy> node;
LinkedNode<Type, IBuilderPolicy> last = null;
for (node = this; node != null; node = node.Next)
{
if (node.Key == policyInterface)
{
// Found it
node.Value = policy;
return;
}
last = node;
}
// Not found, so add a new one
last.Next = new LinkedNode<Type, IBuilderPolicy>
{
Key = policyInterface,
Value = policy
};
}
public virtual void Clear(Type policyInterface)
{
LinkedNode<Type, IBuilderPolicy> node;
LinkedNode<Type, IBuilderPolicy> last = null;
for (node = this; node != null; node = node.Next)
{
if (node.Key == policyInterface)
{
if (null == last)
{
Key = node.Next?.Key;
Value = node.Next?.Value;
Next = node.Next?.Next;
}
else
{
last.Key = node.Next?.Key;
last.Value = node.Next?.Value;
last.Next = node.Next?.Next;
}
return;
}
last = node;
}
}
public virtual void ClearAll()
{
Key = null;
Value = null;
Next = null;
}
#endregion
#region INamedType
public Type Type { get; }
public string Name { get; }
public override bool Equals(object obj)
{
return obj is INamedType registration &&
Type == registration.Type &&
Name == registration.Name;
}
public override int GetHashCode()
{
return _hash;
}
public static implicit operator NamedTypeBuildKey(InternalRegistration namedType)
{
return new NamedTypeBuildKey(namedType.Type, namedType.Name);
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,66 @@
using System;
using Unity.Lifetime;
using Unity.Policy;
namespace Unity.Registration
{
public class TypeRegistration : InternalRegistration,
IContainerRegistration
{
#region Constructors
public TypeRegistration(Type typeFrom, Type typeTo, string name, LifetimeManager lifetimeManager)
: base(typeFrom ?? typeTo, string.IsNullOrEmpty(name) ? null : name)
{
MappedToType = typeTo;
// Make sure manager is not being used already
if (lifetimeManager.InUse)
{
if (lifetimeManager is ILifetimeFactoryPolicy factory)
lifetimeManager = (LifetimeManager)factory.CreateLifetimePolicy();
else
throw new InvalidOperationException(Constants.LifetimeManagerInUse);
}
LifetimeManager = lifetimeManager;
LifetimeManager.InUse = true;
}
#endregion
#region IContainerRegistration
public Type RegisteredType => Type;
/// <summary>
/// The type that this registration is mapped to. If no type mapping was done, the
/// <see cref="InternalRegistration.Type"/> property and this one will have the same value.
/// </summary>
public Type MappedToType { get; }
/// <summary>
/// The lifetime manager for this registration.
/// </summary>
/// <remarks>
/// This property will be null if this registration is for an open generic.</remarks>
public LifetimeManager LifetimeManager { get; }
#endregion
#region IPolicySet
public override IBuilderPolicy Get(Type policyInterface)
{
if (typeof(ILifetimePolicy) == policyInterface)
return LifetimeManager;
return base.Get(policyInterface);
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,35 @@
namespace Unity.Resolution
{
public enum TypeSelectStage
{
/// <summary>
/// First stage. By default, nothing happens here.
/// </summary>
Setup,
/// <summary>
/// Checks for already registered types
/// </summary>
Registration,
/// <summary>
/// Checks if type is array
/// </summary>
Array,
/// <summary>
/// Checks if type is generic
/// </summary>
Generic,
/// <summary>
/// Checks if type is Plain old clr object
/// </summary>
Poco,
/// <summary>
/// Throws an exception if pype could not be found
/// </summary>
Exception
}
}

199
src/Storage/HashRegistry.cs Normal file
Просмотреть файл

@ -0,0 +1,199 @@
using System;
using System.Collections.Generic;
using Unity.Utility;
namespace Unity.Storage
{
internal class HashRegistry<TKey, TValue> : IRegistry<TKey, TValue>
{
#region Constants
private const float LoadFactor = 0.72f;
#endregion
#region Fields
public readonly int[] Buckets;
public readonly Entry[] Entries;
public int Count;
#endregion
#region Constructors
public HashRegistry(int capacity)
{
var size = Prime.GetPrime(capacity);
Buckets = new int[size];
Entries = new Entry[size];
for (var i = 0; i < Buckets.Length; i++) Buckets[i] = -1;
}
public HashRegistry(int capacity, LinkedNode<TKey, TValue> head)
{
var size = Prime.GetPrime(capacity);
Buckets = new int[size];
Entries = new Entry[size];
for (var i = 0; i < Buckets.Length; i++) Buckets[i] = -1;
for (var node = head; node != null; node = node.Next)
{
this[node.Key] = node.Value;
}
}
public HashRegistry(HashRegistry<TKey, TValue> dictionary)
{
var size = Prime.GetPrime(dictionary.Entries.Length * 2);
Buckets = new int[size];
Entries = new Entry[size];
for (var i = 0; i < Buckets.Length; i++) Buckets[i] = -1;
Array.Copy(dictionary.Entries, 0, Entries, 0, dictionary.Count);
for (var i = 0; i < dictionary.Count; i++)
{
var hashCode = Entries[i].HashCode;
if (hashCode < 0) continue;
var bucket = hashCode % size;
Entries[i].Next = Buckets[bucket];
Buckets[bucket] = i;
}
Count = dictionary.Count;
dictionary.Count = 0;
}
#endregion
#region IRegistry
public TValue this[TKey key]
{
get
{
var hashCode = null == key ? 0 : key.GetHashCode() & 0x7FFFFFFF;
for (var i = Buckets[hashCode % Buckets.Length]; i >= 0; i = Entries[i].Next)
{
if (Entries[i].HashCode == hashCode && Equals(Entries[i].Key, key)) return Entries[i].Value;
}
return default(TValue);
}
set
{
var hashCode = null == key ? 0 : key.GetHashCode() & 0x7FFFFFFF;
var targetBucket = hashCode % Buckets.Length;
for (var i = Buckets[targetBucket]; i >= 0; i = Entries[i].Next)
{
if (Entries[i].HashCode == hashCode && Equals(Entries[i].Key, key))
{
Entries[i].Value = value;
return;
}
}
Entries[Count].HashCode = hashCode;
Entries[Count].Next = Buckets[targetBucket];
Entries[Count].Key = key;
Entries[Count].Value = value;
Buckets[targetBucket] = Count;
Count++;
}
}
public bool RequireToGrow => (Entries.Length - Count) < 100 &&
(float)Count / Entries.Length > LoadFactor;
public IEnumerable<TKey> Keys
{
get
{
for (var i = 0; i < Count; i++)
{
yield return Entries[i].Key;
}
}
}
public IEnumerable<TValue> Values
{
get
{
for (var i = 0; i < Count; i++)
{
yield return Entries[i].Value;
}
}
}
public TValue GetOrAdd(TKey key, Func<TValue> factory)
{
var hashCode = (key?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % Buckets.Length;
for (var i = Buckets[targetBucket]; i >= 0; i = Entries[i].Next)
{
var entry = Entries[i];
if (entry.HashCode != hashCode || Equals(entry.Key, key)) continue;
return Entries[i].Value;
}
var value = factory();
Entries[Count].HashCode = hashCode;
Entries[Count].Next = Buckets[targetBucket];
Entries[Count].Key = key;
Entries[Count].Value = value;
Buckets[targetBucket] = Count;
Count++;
return value;
}
public TValue SetOrReplace(TKey key, TValue value)
{
var hashCode = (key?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % Buckets.Length;
for (var i = Buckets[targetBucket]; i >= 0; i = Entries[i].Next)
{
var entry = Entries[i];
if (entry.HashCode != hashCode || Equals(entry.Key, key)) continue;
var old = Entries[i].Value;
Entries[i].Value = value;
return old;
}
Entries[Count].HashCode = hashCode;
Entries[Count].Next = Buckets[targetBucket];
Entries[Count].Key = key;
Entries[Count].Value = value;
Buckets[targetBucket] = Count;
Count++;
return default(TValue);
}
#endregion
#region Nested Types
public struct Entry
{
public int HashCode;
public int Next;
public TKey Key;
public TValue Value;
}
#endregion
}
}

33
src/Storage/IPolicySet.cs Normal file
Просмотреть файл

@ -0,0 +1,33 @@
using System;
using Unity.Policy;
namespace Unity.Storage
{
public interface IPolicySet
{
/// <summary>
/// Get policy
/// </summary>
/// <param name="policyInterface">Type of policy to retrieve</param>
/// <returns>Instance of the policy or null if none found</returns>
IBuilderPolicy Get(Type policyInterface);
/// <summary>
/// Set policy
/// </summary>
/// <param name="policyInterface">Type of policy to be set</param>
/// <param name="policy">Policy instance to be set</param>
void Set(Type policyInterface, IBuilderPolicy policy);
/// <summary>
/// Remove specific policy from the list
/// </summary>
/// <param name="policyInterface">Type of policy to be removed</param>
void Clear(Type policyInterface);
/// <summary>
/// Removes all policies from the list.
/// </summary>
void ClearAll();
}
}

21
src/Storage/IRegistry.cs Normal file
Просмотреть файл

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
namespace Unity.Storage
{
public interface IRegistry<TKey, TValue>
{
TValue this[TKey index] { get; set; }
bool RequireToGrow { get; }
IEnumerable<TKey> Keys { get; }
IEnumerable<TValue> Values { get; }
TValue GetOrAdd(TKey key, Func<TValue> factory);
TValue SetOrReplace(TKey key, TValue value);
}
}

Просмотреть файл

@ -0,0 +1,9 @@
namespace Unity.Storage
{
public class LinkedNode<TKey, TValue>
{
public TKey Key;
public TValue Value;
public LinkedNode<TKey, TValue> Next;
}
}

Просмотреть файл

@ -0,0 +1,155 @@
using System;
using System.Collections.Generic;
using Unity.Policy;
namespace Unity.Storage
{
internal class LinkedRegistry : LinkedNode<string, IPolicySet>,
IRegistry<string, IPolicySet>
{
#region Fields
private int _count;
public const int ListToHashCutoverPoint = 8;
#endregion
#region Constructors
public LinkedRegistry(string key, IPolicySet value)
{
Key = key;
Value = value;
}
#endregion
#region IRegistry
public IPolicySet this[string key]
{
get
{
for (var node = (LinkedNode<string, IPolicySet>)this; node != null; node = node.Next)
{
if (Equals(node.Key, key))
return node.Value;
}
return default(IPolicySet);
}
set
{
LinkedNode<string, IPolicySet> node;
LinkedNode<string, IPolicySet> last = null;
for (node = this; node != null; node = node.Next)
{
if (Equals(node.Key, key))
{
// Found it
node.Value = value;
return;
}
last = node;
}
// Not found, so add a new one
last.Next = new LinkedNode<string, IPolicySet>
{
Key = key,
Value = value
};
_count++;
}
}
public bool RequireToGrow => ListToHashCutoverPoint < _count;
public IEnumerable<string> Keys
{
get
{
for (LinkedNode<string, IPolicySet> node = this; node != null; node = node.Next)
{
yield return node.Key;
}
}
}
public IEnumerable<IPolicySet> Values
{
get
{
for (LinkedNode<string, IPolicySet> node = this; node != null; node = node.Next)
{
yield return node.Value;
}
}
}
public IPolicySet GetOrAdd(string name, Func<IPolicySet> factory)
{
LinkedNode<string, IPolicySet> node;
LinkedNode<string, IPolicySet> last = null;
for (node = this; node != null; node = node.Next)
{
if (Equals(node.Key, name))
{
if (null == node.Value)
node.Value = factory();
return node.Value;
}
last = node;
}
// Not found, so add a new one
last.Next = new LinkedNode<string, IPolicySet>
{
Key = name,
Value = factory()
};
_count++;
return last.Next.Value;
}
public IPolicySet SetOrReplace(string name, IPolicySet value)
{
LinkedNode<string, IPolicySet> node;
LinkedNode<string, IPolicySet> last = null;
for (node = this; node != null; node = node.Next)
{
if (Equals(node.Key, name))
{
var old = node.Value;
node.Value = value;
return old;
}
last = node;
}
// Not found, so add a new one
last.Next = new LinkedNode<string, IPolicySet>
{
Key = name,
Value = value
};
_count++;
return null;
}
#endregion
}
}

Просмотреть файл

@ -1,9 +1,8 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using Unity.Policy; using Unity.Policy;
namespace Unity.Container namespace Unity.Storage
{ {
/// <summary> /// <summary>
/// A custom collection wrapper over <see cref="IBuilderPolicy"/> objects. /// A custom collection wrapper over <see cref="IBuilderPolicy"/> objects.
@ -95,7 +94,7 @@ namespace Unity.Container
lock (_sync) lock (_sync)
{ {
if (null == _policies) if (null == _policies)
_policies = new ConcurrentDictionary<PolicyKey, IBuilderPolicy>(PolicyKeyEqualityComparer.Default); _policies = new Dictionary<PolicyKey, IBuilderPolicy>(PolicyKeyEqualityComparer.Default);
} }
} }
_policies[new PolicyKey(type, name, policyInterface)] = policy; _policies[new PolicyKey(type, name, policyInterface)] = policy;

Просмотреть файл

@ -0,0 +1,126 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Registration;
using Unity.Utility;
namespace Unity.Storage
{
internal class ReverseHashSet : IEnumerable<IContainerRegistration>
{
#region Fields
private int[] _buckets;
private Slot[] _slots;
private int _count;
#endregion
#region Constructors
public ReverseHashSet()
{
_count = 0;
_buckets = new int[37];
_slots = new Slot[37];
}
#endregion
#region ReverseHashSet methods
/// <summary>
/// Add item to this HashSet. Later value replaces previosly set value
/// </summary>
/// <param name="item"></param>
public void Add(IContainerRegistration item)
{
var hashCode = item?.GetHashCode() & 0x7FFFFFFF ?? 0 ;
var bucket = hashCode % _buckets.Length;
var collisionCount = 0;
for (int i = _buckets[bucket]; --i >= 0; i = _slots[i].Next)
{
if (_slots[i].HashCode == hashCode && Equals(_slots[i].Value, item))
{
_slots[i].Value = item;
return;
}
collisionCount++;
}
if (_count == _slots.Length || 6 < collisionCount)
{
IncreaseCapacity();
bucket = hashCode % _buckets.Length;
}
_slots[_count].HashCode = hashCode;
_slots[_count].Value = item;
_slots[_count].Next = _buckets[bucket];
_count++;
_buckets[bucket] = _count;
}
public void Clear()
{
for (var i = 0; i < _count; i++)
{
_buckets[i] = 0;
_slots[_count].HashCode = 0;
_slots[_count].Value = null;
_slots[_count].Next = 0;
}
_count = 0;
}
public IEnumerator<IContainerRegistration> GetEnumerator()
{
for(var i = 0; i < _count; i++)
yield return _slots[i].Value;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region Helper methods
private void IncreaseCapacity()
{
int newSize = HashHelpers.ExpandPrime(_count * 2);
var newSlots = new Slot[newSize];
Array.Copy(_slots, newSlots, _count);
var newBuckets = new int[newSize];
for (var i = 0; i < _count; i++)
{
var bucket = newSlots[i].HashCode % newSize;
newSlots[i].Next = newBuckets[bucket];
newBuckets[bucket] = i + 1;
}
_slots = newSlots;
_buckets = newBuckets;
}
#endregion
private struct Slot
{
internal int HashCode; // Lower 31 bits of hash code, 0 if unused
internal IContainerRegistration Value;
internal int Next; // Index of next entry, 0 if last
}
}
}

Просмотреть файл

@ -8,26 +8,24 @@ using System.Reflection;
using Unity.Builder.Strategy; using Unity.Builder.Strategy;
using Unity.Strategy; using Unity.Strategy;
namespace Unity.Container namespace Unity.Storage
{ {
/// <summary> /// <summary>
/// Represents a chain of responsibility for builder strategies partitioned by stages. /// Represents a chain of responsibility for builder strategies partitioned by stages.
/// </summary> /// </summary>
/// <typeparam name="TStageEnum">The stage enumeration to partition the strategies.</typeparam> /// <typeparam name="TStageEnum">The stage enumeration to partition the strategies.</typeparam>
public class StagedStrategyChain<TStageEnum> : IStagedStrategyChain<IBuilderStrategy, TStageEnum>, /// <typeparam name="TStrategyType"></typeparam>
IEnumerable<IBuilderStrategy>, public class StagedStrategyChain<TStrategyType, TStageEnum> : IStagedStrategyChain<TStrategyType, TStageEnum>, IDisposable
IDisposable
{ {
#region Fields #region Fields
private readonly object _lockObject = new object(); private readonly object _lockObject = new object();
private readonly StagedStrategyChain<TStageEnum> _innerChain; private readonly StagedStrategyChain<TStrategyType, TStageEnum> _innerChain;
private readonly IList<IBuilderStrategy>[] _stages = private readonly IList<TStrategyType>[] _stages = new IList<TStrategyType>[typeof(TStageEnum).GetTypeInfo()
new IList<IBuilderStrategy>[typeof(TStageEnum).GetTypeInfo()
.DeclaredFields .DeclaredFields
.Count(f => f.IsPublic && f.IsStatic)]; .Count(f => f.IsPublic && f.IsStatic)];
private IStrategyChain _cache; private IEnumerable<TStrategyType> _cache;
#endregion #endregion
@ -35,7 +33,7 @@ namespace Unity.Container
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initialize a new instance of the <see cref="StagedStrategyChain{TStageEnum}"/> class. /// Initialize a new instance of the <see cref="StagedStrategyChain{TStrategyType,TStageEnum}"/> class.
/// </summary> /// </summary>
public StagedStrategyChain() public StagedStrategyChain()
: this(null) : this(null)
@ -43,10 +41,10 @@ namespace Unity.Container
} }
/// <summary> /// <summary>
/// Initialize a new instance of the <see cref="StagedStrategyChain{TStageEnum}"/> class with an inner strategy chain to use when building. /// Initialize a new instance of the <see cref="StagedStrategyChain{TStrategyType, TStageEnum}"/> class with an inner strategy chain to use when building.
/// </summary> /// </summary>
/// <param name="innerChain">The inner strategy chain to use first when finding strategies in the build operation.</param> /// <param name="innerChain">The inner strategy chain to use first when finding strategies in the build operation.</param>
public StagedStrategyChain(StagedStrategyChain<TStageEnum> innerChain) public StagedStrategyChain(StagedStrategyChain<TStrategyType,TStageEnum> innerChain)
{ {
if (null != innerChain) if (null != innerChain)
{ {
@ -56,7 +54,7 @@ namespace Unity.Container
for (var i = 0; i < _stages.Length; ++i) for (var i = 0; i < _stages.Length; ++i)
{ {
_stages[i] = new List<IBuilderStrategy>(); _stages[i] = new List<TStrategyType>();
} }
} }
@ -73,9 +71,9 @@ namespace Unity.Container
} }
} }
private IEnumerable<IBuilderStrategy> Enumerate(int i) private IEnumerable<TStrategyType> Enumerate(int i)
{ {
return (_innerChain?.Enumerate(i) ?? Enumerable.Empty<IBuilderStrategy>()).Concat(_stages[i]); return (_innerChain?.Enumerate(i) ?? Enumerable.Empty<TStrategyType>()).Concat(_stages[i]);
} }
#endregion #endregion
@ -94,7 +92,7 @@ namespace Unity.Container
/// </summary> /// </summary>
/// <param name="strategy">The strategy to add to the chain.</param> /// <param name="strategy">The strategy to add to the chain.</param>
/// <param name="stage">The stage to add the strategy.</param> /// <param name="stage">The stage to add the strategy.</param>
public void Add(IBuilderStrategy strategy, TStageEnum stage) public void Add(TStrategyType strategy, TStageEnum stage)
{ {
lock (_lockObject) lock (_lockObject)
{ {
@ -104,19 +102,6 @@ namespace Unity.Container
} }
} }
/// <summary>
/// Add a new strategy for the <paramref name="stage"/>.
/// </summary>
/// <typeparam name="TStrategy">The <see cref="System.Type"/> of strategy</typeparam>
/// <typeparam name="TStageEnum">The stage enum</typeparam>
/// <param name="chain">The chain this strategy is added to.</param>
/// <param name="stage">The stage to add the strategy to.</param>
public void AddNew<TStrategy>(TStageEnum stage)
where TStrategy : IBuilderStrategy, new()
{
Add(new TStrategy(), stage);
}
/// <summary> /// <summary>
/// Clear the current strategy chain list. /// Clear the current strategy chain list.
/// </summary> /// </summary>
@ -136,34 +121,27 @@ namespace Unity.Container
} }
} }
/// <summary>
/// Makes a strategy chain based on this instance.
/// </summary>
/// <returns>A new <see cref="StrategyChain"/>.</returns>
public IStrategyChain MakeStrategyChain()
{
lock (_lockObject)
{
if (null == _cache)
{
_cache = new StrategyChain(this);
}
return _cache;
}
}
#endregion #endregion
#region IEnumerable #region IEnumerable
public IEnumerator<IBuilderStrategy> GetEnumerator() public IEnumerator<TStrategyType> GetEnumerator()
{ {
return Enumerable.Range(0, _stages.Length) var cache = _cache;
if (null != cache) return cache.GetEnumerator();
lock (_lockObject)
{
if (null == _cache)
{
_cache = Enumerable.Range(0, _stages.Length)
.SelectMany(Enumerate) .SelectMany(Enumerate)
.GetEnumerator(); .ToArray();
}
return _cache.GetEnumerator();
}
} }
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()

Просмотреть файл

@ -0,0 +1,70 @@
using System;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Injection;
using Unity.Lifetime;
using Unity.ObjectBuilder.Policies;
using Unity.Policy;
using Unity.Policy.Mapping;
using Unity.Registration;
using Unity.Strategy;
namespace Unity.Strategies
{
/// <summary>
/// Represents a strategy for mapping build keys in the build up operation.
/// </summary>
public class BuildKeyMappingStrategy : BuilderStrategy, IRegisterTypeStrategy
{
#region BuilderStrategy
/// <summary>
/// Called during the chain of responsibility for a build operation. Looks for the <see cref="IBuildKeyMappingPolicy"/>
/// and if found maps the build key for the current operation.
/// </summary>
/// <param name="context">The context for the operation.</param>
public override object PreBuildUp(IBuilderContext context)
{
IBuildKeyMappingPolicy policy = context.PersistentPolicies.Get<IBuildKeyMappingPolicy>(context.OriginalBuildKey.Type,
context.OriginalBuildKey.Name, out _)
?? (context.OriginalBuildKey.Type.GetTypeInfo().IsGenericType
? context.Policies.Get<IBuildKeyMappingPolicy>(context.OriginalBuildKey.Type.GetGenericTypeDefinition(),
context.OriginalBuildKey.Name, out _)
: null);
if (null == policy) return null;
context.BuildKey = policy.Map(context.BuildKey, context);
return null;
}
#endregion
#region IRegisterTypeStrategy
public void RegisterType(IContainerContext context, Type typeFrom, Type typeTo, string name,
LifetimeManager lifetimeManager, params InjectionMember[] injectionMembers)
{
// Validate imput
if (typeFrom == null || typeFrom == typeTo) return;
// Set mapping policy
var policy = typeFrom.GetTypeInfo().IsGenericTypeDefinition && typeTo.GetTypeInfo().IsGenericTypeDefinition
? new GenericTypeBuildKeyMappingPolicy(typeTo, name)
: (IBuildKeyMappingPolicy)new BuildKeyMappingPolicy(typeTo, name);
context.Policies.Set(typeFrom, name, typeof(IBuildKeyMappingPolicy), policy);
// Require Re-Resolve if no injectors specified
var members = null == injectionMembers ? new InjectionMember[0] : injectionMembers;
var overrides = members.Where(m => m is InjectionConstructor || m is InjectionMethod || m is InjectionProperty).Any();
if (lifetimeManager is IRequireBuildUpPolicy || overrides) return;
context.Policies.Set(typeFrom, name, typeof(IBuildPlanPolicy), new ResolveBuildUpPolicy());
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,84 @@
using System;
using System.Reflection;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Exceptions;
using Unity.ObjectBuilder.Policies;
using Unity.Policy;
namespace Unity.Strategies
{
/// <summary>
/// A <see cref="BuilderStrategy"/> that will look for a build plan
/// in the current context. If it exists, it invokes it, otherwise
/// it creates one and stores it for later, and invokes it.
/// </summary>
public class BuildPlanStrategy : BuilderStrategy
{
#region BuilderStrategy
/// <summary>
/// Called during the chain of responsibility for a build operation.
/// </summary>
/// <param name="context">The context for the operation.</param>
public override object PreBuildUp(IBuilderContext context)
{
var plan = GetPolicy<IBuildPlanPolicy>(context.Policies, context.OriginalBuildKey, out var buildPlanLocation);
if (plan == null || plan is OverriddenBuildPlanMarkerPolicy)
{
var planCreator = GetPolicy<IBuildPlanCreatorPolicy>(context.Policies, context.BuildKey, out var creatorLocation);
if (planCreator != null)
{
plan = planCreator.CreatePlan(context, context.BuildKey);
(buildPlanLocation ?? creatorLocation).Set(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name, typeof(IBuildPlanPolicy), plan);
}
else
throw new ResolutionFailedException(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name, null, context);
}
plan?.BuildUp(context);
return null;
}
#endregion
#region Implementation
public static TPolicyInterface GetPolicy<TPolicyInterface>(IPolicyList list, INamedType buildKey, out IPolicyList containingPolicyList)
{
return (TPolicyInterface)(list.Get(buildKey.Type, buildKey.Name, typeof(TPolicyInterface), out containingPolicyList) ??
GetExtended(list, typeof(TPolicyInterface), buildKey, buildKey.Type, out containingPolicyList) ??
list.Get(null, null, typeof(TPolicyInterface), out containingPolicyList)); // Nothing! Get Default
}
private static IBuilderPolicy GetExtended(IPolicyList list, Type policyInterface, INamedType buildKey, Type buildType, out IPolicyList containingPolicyList)
{
containingPolicyList = null;
if (null == buildType) return null;
// Check if generic
if (buildType.GetTypeInfo().IsGenericType)
{
var newType = buildType.GetGenericTypeDefinition();
return list.Get(newType, buildKey.Name, policyInterface, out containingPolicyList) ??
list.Get(newType, string.Empty, policyInterface, out containingPolicyList);
}
// Check if array
if (buildType.IsArray && buildType.GetArrayRank() == 1)
{
return list.Get(typeof(Array), buildKey.Name, policyInterface, out containingPolicyList) ??
list.Get(typeof(Array), string.Empty, policyInterface, out containingPolicyList);
}
// Check default for type
return list.Get(buildType, string.Empty, policyInterface, out containingPolicyList);
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,104 @@
using System;
using System.Reflection;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Exceptions;
using Unity.Lifetime;
using Unity.Policy;
namespace Unity.Strategies
{
/// <summary>
/// An <see cref="IBuilderStrategy"/> implementation that uses
/// a <see cref="ILifetimePolicy"/> to figure out if an object
/// has already been created and to update or remove that
/// object from some backing store.
/// </summary>
public class LifetimeStrategy : BuilderStrategy
{
#region Fields
private readonly object _genericLifetimeManagerLock = new object();
#endregion
#region BuilderStrategy
/// <summary>
/// Called during the chain of responsibility for a build operation. The
/// PreBuildUp method is called when the chain is being executed in the
/// forward direction.
/// </summary>
/// <param name="context">Context of the build operation.</param>
public override object PreBuildUp(IBuilderContext context)
{
if (null != context.Existing) return null;
var lifetimePolicy = GetLifetimePolicy(context, out _);
if (null == lifetimePolicy) return null;
if (lifetimePolicy is IRequiresRecovery recovery)
{
context.RecoveryStack.Add(recovery);
}
var existing = lifetimePolicy.GetValue(context.Lifetime);
if (existing != null)
{
context.Existing = existing;
context.BuildComplete = true;
}
return lifetimePolicy;
}
/// <summary>
/// Called during the chain of responsibility for a build operation. The
/// PostBuildUp method is called when the chain has finished the PreBuildUp
/// phase and executes in reverse order from the PreBuildUp calls.
/// </summary>
/// <param name="context">Context of the build operation.</param>
/// <param name="lifetimePolicy"></param>
public override void PostBuildUp(IBuilderContext context, object lifetimePolicy = null)
{
(lifetimePolicy as ILifetimePolicy)?.SetValue(context.Existing, context.Lifetime);
}
#endregion
#region Implementation
private ILifetimePolicy GetLifetimePolicy(IBuilderContext context, out IPolicyList source)
{
var policy = context.Policies.Get(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name, typeof(ILifetimePolicy), out source);
if (policy == null && context.OriginalBuildKey.Type.GetTypeInfo().IsGenericType)
{
policy = context.Policies.Get(context.BuildKey.Type.GetGenericTypeDefinition(), context.BuildKey.Name, typeof(ILifetimePolicy), out source);
if (!(policy is ILifetimeFactoryPolicy factoryPolicy)) return null;
lock (_genericLifetimeManagerLock)
{
// check whether the policy for closed-generic has been added since first checked
var newLifetime = (ILifetimePolicy)source.Get(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name, typeof(ILifetimePolicy), out _);
if (null == newLifetime)
{
newLifetime = factoryPolicy.CreateLifetimePolicy();
source.Set(context.OriginalBuildKey.Type, context.OriginalBuildKey.Name, typeof(ILifetimePolicy), newLifetime);
if (newLifetime is IDisposable)
{
context.Lifetime.Add(newLifetime);
}
}
return newLifetime;
}
}
return (ILifetimePolicy)policy;
}
#endregion
}
}

Просмотреть файл

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\package.props" /> <Import Project="..\package.props" />

Просмотреть файл

@ -0,0 +1,176 @@
using System;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.Events;
using Unity.Extension;
using Unity.Lifetime;
using Unity.Policy;
using Unity.Registration;
using Unity.Storage;
using Unity.Strategy;
namespace Unity
{
public partial class UnityContainer
{
/// <summary>
/// Abstraction layer between container and extensions
/// </summary>
/// <remarks>
/// Implemented as a nested class to gain access to
/// container that would otherwise be inaccessible.
/// </remarks>
private class ContainerContext : ExtensionContext,
IContainerContext,
IPolicyList
{
#region Fields
private readonly UnityContainer _container;
#endregion
#region Constructors
public ContainerContext(UnityContainer container)
{
_container = container ?? throw new ArgumentNullException(nameof(container));
Policies = this;
}
#endregion
#region ExtensionContext
public override IUnityContainer Container => _container;
public override IStagedStrategyChain<IBuilderStrategy, UnityBuildStage> Strategies => _container._strategies;
public override IStagedStrategyChain<IBuilderStrategy, BuilderStage> BuildPlanStrategies => _container._buildPlanStrategies;
public override IPolicyList Policies { get; }
public override ILifetimeContainer Lifetime => _container._lifetimeContainer;
public override event EventHandler<RegisterEventArgs> Registering
{
add => _container.Registering += value;
remove => _container.Registering -= value;
}
public override event EventHandler<RegisterInstanceEventArgs> RegisteringInstance
{
add => _container.RegisteringInstance += value;
remove => _container.RegisteringInstance -= value;
}
public override event EventHandler<ChildContainerCreatedEventArgs> ChildContainerCreated
{
add => _container.ChildContainerCreated += value;
remove => _container.ChildContainerCreated -= value;
}
#endregion
#region IContainerContext
public IContainerContext RegistrationContext(InternalRegistration registration)
{
return new RegistrationContext(_container, registration);
}
#endregion
#region IPolicyList
public virtual void ClearAll()
{
_container._registrations =
new HashRegistry<Type, IRegistry<string, IPolicySet>>(ContainerInitialCapacity);
}
public virtual IBuilderPolicy Get(Type type, string name, Type policyInterface, out IPolicyList list)
{
for (var registry = _container; null != registry; registry = registry._parent)
{
IPolicySet data;
if (null == (data = registry[type, name])) continue;
list = registry._context;
return data.Get(policyInterface);
}
list = null;
return null;
}
public virtual void Set(Type type, string name, Type policyInterface, IBuilderPolicy policy)
{
for (var registry = _container; null != registry; registry = registry._parent)
{
IPolicySet data;
if (null == (data = registry[type, name])) continue;
data.Set(policyInterface, policy);
return;
}
_container[type, name, policyInterface] = policy;
}
public virtual void Clear(Type type, string name, Type policyInterface)
{
throw new NotImplementedException();
}
#endregion
}
private class RegistrationContext : ContainerContext
{
private readonly InternalRegistration _registration;
internal RegistrationContext(UnityContainer container, InternalRegistration registration)
: base(container)
{
_registration = registration;
}
#region IPolicyList
public override IBuilderPolicy Get(Type type, string name, Type policyInterface, out IPolicyList list)
{
if (_registration.Type != type || _registration.Name != name)
return base.Get(type, name, policyInterface, out list);
list = this;
return _registration.Get(policyInterface);
}
public override void Set(Type type, string name, Type policyInterface, IBuilderPolicy policy)
{
if (_registration.Type != type || _registration.Name != name)
base.Set(type, name, policyInterface, policy);
_registration.Set(policyInterface, policy);
}
public override void Clear(Type type, string name, Type policyInterface)
{
if (_registration.Type != type || _registration.Name != name)
base.Clear(type, name, policyInterface);
_registration.Clear(policyInterface);
}
#endregion
}
}
}

Просмотреть файл

@ -7,16 +7,20 @@ using Unity.Builder;
using Unity.Builder.Strategy; using Unity.Builder.Strategy;
using Unity.Container; using Unity.Container;
using Unity.Container.Lifetime; using Unity.Container.Lifetime;
using Unity.Container.Registration;
using Unity.Events; using Unity.Events;
using Unity.Extension; using Unity.Extension;
using Unity.Lifetime; using Unity.Lifetime;
using Unity.ObjectBuilder.BuildPlan;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod; using Unity.ObjectBuilder.BuildPlan.DynamicMethod;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod.Creation;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod.Method;
using Unity.ObjectBuilder.BuildPlan.DynamicMethod.Property;
using Unity.ObjectBuilder.BuildPlan.Selection; using Unity.ObjectBuilder.BuildPlan.Selection;
using Unity.ObjectBuilder.Policies; using Unity.ObjectBuilder.Policies;
using Unity.ObjectBuilder.Strategies;
using Unity.Policy; using Unity.Policy;
using Unity.Policy.BuildPlanCreator;
using Unity.Registration;
using Unity.Storage;
using Unity.Strategies;
using Unity.Strategy; using Unity.Strategy;
namespace Unity namespace Unity
@ -25,21 +29,27 @@ namespace Unity
{ {
#region Fields #region Fields
private LifetimeContainer _lifetimeContainer; // Container specific
private readonly PolicyList _policies;
private readonly UnityContainer _parent; private readonly UnityContainer _parent;
private readonly NamedTypesRegistry _registeredNames; private readonly LifetimeContainer _lifetimeContainer;
private readonly List<UnityContainerExtension> _extensions; private readonly List<UnityContainerExtension> _extensions;
private readonly StagedStrategyChain<UnityBuildStage> _strategies;
private readonly StagedStrategyChain<BuilderStage> _buildPlanStrategies; // Policies
private readonly IPolicySet _defaultPolicies;
private readonly ContainerContext _context; private readonly ContainerContext _context;
// Strategies
private readonly StagedStrategyChain<IBuilderStrategy, UnityBuildStage> _strategies;
private readonly StagedStrategyChain<IBuilderStrategy, BuilderStage> _buildPlanStrategies;
// Events
private event EventHandler<RegisterEventArgs> Registering; private event EventHandler<RegisterEventArgs> Registering;
private event EventHandler<RegisterInstanceEventArgs> RegisteringInstance; private event EventHandler<RegisterInstanceEventArgs> RegisteringInstance;
private event EventHandler<ChildContainerCreatedEventArgs> ChildContainerCreated; private event EventHandler<ChildContainerCreatedEventArgs> ChildContainerCreated;
// Caches // Caches
private IRegisterTypeStrategy[] _registerTypeStrategies; private IRegisterTypeStrategy[] _registerTypeStrategies;
private IStrategyChain _strategyChain;
#endregion #endregion
@ -53,82 +63,74 @@ namespace Unity
/// will apply its own settings first, and then check the parent for additional ones.</param> /// will apply its own settings first, and then check the parent for additional ones.</param>
private UnityContainer(UnityContainer parent) private UnityContainer(UnityContainer parent)
{ {
_extensions = new List<UnityContainerExtension>(); // Parent
_parent = parent; _parent = parent;
_parent?._lifetimeContainer.Add(this); _parent?._lifetimeContainer.Add(this);
_context = new ContainerContext(this);
_strategies = new StagedStrategyChain<UnityBuildStage>(_parent?._strategies);
_buildPlanStrategies = new StagedStrategyChain<BuilderStage>(_parent?._buildPlanStrategies);
_registeredNames = new NamedTypesRegistry(_parent?._registeredNames);
_lifetimeContainer = new LifetimeContainer { _strategies, _buildPlanStrategies };
_policies = new PolicyList(_parent?._policies);
_policies.Set<IRegisteredNamesPolicy>(new RegisteredNamesPolicy(_registeredNames), null);
if (null == _parent) InitializeStrategies(); // Strategies
_strategies = new StagedStrategyChain<IBuilderStrategy, UnityBuildStage>(_parent?._strategies);
_buildPlanStrategies = new StagedStrategyChain<IBuilderStrategy, BuilderStage>(_parent?._buildPlanStrategies);
// Lifetime
_lifetimeContainer = new LifetimeContainer(this) { _strategies, _buildPlanStrategies };
// Default Policies
if (null == _parent) InitializeRootContainer();
_defaultPolicies = parent?._defaultPolicies ?? GetDefaultPolicies();
this[null, null] = _defaultPolicies;
// Context and policies
_extensions = new List<UnityContainerExtension>();
_context = new ContainerContext(this);
// Caches // Caches
OnStrategiesChanged(this, null); OnStrategiesChanged(this, null);
_strategies.Invalidated += OnStrategiesChanged; _strategies.Invalidated += OnStrategiesChanged;
RegisterInstance(typeof(IUnityContainer), null, this, new ContainerLifetimeManager());
} }
#endregion #endregion
#region Default Strategies #region Defaults
protected void InitializeStrategies() protected void InitializeRootContainer()
{ {
// Main strategy chain // Main strategy chain
_strategies.AddNew<BuildKeyMappingStrategy>(UnityBuildStage.TypeMapping); _strategies.Add(new BuildKeyMappingStrategy(), UnityBuildStage.TypeMapping);
_strategies.AddNew<LifetimeStrategy>(UnityBuildStage.Lifetime); _strategies.Add(new LifetimeStrategy(), UnityBuildStage.Lifetime);
_strategies.Add(new BuildPlanStrategy(), UnityBuildStage.Creation);
_strategies.AddNew<ArrayResolutionStrategy>(UnityBuildStage.Creation);
_strategies.AddNew<BuildPlanStrategy>(UnityBuildStage.Creation);
// Build plan strategy chain // Build plan strategy chain
_buildPlanStrategies.AddNew<DynamicMethodConstructorStrategy>(BuilderStage.Creation); _buildPlanStrategies.Add(new DynamicMethodConstructorStrategy(), BuilderStage.Creation);
_buildPlanStrategies.AddNew<DynamicMethodPropertySetterStrategy>(BuilderStage.Initialization); _buildPlanStrategies.Add(new DynamicMethodPropertySetterStrategy(), BuilderStage.Initialization);
_buildPlanStrategies.AddNew<DynamicMethodCallStrategy>(BuilderStage.Initialization); _buildPlanStrategies.Add(new DynamicMethodCallStrategy(), BuilderStage.Initialization);
// Policies - mostly used by the build plan strategies // Special Cases
_policies.SetDefault<IConstructorSelectorPolicy>(new DefaultUnityConstructorSelectorPolicy()); this[null, null] = _defaultPolicies;
_policies.SetDefault<IPropertySelectorPolicy>(new DefaultUnityPropertySelectorPolicy()); this[typeof(Func<>), string.Empty, typeof(ILifetimePolicy)] = new PerResolveLifetimeManager();
_policies.SetDefault<IMethodSelectorPolicy>(new DefaultUnityMethodSelectorPolicy()); this[typeof(Func<>), string.Empty, typeof(IBuildPlanPolicy)] = new DeferredResolveCreatorPolicy();
_policies.SetDefault<IBuildPlanCreatorPolicy>(new DynamicMethodBuildPlanCreatorPolicy(_buildPlanStrategies)); this[typeof(Lazy<>), string.Empty, typeof(IBuildPlanCreatorPolicy)] = new GenericLazyBuildPlanCreatorPolicy();
_policies.Set<IBuildPlanPolicy>(new DeferredResolveBuildPlanPolicy(), typeof(Func<>)); this[typeof(Array), string.Empty, typeof(IBuildPlanCreatorPolicy)] =
_policies.Set<ILifetimePolicy>(new PerResolveLifetimeManager(), typeof(Func<>)); new DelegateBasedBuildPlanCreatorPolicy(typeof(UnityContainer).GetTypeInfo().GetDeclaredMethod(nameof(ResolveArray)),
_policies.Set<IBuildPlanCreatorPolicy>(new LazyDynamicMethodBuildPlanCreatorPolicy(), typeof(Lazy<>)); context => context.OriginalBuildKey.Type.GetElementType());
_policies.Set<IBuildPlanCreatorPolicy>(new EnumerableDynamicMethodBuildPlanCreatorPolicy(), typeof(IEnumerable<>)); this[typeof(IEnumerable<>), string.Empty, typeof(IBuildPlanCreatorPolicy)] =
new DelegateBasedBuildPlanCreatorPolicy(typeof(UnityContainer).GetTypeInfo().GetDeclaredMethod(nameof(ResolveEnumerable)),
context => context.BuildKey.Type.GetTypeInfo().GenericTypeArguments.First());
// Register this instance
RegisterInstance(typeof(IUnityContainer), null, this, new ContainerLifetimeManager());
} }
private void SetLifetimeManager(Type lifetimeType, string name, LifetimeManager lifetimeManager) private IPolicySet GetDefaultPolicies()
{ {
if (lifetimeManager.InUse) var defaults = new InternalRegistration(null, null);
{
throw new InvalidOperationException(Constants.LifetimeManagerInUse);
}
if (lifetimeType.GetTypeInfo().IsGenericTypeDefinition) defaults.Set(typeof(IConstructorSelectorPolicy), new DefaultUnityConstructorSelectorPolicy());
{ defaults.Set(typeof(IPropertySelectorPolicy), new DefaultUnityPropertySelectorPolicy());
LifetimeManagerFactory factory = defaults.Set(typeof(IMethodSelectorPolicy), new DefaultUnityMethodSelectorPolicy());
new LifetimeManagerFactory(new ContainerContext(this), lifetimeManager.GetType()); defaults.Set(typeof(IBuildPlanCreatorPolicy), new DynamicMethodBuildPlanCreatorPolicy(_buildPlanStrategies));
_policies.Set<ILifetimeFactoryPolicy>(factory,
new NamedTypeBuildKey(lifetimeType, name)); return defaults;
}
else
{
lifetimeManager.InUse = true;
_policies.Set<ILifetimePolicy>(lifetimeManager,
new NamedTypeBuildKey(lifetimeType, name));
if (lifetimeManager is IDisposable)
{
_lifetimeContainer.Add(lifetimeManager);
}
}
} }
#endregion #endregion
@ -136,28 +138,12 @@ namespace Unity
#region Implementation #region Implementation
private UnityContainer GetRootContainer()
{
UnityContainer container;
for (container = this; container._parent != null; container = container._parent) ;
return container;
}
private void OnStrategiesChanged(object sender, EventArgs e) private void OnStrategiesChanged(object sender, EventArgs e)
{ {
_registerTypeStrategies = _strategies.OfType<IRegisterTypeStrategy>().ToArray(); _registerTypeStrategies = _strategies.OfType<IRegisterTypeStrategy>().ToArray();
_strategyChain = new StrategyChain(_strategies);
} }
/// <summary>
/// Verifies that an argument instance is assignable from the provided type (meaning
/// interfaces are implemented, or classes exist in the base class hierarchy, or instance can be
/// assigned through a runtime wrapper, as is the case for COM Objects).
/// </summary>
/// <param name="assignmentTargetType">The argument type that will be assigned to.</param>
/// <param name="assignmentInstance">The instance that will be assigned.</param>
/// <param name="argumentName">Argument name.</param>
private static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName) private static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName)
{ {
if (!(assignmentTargetType ?? throw new ArgumentNullException(nameof(assignmentTargetType))) if (!(assignmentTargetType ?? throw new ArgumentNullException(nameof(assignmentTargetType)))
@ -187,90 +173,18 @@ namespace Unity
return assignmentInstanceType; return assignmentInstanceType;
} }
#endregion private static IPolicySet CreateRegistration(Type type, string name)
#region Nested Types
/// <summary>
/// Implementation of the ExtensionContext that is actually used
/// by the UnityContainer implementation.
/// </summary>
/// <remarks>
/// This is a nested class so that it can access state in the
/// container that would otherwise be inaccessible.
/// </remarks>
private class ContainerContext : ExtensionContext, IContainerContext
{ {
private readonly UnityContainer _container; return new InternalRegistration(type, name);
public ContainerContext(UnityContainer container)
{
_container = container ?? throw new ArgumentNullException(nameof(container));
} }
public override IUnityContainer Container => _container; private UnityContainer GetRootContainer()
public override IStagedStrategyChain<IBuilderStrategy, UnityBuildStage> Strategies => _container._strategies;
public override IStagedStrategyChain<IBuilderStrategy, BuilderStage> BuildPlanStrategies => _container._buildPlanStrategies;
public override IPolicyList Policies => _container._policies;
public override ILifetimeContainer Lifetime => _container._lifetimeContainer;
public override event EventHandler<RegisterEventArgs> Registering
{ {
add => _container.Registering += value; UnityContainer container;
remove => _container.Registering -= value;
}
/// <summary> for (container = this; container._parent != null; container = container._parent) ;
/// This event is raised when the <see cref="Unity.UnityContainer.RegisterInstance(Type,string,object,LifetimeManager)"/> method,
/// or one of its overloads, is called.
/// </summary>
public override event EventHandler<RegisterInstanceEventArgs> RegisteringInstance
{
add => _container.RegisteringInstance += value;
remove => _container.RegisteringInstance -= value;
}
public override event EventHandler<ChildContainerCreatedEventArgs> ChildContainerCreated return container;
{
add => _container.ChildContainerCreated += value;
remove => _container.ChildContainerCreated -= value;
}
}
// Works like the ExternallyControlledLifetimeManager, but uses regular instead of weak references
private class ContainerLifetimeManager : LifetimeManager, IBuildPlanPolicy
{
private object _value;
public override object GetValue(ILifetimeContainer container = null)
{
return _value;
}
public override void SetValue(object newValue, ILifetimeContainer container = null)
{
_value = newValue;
}
public override void RemoveValue(ILifetimeContainer container = null)
{
}
public void BuildUp(IBuilderContext context)
{
context.Existing = _value;
}
protected override LifetimeManager OnCreateLifetimeManager()
{
return new ContainerLifetimeManager();
}
} }
#endregion #endregion

Просмотреть файл

@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Unity.Events;
using Unity.Extension;
using Unity.Policy;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer : IUnityContainer
{
#region Public Constructor
/// <summary>
/// Create a default <see cref="UnityContainer"/>.
/// </summary>
public UnityContainer()
: this(null)
{
}
#endregion
#region Extension Management
/// <summary>
/// Add an extension object to the container.
/// </summary>
/// <param name="extension"><see cref="UnityContainerExtension"/> to add.</param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer AddExtension(UnityContainerExtension extension)
{
_extensions.Add(extension ?? throw new ArgumentNullException(nameof(extension)));
extension.InitializeExtension(_context);
return this;
}
/// <summary>
/// GetOrDefault access to a configuration interface exposed by an extension.
/// </summary>
/// <remarks>Extensions can expose configuration interfaces as well as adding
/// strategies and policies to the container. This method walks the list of
/// added extensions and returns the first one that implements the requested type.
/// </remarks>
/// <param name="configurationInterface"><see cref="Type"/> of configuration interface required.</param>
/// <returns>The requested extension's configuration interface, or null if not found.</returns>
public object Configure(Type configurationInterface)
{
return _extensions.FirstOrDefault(ex => configurationInterface.GetTypeInfo()
.IsAssignableFrom(ex.GetType().GetTypeInfo()));
}
/// <summary>
/// Remove all installed extensions typeFrom this container.
/// </summary>
/// <remarks>
/// <para>
/// This method removes all extensions typeFrom the container, including the default ones
/// that implement the out-of-the-box behavior. After this method, if you want to use
/// the container again you will need to either read the default extensions or replace
/// them with your own.
/// </para>
/// <para>
/// The registered instances and singletons that have already been set up in this container
/// do not get removed.
/// </para>
/// </remarks>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer RemoveAllExtensions()
{
var toRemove = new List<UnityContainerExtension>(_extensions);
toRemove.Reverse();
foreach (UnityContainerExtension extension in toRemove)
{
extension.Remove();
(extension as IDisposable)?.Dispose();
}
_extensions.Clear();
// Reset our policies, strategies, and registered names to reset to "zero"
_strategies.Clear();
((IPolicyList)_context).ClearAll();
if (null == _parent)
InitializeRootContainer();
return this;
}
#endregion
#region Child container management
/// <summary>
/// Create a child container.
/// </summary>
/// <remarks>
/// A child container shares the parent's configuration, but can be configured with different
/// settings or lifetime.</remarks>
/// <returns>The new child container.</returns>
public IUnityContainer CreateChildContainer()
{
var child = new UnityContainer(this);
ChildContainerCreated?.Invoke(this, new ChildContainerCreatedEventArgs(child._context));
return child;
}
/// <summary>
/// The parent of this container.
/// </summary>
/// <value>The parent container, or null if this container doesn'type have one.</value>
public IUnityContainer Parent => _parent;
#endregion
#region IDisposable Implementation
/// <summary>
/// Dispose this container instance.
/// </summary>
/// <remarks>
/// Disposing the container also disposes any child containers,
/// and disposes any instances whose lifetimes are managed
/// by the container.
/// </remarks>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose this container instance.
/// </summary>
/// <remarks>
/// This class doesn'type have a finalizer, so <paramref name="disposing"/> will always be true.</remarks>
/// <param name="disposing">True if being called typeFrom the IDisposable.Dispose
/// method, false if being called typeFrom a finalizer.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_parent?._lifetimeContainer?.Remove(this);
_lifetimeContainer?.Dispose();
foreach (IDisposable disposable in _extensions.OfType<IDisposable>().ToArray())
disposable.Dispose();
_extensions.Clear();
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(1);
}
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,492 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Events;
using Unity.Lifetime;
using Unity.Policy;
using Unity.Registration;
using Unity.Storage;
namespace Unity
{
public partial class UnityContainer
{
#region Constants
private const int ContainerInitialCapacity = 37;
private const int ListToHashCutoverPoint = 8;
#endregion
#region Fields
private readonly object _syncRoot = new object();
private HashRegistry<Type, IRegistry<string, IPolicySet>> _registrations =
new HashRegistry<Type, IRegistry<string, IPolicySet>>(ContainerInitialCapacity);
#endregion
#region Type Registration
/// <summary>
/// RegisterType a type mapping with the container, where the created instances will use
/// the given <see cref="LifetimeManager"/>.
/// </summary>
/// <param name="typeFrom"><see cref="Type"/> that will be requested.</param>
/// <param name="typeTo"><see cref="Type"/> that will actually be returned.</param>
/// <param name="name">Name to use for registration, null if a default registration.</param>
/// <param name="lifetimeManager">The <see cref="LifetimeManager"/> that controls the lifetime
/// of the returned instance.</param>
/// <param name="injectionMembers">Injection configuration objects.</param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer RegisterType(Type typeFrom, Type typeTo, string name, LifetimeManager lifetimeManager, InjectionMember[] injectionMembers)
{
// Validate imput
if (string.Empty == name) name = null;
if (null == typeTo) throw new ArgumentNullException(nameof(typeTo));
if (null == lifetimeManager) lifetimeManager = TransientLifetimeManager.Instance;
if (typeFrom != null && !typeFrom.GetTypeInfo().IsGenericType && !typeTo.GetTypeInfo().IsGenericType &&
!typeFrom.GetTypeInfo().IsAssignableFrom(typeTo.GetTypeInfo()))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Constants.TypesAreNotAssignable, typeFrom, typeTo), nameof(typeFrom));
}
// Create registration and add to appropriate storage
var container = (lifetimeManager is ISingletonLifetimePolicy) ? GetRootContainer() : this;
var registration = new TypeRegistration(typeFrom, typeTo, name, lifetimeManager);
// Add or replace existing
if (container.SetOrUpdate(registration) is IDisposable disposable)
{
container._lifetimeContainer.Remove(disposable);
disposable.Dispose();
}
// If Disposable add to container's lifetime
if (registration.LifetimeManager is IDisposable manager)
container._lifetimeContainer.Add(manager);
// Add Injection Members
var context = container._context.RegistrationContext(registration);
if (null != injectionMembers && injectionMembers.Length > 0)
{
foreach (var member in injectionMembers)
{
member.AddPolicies(registration.RegisteredType, registration.MappedToType,
registration.Name, context.Policies);
}
}
// Register policies for each strategy
var strategies = container._registerTypeStrategies;
foreach (var strategy in strategies)
strategy.RegisterType(context, registration.RegisteredType, registration.MappedToType,
registration.Name, registration.LifetimeManager, injectionMembers);
// Raise event
container.Registering?.Invoke(this, new RegisterEventArgs(registration.RegisteredType,
registration.MappedToType,
registration.Name,
registration.LifetimeManager));
return this;
}
#endregion
#region Instance Registration
/// <summary>
/// Register an instance with the container.
/// </summary>
/// <remarks> <para>
/// Instance registration is much like setting a type as a singleton, except that instead
/// of the container creating the instance the first time it is requested, the user
/// creates the instance ahead of type and adds that instance to the container.
/// </para></remarks>
/// <param name="registrationType">Type of instance to register (may be an implemented interface instead of the full type).</param>
/// <param name="instance">Object to be returned.</param>
/// <param name="registrationName">Name for registration.</param>
/// <param name="lifetimeManager">
/// <para>If null or <see cref="ContainerControlledLifetimeManager"/>, the container will take over the lifetime of the instance,
/// calling Dispose on it (if it's <see cref="IDisposable"/>) when the container is Disposed.</para>
/// <para>
/// If <see cref="ExternallyControlledLifetimeManager"/>, container will not maintain a strong reference to <paramref name="instance"/>.
/// User is responsible for disposing instance, and for keeping the instance typeFrom being garbage collected.</para></param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer RegisterInstance(Type registrationType, string registrationName, object instance, LifetimeManager lifetimeManager)
{
// Validate imput
if (string.Empty == registrationName) registrationName = null;
if (null == instance) throw new ArgumentNullException(nameof(instance));
// TODO: Move to strategy
var lifetime = lifetimeManager ?? new ContainerControlledLifetimeManager();
if (lifetime.InUse) throw new InvalidOperationException(Constants.LifetimeManagerInUse);
lifetime.SetValue(instance, _lifetimeContainer);
// Create registration and add to appropriate storage
var registration = new InstanceRegistration(registrationType, registrationName, instance, lifetime);
var container = (lifetimeManager is ISingletonLifetimePolicy) ? GetRootContainer() : this;
// Add or replace existing
if (container.SetOrUpdate(registration) is IDisposable disposable)
{
container._lifetimeContainer.Remove(disposable);
disposable.Dispose();
}
if (registration.LifetimeManager is IDisposable manager)
container._lifetimeContainer.Add(manager);
// Raise event
container.RegisteringInstance?.Invoke(this, new RegisterInstanceEventArgs(registration.RegisteredType, instance,
registration.Name, registration.LifetimeManager));
return this;
}
#endregion
#region Check Registration
public bool IsRegistered(Type type, string name)
{
for (var registry = this; null != registry; registry = registry._parent)
{
if (null == registry[type, name]) continue;
return true;
}
return false;
}
#endregion
private IRegistry<string, IPolicySet> this[Type type]
{
get
{
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != type)
{
continue;
}
return _registrations.Entries[i].Value;
}
return null;
}
}
private IPolicySet this[Type type, string name]
{
get
{
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != type)
{
continue;
}
return _registrations.Entries[i].Value?[name];
}
return null;
}
set
{
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
var collisions = 0;
lock (_syncRoot)
{
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != type)
{
collisions++;
continue;
}
var existing = _registrations.Entries[i].Value;
if (existing.RequireToGrow)
{
existing = existing is HashRegistry<string, IPolicySet> registry
? new HashRegistry<string, IPolicySet>(registry)
: new HashRegistry<string, IPolicySet>(LinkedRegistry.ListToHashCutoverPoint * 2,
(LinkedRegistry)existing);
_registrations.Entries[i].Value = existing;
}
existing[name] = value;
return;
}
if (_registrations.RequireToGrow || ListToHashCutoverPoint < collisions)
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(_registrations);
targetBucket = hashCode % _registrations.Buckets.Length;
}
_registrations.Entries[_registrations.Count].HashCode = hashCode;
_registrations.Entries[_registrations.Count].Next = _registrations.Buckets[targetBucket];
_registrations.Entries[_registrations.Count].Key = type;
_registrations.Entries[_registrations.Count].Value = new LinkedRegistry(name, value);
_registrations.Buckets[targetBucket] = _registrations.Count;
_registrations.Count++;
}
}
}
private IBuilderPolicy this[Type type, string name, Type interfaceType]
{
get
{
var collisions = 0;
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
IPolicySet registration = null;
lock (_syncRoot)
{
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != type)
{
collisions++;
continue;
}
var existing = _registrations.Entries[i].Value;
if (existing.RequireToGrow)
{
existing = existing is HashRegistry<string, IPolicySet> registry
? new HashRegistry<string, IPolicySet>(registry)
: new HashRegistry<string, IPolicySet>(LinkedRegistry.ListToHashCutoverPoint * 2,
(LinkedRegistry)existing);
_registrations.Entries[i].Value = existing;
}
registration = existing.GetOrAdd(name, () => CreateRegistration(type, name));
break;
}
if (null == registration)
{
if (_registrations.RequireToGrow || ListToHashCutoverPoint < collisions)
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(_registrations);
targetBucket = hashCode % _registrations.Buckets.Length;
}
registration = CreateRegistration(type, name);
_registrations.Entries[_registrations.Count].HashCode = hashCode;
_registrations.Entries[_registrations.Count].Next = _registrations.Buckets[targetBucket];
_registrations.Entries[_registrations.Count].Key = type;
_registrations.Entries[_registrations.Count].Value = new LinkedRegistry(name, registration);
_registrations.Buckets[targetBucket] = _registrations.Count;
_registrations.Count++;
}
}
return registration.Get(interfaceType);
}
set
{
var collisions = 0;
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
lock (_syncRoot)
{
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != type)
{
collisions++;
continue;
}
var existing = _registrations.Entries[i].Value;
if (existing.RequireToGrow)
{
existing = existing is HashRegistry<string, IPolicySet> registry
? new HashRegistry<string, IPolicySet>(registry)
: new HashRegistry<string, IPolicySet>(LinkedRegistry.ListToHashCutoverPoint * 2,
(LinkedRegistry)existing);
_registrations.Entries[i].Value = existing;
}
existing.GetOrAdd(name, () => CreateRegistration(type, name)).Set(interfaceType, value);
return;
}
if (_registrations.RequireToGrow || ListToHashCutoverPoint < collisions)
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(_registrations);
targetBucket = hashCode % _registrations.Buckets.Length;
}
var registration = CreateRegistration(type, name);
registration.Set(interfaceType, value);
_registrations.Entries[_registrations.Count].HashCode = hashCode;
_registrations.Entries[_registrations.Count].Next = _registrations.Buckets[targetBucket];
_registrations.Entries[_registrations.Count].Key = type;
_registrations.Entries[_registrations.Count].Value = new LinkedRegistry(name, registration);
_registrations.Buckets[targetBucket] = _registrations.Count;
_registrations.Count++;
}
}
}
#region Special Accessors
private IPolicySet SetOrUpdate(INamedType registration)
{
var collisions = 0;
var hashCode = (registration.Type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
lock (_syncRoot)
{
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != registration.Type)
{
collisions++;
continue;
}
var existing = _registrations.Entries[i].Value;
if (existing.RequireToGrow)
{
existing = existing is HashRegistry<string, IPolicySet> registry
? new HashRegistry<string, IPolicySet>(registry)
: new HashRegistry<string, IPolicySet>(LinkedRegistry.ListToHashCutoverPoint * 2, (LinkedRegistry)existing);
_registrations.Entries[i].Value = existing;
}
return existing.SetOrReplace(registration.Name, (IPolicySet)registration);
}
if (_registrations.RequireToGrow || ListToHashCutoverPoint < collisions)
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(_registrations);
targetBucket = hashCode % _registrations.Buckets.Length;
}
_registrations.Entries[_registrations.Count].HashCode = hashCode;
_registrations.Entries[_registrations.Count].Next = _registrations.Buckets[targetBucket];
_registrations.Entries[_registrations.Count].Key = registration.Type;
_registrations.Entries[_registrations.Count].Value = new LinkedRegistry(registration.Name, (IPolicySet)registration);
_registrations.Buckets[targetBucket] = _registrations.Count;
_registrations.Count++;
return null;
}
}
#endregion
#region Registrations Collection
/// <summary>
/// GetOrDefault a sequence of <see cref="IContainerRegistration"/> that describe the current state
/// of the container.
/// </summary>
public IEnumerable<IContainerRegistration> Registrations
{
get
{
return GetRegisteredTypes(this).SelectMany(type => GetRegisteredType(this, type));
}
}
private ISet<Type> GetRegisteredTypes(UnityContainer container)
{
var set = null == container._parent ? new HashSet<Type>()
: GetRegisteredTypes(container._parent);
foreach (var type in container._registrations.Keys.Where(t => null != t))
set.Add(type);
return set;
}
private IEnumerable<IContainerRegistration> GetRegisteredType(UnityContainer container, Type type)
{
ReverseHashSet set;
if (null != container._parent)
set = (ReverseHashSet)GetRegisteredType(container._parent, type);
else
set = new ReverseHashSet();
foreach (var registration in container[type]?.Values.OfType<IContainerRegistration>()
?? Enumerable.Empty<IContainerRegistration>())
{
set.Add(registration);
}
return set;
}
private IEnumerable<string> GetRegisteredNames(UnityContainer container, Type type)
{
ISet<string> set;
if (null != container._parent)
set = (ISet<string>)GetRegisteredNames(container._parent, type);
else
set = new HashSet<string>();
foreach (var registration in container[type]?.Values.OfType<IContainerRegistration>()
?? Enumerable.Empty<IContainerRegistration>())
{
set.Add(registration.Name);
}
var generic = type.GetTypeInfo().IsGenericType ? type.GetGenericTypeDefinition() : type;
if (generic != type)
{
foreach (var registration in container[generic]?.Values.OfType<IContainerRegistration>()
?? Enumerable.Empty<IContainerRegistration>())
{
set.Add(registration.Name);
}
}
return set;
}
#endregion
}
}

Просмотреть файл

@ -0,0 +1,251 @@
using System;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Exceptions;
using Unity.Policy;
using Unity.Resolution;
using Unity.Storage;
namespace Unity
{
/// <inheritdoc />
/// <summary>
/// A simple, extensible dependency injection container.
/// </summary>
public partial class UnityContainer
{
#region Getting objects
/// <summary>
/// GetOrDefault an instance of the requested type with the given name typeFrom the container.
/// </summary>
/// <param name="type"><see cref="Type"/> of object to get typeFrom the container.</param>
/// <param name="name">Name of the object to retrieve.</param>
/// <param name="resolverOverrides">Any overrides for the resolve call.</param>
/// <returns>The retrieved object.</returns>
public object Resolve(Type type, string name, params ResolverOverride[] resolverOverrides)
{
return BuildUp(type, null, name, resolverOverrides);
}
#endregion
#region BuildUp existing object
/// <summary>
/// Run an existing object through the container and perform injection on it.
/// </summary>
/// <remarks>
/// <para>
/// This method is useful when you don'type control the construction of an
/// instance (ASP.NET pages or objects created via XAML, for instance)
/// but you still want properties and other injection performed.
/// </para></remarks>
/// <param name="typeToBuild"><see cref="Type"/> of object to perform injection on.</param>
/// <param name="existing">Instance to build up.</param>
/// <param name="nameToBuild">name to use when looking up the typemappings and other configurations.</param>
/// <param name="resolverOverrides">Any overrides for the buildup.</param>
/// <returns>The resulting object. By default, this will be <paramref name="existing"/>, but
/// container extensions may add things like automatic proxy creation which would
/// cause this to return a different object (but still type compatible with <paramref name="typeToBuild"/>).</returns>
public object BuildUp(Type typeToBuild, object existing, string nameToBuild, params ResolverOverride[] resolverOverrides)
{
// Verify arguments
var name = string.IsNullOrEmpty(nameToBuild) ? null : nameToBuild;
var type = typeToBuild ?? throw new ArgumentNullException(nameof(typeToBuild));
if (null != existing) InstanceIsAssignable(type, existing, nameof(existing));
IBuilderContext context = null;
try
{
var registration = Registration(type, name, true);
var policies = new PolicyListWrapper(registration, _context);
var transient = new PolicyList(policies);
context = new BuilderContext(this, _lifetimeContainer,
_strategyChain,
policies,
transient,
registration,
existing, resolverOverrides);
if (type.GetTypeInfo().IsGenericTypeDefinition)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Constants.CannotResolveOpenGenericType,
type.FullName), nameof(typeToBuild));
}
context.Strategies.BuildUp(context);
return context.Existing;
}
catch (Exception ex)
{
throw new ResolutionFailedException(type, name, ex, context);
}
}
#endregion
private class PolicyListWrapper : IPolicyList
{
private readonly INamedType _store;
private readonly IPolicyList _policies;
public PolicyListWrapper(INamedType store, IPolicyList policies)
{
_store = store;
_policies = policies;
}
public void Clear(Type type, string name, Type policyInterface)
{
}
public void ClearAll()
{
}
public IBuilderPolicy Get(Type type, string name, Type policyInterface, out IPolicyList list)
{
list = null;
if (type != _store.Type || name != _store.Name)
return _policies.Get(type, name, policyInterface, out list);
var result = ((IPolicySet)_store).Get(policyInterface);
if (null != result) list = this;
return result;
}
public void Set(Type type, string name, Type policyInterface, IBuilderPolicy policy)
{
if (type != _store.Type || name != _store.Name)
_policies.Set(type, name, policyInterface, policy);
((IPolicySet)_store).Set(policyInterface, policy);
}
}
#region Resolving Enumerables
private static void ResolveArray<T>(IBuilderContext context)
{
if (null != context.Existing) return;
var container = (UnityContainer)context.Container;
context.Existing = container.GetRegisteredNames(container, typeof(T))
.Where(registration => null != registration)
.Select(registration => context.NewBuildUp(typeof(T), registration))
.Cast<T>()
.ToArray();
context.BuildComplete = true;
context.SetPerBuildSingleton();
}
private static void ResolveEnumerable<T>(IBuilderContext context)
{
if (null != context.Existing) return;
var container = (UnityContainer)context.Container;
context.Existing = container.GetRegisteredNames(container, typeof(T))
.Select(registration => context.NewBuildUp(typeof(T), registration))
.Cast<T>()
.ToArray();
context.BuildComplete = true;
context.SetPerBuildSingleton();
}
#endregion
#region Implementation
/// <summary>
/// Retrieves registration for requested named type
/// </summary>
/// <param name="type">Registration type</param>
/// <param name="name">Registration name</param>
/// <param name="create">Instruncts container if it should create registration if not found</param>
/// <returns>Registration for requested named type or null if named type is not registered and
/// <see cref="create"/> is false</returns>
public INamedType Registration(Type type, string name, bool create = false)
{
for (var container = this; null != container; container = container._parent)
{
IPolicySet data;
if (null == (data = container[type, name])) continue;
return (INamedType)data;
}
if (!create) return null;
var collisions = 0;
var hashCode = (type?.GetHashCode() ?? 0) & 0x7FFFFFFF;
var targetBucket = hashCode % _registrations.Buckets.Length;
lock (_syncRoot)
{
for (var i = _registrations.Buckets[targetBucket]; i >= 0; i = _registrations.Entries[i].Next)
{
if (_registrations.Entries[i].HashCode != hashCode ||
_registrations.Entries[i].Key != type)
{
collisions++;
continue;
}
var existing = _registrations.Entries[i].Value;
if (existing.RequireToGrow)
{
existing = existing is HashRegistry<string, IPolicySet> registry
? new HashRegistry<string, IPolicySet>(registry)
: new HashRegistry<string, IPolicySet>(LinkedRegistry.ListToHashCutoverPoint * 2,
(LinkedRegistry)existing);
_registrations.Entries[i].Value = existing;
}
return (INamedType)existing.GetOrAdd(name, () => CreateRegistration(type, name));
}
if (_registrations.RequireToGrow || ListToHashCutoverPoint < collisions)
{
_registrations = new HashRegistry<Type, IRegistry<string, IPolicySet>>(_registrations);
targetBucket = hashCode % _registrations.Buckets.Length;
}
var registration = CreateRegistration(type, name);
_registrations.Entries[_registrations.Count].HashCode = hashCode;
_registrations.Entries[_registrations.Count].Next = _registrations.Buckets[targetBucket];
_registrations.Entries[_registrations.Count].Key = type;
_registrations.Entries[_registrations.Count].Value = new LinkedRegistry(name, registration);
_registrations.Buckets[targetBucket] = _registrations.Count;
_registrations.Count++;
return (INamedType)registration;
}
}
#endregion
}
}

Просмотреть файл

@ -1,420 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using Unity.Builder;
using Unity.Container.Registration;
using Unity.Events;
using Unity.Exceptions;
using Unity.Extension;
using Unity.Injection;
using Unity.Lifetime;
using Unity.ObjectBuilder;
using Unity.Policy;
using Unity.Registration;
using Unity.Resolution;
using Unity.Strategy;
namespace Unity
{
/// <inheritdoc />
/// <summary>
/// A simple, extensible dependency injection container.
/// </summary>
public partial class UnityContainer : IUnityContainer
{
#region Public Constructor
/// <summary>
/// Create a default <see cref="UnityContainer"/>.
/// </summary>
public UnityContainer()
: this(null)
{
}
#endregion
#region Type Registration
/// <summary>
/// RegisterType a type mapping with the container, where the created instances will use
/// the given <see cref="LifetimeManager"/>.
/// </summary>
/// <param name="typeFrom"><see cref="Type"/> that will be requested.</param>
/// <param name="typeTo"><see cref="Type"/> that will actually be returned.</param>
/// <param name="name">Name to use for registration, null if a default registration.</param>
/// <param name="lifetimeManager">The <see cref="LifetimeManager"/> that controls the lifetime
/// of the returned instance.</param>
/// <param name="injectionMembers">Injection configuration objects.</param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on
/// (this in C#, Me in Visual Basic).</returns>
public IUnityContainer RegisterType(Type typeFrom, Type typeTo, string name,
LifetimeManager lifetimeManager, InjectionMember[] injectionMembers)
{
// Validate input
if (string.Empty == name) name = null;
if (null == typeTo) throw new ArgumentNullException(nameof(typeTo));
if (typeFrom != null && !typeFrom.GetTypeInfo().IsGenericType && !typeTo.GetTypeInfo().IsGenericType &&
!typeFrom.GetTypeInfo().IsAssignableFrom(typeTo.GetTypeInfo()))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Constants.TypesAreNotAssignable,
typeFrom, typeTo), nameof(typeFrom));
}
// Register Type
var buildType = typeFrom ?? typeTo;
var container = (lifetimeManager is ISingletonLifetimePolicy) ? GetRootContainer() : this;
// Clear build plan
container._policies.Set(buildType, name, typeof(IBuildPlanPolicy), new OverriddenBuildPlanMarkerPolicy());
// Register Type/Name
container._registeredNames.RegisterType(buildType, name);
// Add Injection Members to the list
if (null != injectionMembers && injectionMembers.Length > 0)
{
foreach (var member in injectionMembers)
{
if (member is IInjectionFactory && null != typeFrom && typeFrom != typeTo)
throw new InvalidOperationException(Constants.CannotInjectFactory);
member.AddPolicies(buildType, typeTo, name, container._policies);
}
}
// Register policies for each strategy
var strategies = container._registerTypeStrategies;
foreach (var strategy in strategies)
strategy.RegisterType(_context, typeFrom, typeTo, name, lifetimeManager, injectionMembers);
// Raise event
container.Registering?.Invoke(this, new RegisterEventArgs(typeFrom, typeTo, name, lifetimeManager));
return this;
}
#endregion
#region Instance Registration
/// <summary>
/// RegisterType an instance with the container.
/// </summary>
/// <remarks>
/// <para>
/// Instance registration is much like setting a type as a singleton, except that instead
/// of the container creating the instance the first time it is requested, the user
/// creates the instance ahead of type and adds that instance to the container.
/// </para>
/// </remarks>
/// <param name="toType">Type of instance to register (may be an implemented interface instead of the full type).</param>
/// <param name="instance">Object to returned.</param>
/// <param name="name">Name for registration.</param>
/// <param name="manager">
/// <para>If true, the container will take over the lifetime of the instance,
/// calling Dispose on it (if it's <see cref="IDisposable"/>) when the container is Disposed.</para>
/// <para>
/// If false, container will not maintain a strong reference to <paramref name="instance"/>. User is responsible
/// for disposing instance, and for keeping the instance typeFrom being garbage collected.</para></param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer RegisterInstance(Type toType, string name, object instance, LifetimeManager manager)
{
if (null == instance) throw new ArgumentNullException(nameof(instance));
if (null != toType) InstanceIsAssignable(toType, instance, nameof(instance));
var type = toType ?? instance.GetType();
var lifetime = manager ?? new ContainerControlledLifetimeManager();
var container = (manager is ISingletonLifetimePolicy) ? GetRootContainer() : this;
container._registeredNames.RegisterType(type, name);
lifetime.SetValue(instance, _lifetimeContainer);
container.SetLifetimeManager(type, name, lifetime);
if (lifetime is IBuildPlanPolicy buildPlanPolicy)
container._policies.Set(type, name, typeof(IBuildPlanPolicy), buildPlanPolicy);
else
container._policies.Set(type, name, typeof(IBuildPlanPolicy), new OverriddenBuildPlanMarkerPolicy());
container.RegisteringInstance?.Invoke(this, new RegisterInstanceEventArgs(type, instance,
name, lifetime));
return this;
}
#endregion
#region Getting objects
/// <summary>
/// GetOrDefault an instance of the requested type with the given name typeFrom the container.
/// </summary>
/// <param name="type"><see cref="Type"/> of object to get typeFrom the container.</param>
/// <param name="name">Name of the object to retrieve.</param>
/// <param name="resolverOverrides">Any overrides for the resolve call.</param>
/// <returns>The retrieved object.</returns>
public object Resolve(Type type, string name, params ResolverOverride[] resolverOverrides)
{
return BuildUp(type, null, name, resolverOverrides);
}
#endregion
#region BuildUp existing object
/// <summary>
/// Run an existing object through the container and perform injection on it.
/// </summary>
/// <remarks>
/// <para>
/// This method is useful when you don'type control the construction of an
/// instance (ASP.NET pages or objects created via XAML, for instance)
/// but you still want properties and other injection performed.
/// </para></remarks>
/// <param name="typeToBuild"><see cref="Type"/> of object to perform injection on.</param>
/// <param name="existing">Instance to build up.</param>
/// <param name="name">name to use when looking up the typemappings and other configurations.</param>
/// <param name="resolverOverrides">Any overrides for the buildup.</param>
/// <returns>The resulting object. By default, this will be <paramref name="existing"/>, but
/// container extensions may add things like automatic proxy creation which would
/// cause this to return a different object (but still type compatible with <paramref name="typeToBuild"/>).</returns>
public object BuildUp(Type typeToBuild, object existing, string name, params ResolverOverride[] resolverOverrides)
{
var type = typeToBuild ?? throw new ArgumentNullException(nameof(typeToBuild));
if (null != existing) InstanceIsAssignable(type, existing, nameof(existing));
IBuilderContext context = null;
try
{
context = new BuilderContext(this, _strategies.MakeStrategyChain(),
_lifetimeContainer,
_policies,
new NamedTypeBuildKey(type, name),
existing);
context.AddResolverOverrides(resolverOverrides);
if (type.GetTypeInfo().IsGenericTypeDefinition)
{
throw new ArgumentException(
String.Format(CultureInfo.CurrentCulture,
Constants.CannotResolveOpenGenericType,
type.FullName), nameof(type));
}
return context.Strategies.ExecuteBuildUp(context);
}
catch (Exception ex)
{
throw new ResolutionFailedException(type, name, ex, context);
}
}
#endregion
#region Extension Management
/// <summary>
/// Add an extension object to the container.
/// </summary>
/// <param name="extension"><see cref="UnityContainerExtension"/> to add.</param>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer AddExtension(UnityContainerExtension extension)
{
_extensions.Add(extension ?? throw new ArgumentNullException(nameof(extension)));
extension.InitializeExtension(new ContainerContext(this));
return this;
}
/// <summary>
/// GetOrDefault access to a configuration interface exposed by an extension.
/// </summary>
/// <remarks>Extensions can expose configuration interfaces as well as adding
/// strategies and policies to the container. This method walks the list of
/// added extensions and returns the first one that implements the requested type.
/// </remarks>
/// <param name="configurationInterface"><see cref="Type"/> of configuration interface required.</param>
/// <returns>The requested extension's configuration interface, or null if not found.</returns>
public object Configure(Type configurationInterface)
{
return _extensions.FirstOrDefault(ex => configurationInterface.GetTypeInfo()
.IsAssignableFrom(ex.GetType().GetTypeInfo()));
}
/// <summary>
/// Remove all installed extensions typeFrom this container.
/// </summary>
/// <remarks>
/// <para>
/// This method removes all extensions typeFrom the container, including the default ones
/// that implement the out-of-the-box behavior. After this method, if you want to use
/// the container again you will need to either read the default extensions or replace
/// them with your own.
/// </para>
/// <para>
/// The registered instances and singletons that have already been set up in this container
/// do not get removed.
/// </para>
/// </remarks>
/// <returns>The <see cref="UnityContainer"/> object that this method was called on (this in C#, Me in Visual Basic).</returns>
public IUnityContainer RemoveAllExtensions()
{
var toRemove = new List<UnityContainerExtension>(_extensions);
toRemove.Reverse();
foreach (UnityContainerExtension extension in toRemove)
{
extension.Remove();
(extension as IDisposable)?.Dispose();
}
_extensions.Clear();
// Reset our policies, strategies, and registered names to reset to "zero"
_strategies.Clear();
_policies.ClearAll();
_registeredNames.Clear();
if (null == _parent)
InitializeStrategies();
return this;
}
#endregion
#region Child container management
/// <summary>
/// Create a child container.
/// </summary>
/// <remarks>
/// A child container shares the parent's configuration, but can be configured with different
/// settings or lifetime.</remarks>
/// <returns>The new child container.</returns>
public IUnityContainer CreateChildContainer()
{
var child = new UnityContainer(this);
ChildContainerCreated?.Invoke(this, new ChildContainerCreatedEventArgs(child._context));
return child;
}
/// <summary>
/// The parent of this container.
/// </summary>
/// <value>The parent container, or null if this container doesn'type have one.</value>
public IUnityContainer Parent => _parent;
#endregion
#region IDisposable Implementation
/// <summary>
/// Dispose this container instance.
/// </summary>
/// <remarks>
/// Disposing the container also disposes any child containers,
/// and disposes any instances whose lifetimes are managed
/// by the container.
/// </remarks>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Dispose this container instance.
/// </summary>
/// <remarks>
/// This class doesn'type have a finalizer, so <paramref name="disposing"/> will always be true.</remarks>
/// <param name="disposing">True if being called typeFrom the IDisposable.Dispose
/// method, false if being called typeFrom a finalizer.</param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_lifetimeContainer != null)
{
_lifetimeContainer.Dispose();
_lifetimeContainer = null;
if (_parent != null && _parent._lifetimeContainer != null)
{
_parent._lifetimeContainer.Remove(this);
}
}
foreach (IDisposable disposable in Enumerable.OfType<IDisposable>(_extensions))
disposable.Dispose();
_extensions.Clear();
}
}
#endregion
/// <summary>
/// Returns information about existing registration
/// </summary>
/// <param name="type">Type to check</param>
/// <param name="name">Name of the registration</param>
/// <returns>True if registratin exists</returns>
public bool IsRegistered(Type type, string name)
{
return null != _policies.Get(type, name, typeof(IBuildPlanPolicy), out _);
}
/// <summary>
/// GetOrDefault a sequence of <see cref="ContainerRegistration"/> that describe the current state
/// of the container.
/// </summary>
public IEnumerable<IContainerRegistration> Registrations
{
get
{
var allRegisteredNames = new Dictionary<Type, List<string>>();
FillTypeRegistrationDictionary(allRegisteredNames);
return
from type in allRegisteredNames.Keys
from name in allRegisteredNames[type]
select new ContainerRegistration(type, name, _policies);
}
}
private void FillTypeRegistrationDictionary(IDictionary<Type, List<string>> typeRegistrations)
{
if (_parent != null)
{
_parent.FillTypeRegistrationDictionary(typeRegistrations);
}
foreach (Type t in _registeredNames.RegisteredTypes)
{
if (!typeRegistrations.ContainsKey(t))
{
typeRegistrations[t] = new List<string>();
}
typeRegistrations[t] =
(typeRegistrations[t].Concat(_registeredNames.GetKeys(t))).Distinct().ToList();
}
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -17,7 +17,6 @@ namespace Unity
public const string CannotInjectMethodWithRefParams = "The method {0}.{1}({2}) has at least one ref parameter.Methods with ref parameters cannot be injected."; public const string CannotInjectMethodWithRefParams = "The method {0}.{1}({2}) has at least one ref parameter.Methods with ref parameters cannot be injected.";
public const string CannotInjectOpenGenericMethod = "The method {1} on type {0} is marked for injection, but it is an open generic method. Injection cannot be performed."; public const string CannotInjectOpenGenericMethod = "The method {1} on type {0} is marked for injection, but it is an open generic method. Injection cannot be performed.";
public const string CannotInjectStaticMethod = "The method {0}.{1}({2}) is static. Static methods cannot be injected."; public const string CannotInjectStaticMethod = "The method {0}.{1}({2}) is static. Static methods cannot be injected.";
public const string CannotInjectFactory = "Injection factory can not be used in combination with type mapping (RegisterType<To, From>() or RegisterType<To>(new [Delegate]InjectionFactory()) )";
public const string CannotResolveOpenGenericType = "The type {0} is an open generic type. An open generic type cannot be resolved."; public const string CannotResolveOpenGenericType = "The type {0} is an open generic type. An open generic type cannot be resolved.";
public const string ConstructorArgumentResolveOperation = "Resolving parameter '{0}' of constructor {1}"; public const string ConstructorArgumentResolveOperation = "Resolving parameter '{0}' of constructor {1}";
public const string ConstructorParameterResolutionFailed = "The parameter {0} could not be resolved when attempting to call constructor {1}."; public const string ConstructorParameterResolutionFailed = "The parameter {0} could not be resolved when attempting to call constructor {1}.";
@ -32,6 +31,7 @@ namespace Unity
public const string MissingDependency = "Could not resolve dependency for build key {0}."; public const string MissingDependency = "Could not resolve dependency for build key {0}.";
public const string MultipleInjectionConstructors = "The type {0} has multiple constructors marked with the InjectionConstructor attribute. Unable to disambiguate."; public const string MultipleInjectionConstructors = "The type {0} has multiple constructors marked with the InjectionConstructor attribute. Unable to disambiguate.";
public const string MustHaveOpenGenericType = "The supplied type {0} must be an open generic type."; public const string MustHaveOpenGenericType = "The supplied type {0} must be an open generic type.";
public const string MustHaveOpenArrayType = "The supplied type {0} must be an array type.";
public const string MustHaveSameNumberOfGenericArguments = "The supplied type {0} does not have the same number of generic arguments as the target type {1}."; public const string MustHaveSameNumberOfGenericArguments = "The supplied type {0} does not have the same number of generic arguments as the target type {1}.";
public const string NoConstructorFound = "The type {0} does not have an accessible constructor."; public const string NoConstructorFound = "The type {0} does not have an accessible constructor.";
public const string NoMatchingGenericArgument = "The type {0} does not have a generic argument named '{1}'"; public const string NoMatchingGenericArgument = "The type {0} does not have a generic argument named '{1}'";

Просмотреть файл

@ -0,0 +1,78 @@
using System;
namespace Unity.Utility
{
internal static class HashHelpers
{
// Table of prime numbers to use as hash table sizes.
public static readonly int[] Primes = {
1, 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369};
internal const Int32 HashPrime = 101;
public static bool IsPrime(int candidate)
{
if ((candidate & 1) != 0)
{
int limit = (int)Math.Sqrt(candidate);
for (int divisor = 3; divisor <= limit; divisor += 2)
{
if ((candidate % divisor) == 0)
return false;
}
return true;
}
return (candidate == 2);
}
public static int GetPrime(int min)
{
if (min < 0)
throw new ArgumentException("Capacity Overflow");
for (int i = 0; i < Primes.Length; i++)
{
int prime = Primes[i];
if (prime >= min) return prime;
}
//outside of our predefined table.
//compute the hard way.
for (int i = (min | 1); i < Int32.MaxValue; i += 2)
{
if (IsPrime(i) && ((i - 1) % HashPrime != 0))
return i;
}
return min;
}
public static int GetMinPrime()
{
return Primes[0];
}
// Returns size of hashtable to grow to.
public static int ExpandPrime(int oldSize)
{
int newSize = 2 * oldSize;
// Allow the hashtables to grow to maximum possible size (~2G elements) before encoutering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
{
return MaxPrimeArrayLength;
}
return GetPrime(newSize);
}
// This is the maximum prime smaller than Array.MaxArrayLength
public const int MaxPrimeArrayLength = 0x7FEFFFFD;
}
}

Просмотреть файл

@ -1,39 +1,11 @@
using System; using System;
using System.Security.Cryptography;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Attributes.Jobs;
using BenchmarkDotNet.Running;
namespace MyBenchmarks namespace Performance
{ {
[ClrJob] class Program
[BenchmarkCategory("Collections")]
public class Md5VsSha256
{ {
private const int N = 10000; static void Main(string[] args)
private readonly byte[] data;
private readonly SHA256 sha256 = SHA256.Create();
private readonly MD5 md5 = MD5.Create();
public Md5VsSha256()
{ {
data = new byte[N];
new Random(42).NextBytes(data);
}
[Benchmark]
public byte[] Sha256() => sha256.ComputeHash(data);
[Benchmark]
public byte[] Md5() => md5.ComputeHash(data);
}
public class Program
{
public static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<Md5VsSha256>();
} }
} }
} }

Просмотреть файл

@ -5,27 +5,14 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net47</TargetFramework> <TargetFramework>net47</TargetFramework>
<UnityAbstractions>..\..\..\Abstractions\src\Unity.Abstractions.csproj</UnityAbstractions>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Remove="BenchmarkDotNet.Artifacts\**" />
<EmbeddedResource Remove="BenchmarkDotNet.Artifacts\**" />
<None Remove="BenchmarkDotNet.Artifacts\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.11" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Unity.Container.csproj" /> <ProjectReference Include="..\..\src\Unity.Container.csproj" />
</ItemGroup> </ItemGroup>
<PropertyGroup>
<UnityAbstractions>..\..\..\Abstractions\src\Unity.Abstractions.csproj</UnityAbstractions>
</PropertyGroup>
<ItemGroup Condition="Exists('$(UnityAbstractions)')"> <ItemGroup Condition="Exists('$(UnityAbstractions)')">
<ProjectReference Include="$(UnityAbstractions)" /> <ProjectReference Include="$(UnityAbstractions)" />
</ItemGroup> </ItemGroup>

Просмотреть файл

@ -0,0 +1,13 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Unity.Specification
{
[TestClass]
public class ResolutionTestFixture : Resolution.SpecificationTests
{
public override IUnityContainer GetContainer()
{
return new UnityContainer();
}
}
}

Просмотреть файл

@ -1,377 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.TestSupport;
using Microsoft.Practices.Unity.Utility;
using Unity.Exceptions;
using Unity.Lifetime;
namespace Unity.Tests.ChildContainer
{
/// <summary>
/// Summary description for UnityChildContainers
/// </summary>
[TestClass]
public class ChildContainerFixture
{
[TestMethod]
public void CreateChildUsingParentsConfiguration()
{
UnityContainer parent = new UnityContainer();
parent.RegisterType<ITemporary, Temporary>();
IUnityContainer child = parent.CreateChildContainer();
ITemporary temp = child.Resolve<ITemporary>();
Assert.IsNotNull(temp);
Assert.IsInstanceOfType(temp, typeof(Temporary));
}
[TestMethod]
public void NamesRegisteredInParentAppearInChild()
{
UnityContainer parent = new UnityContainer();
parent.RegisterType<ITemporary, SpecialTemp>("test");
IUnityContainer child = parent.CreateChildContainer();
ITemporary temp = child.Resolve<ITemporary>("test");
Assert.IsInstanceOfType(temp, typeof(SpecialTemp));
}
[TestMethod]
public void NamesRegisteredInParentAppearInChildGetAll()
{
string[] numbers = { "first", "second", "third" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance(numbers[0], "first")
.RegisterInstance(numbers[1], "second");
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance(numbers[2], "third");
List<string> nums = new List<string>(child.ResolveAll<string>());
CollectionAssert.AreEquivalent(numbers, nums);
}
[TestMethod]
public void ChildConfigurationOverridesParentConfiguration()
{
UnityContainer parent = new UnityContainer();
parent.RegisterType<ITemporary, Temporary>();
IUnityContainer child = parent.CreateChildContainer()
.RegisterType<ITemporary, SpecialTemp>();
ITemporary parentTemp = parent.Resolve<ITemporary>();
ITemporary childTemp = child.Resolve<ITemporary>();
Assert.IsInstanceOfType(parentTemp, typeof(Temporary));
Assert.IsInstanceOfType(childTemp, typeof(SpecialTemp));
}
[TestMethod]
public void DisposingParentDisposesChild()
{
UnityContainer parent = new UnityContainer();
IUnityContainer child = parent.CreateChildContainer();
MyDisposableObject spy = new MyDisposableObject();
child.RegisterInstance(spy);
parent.Dispose();
Assert.IsTrue(spy.WasDisposed);
}
[TestMethod]
public void CanDisposeChildWithoutDisposingParent()
{
MyDisposableObject parentSpy = new MyDisposableObject();
MyDisposableObject childSpy = new MyDisposableObject();
UnityContainer parent = new UnityContainer();
parent.RegisterInstance(parentSpy);
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance(childSpy);
child.Dispose();
Assert.IsFalse(parentSpy.WasDisposed);
Assert.IsTrue(childSpy.WasDisposed);
childSpy.WasDisposed = false;
parent.Dispose();
Assert.IsTrue(parentSpy.WasDisposed);
Assert.IsFalse(childSpy.WasDisposed);
}
[TestMethod]
public void VerifyToList()
{
string[] numbers = { "first", "second", "third" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance(numbers[0], "first")
.RegisterInstance(numbers[1], "second");
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance(numbers[2], "third");
List<string> nums = new List<string>(child.ResolveAll<string>());
CollectionAssert.AreEquivalent(numbers, nums);
}
[TestMethod]
public void ChangesInParentReflectsInChild()
{
string[] numbers = { "first", "second", "third", "fourth" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance(numbers[0], "1")
.RegisterInstance(numbers[1], "2");
IUnityContainer child = parent.CreateChildContainer();
List<string> childnums = new List<string>(child.ResolveAll<string>());
List<string> parentnums = new List<string>(parent.ResolveAll<string>());
CollectionAssert.AreEquivalent(childnums, parentnums);
parent.RegisterInstance(numbers[3], "4"); //Register an instance in Parent but not in child
List<string> childnums2 = new List<string>(child.ResolveAll<string>());
List<string> parentnums2 = new List<string>(parent.ResolveAll<string>());
CollectionAssert.AreEquivalent(childnums2, parentnums2); //Both parent child should have same instances
}
[TestMethod]
public void DuplicateRegInParentAndChild()
{
string[] numbers = { "first", "second", "third", "fourth" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance(numbers[0], "1")
.RegisterInstance(numbers[1], "2");
IUnityContainer child = parent.CreateChildContainer();
List<string> childnums = new List<string>(child.ResolveAll<string>());
List<string> parentnums = new List<string>(parent.ResolveAll<string>());
CollectionAssert.AreEquivalent(childnums, parentnums);
parent.RegisterInstance(numbers[3], "4");
child.RegisterInstance(numbers[3], "4");
List<string> childnums2 = new List<string>(child.ResolveAll<string>());
List<string> parentnums2 = new List<string>(parent.ResolveAll<string>());
CollectionAssert.AreEquivalent(childnums2, parentnums2); //Both parent child should have same instances
}
[TestMethod]
public void VerifyArgumentNullException()
{
string[] numbers = { "first", "second", "third" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance("1", numbers[0])
.RegisterInstance("2", numbers[1]);
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance("3", numbers[2]);
List<string> nums = new List<string>(child.ResolveAll<string>());
AssertHelper.ThrowsException<ArgumentNullException>(() => Guard.ArgumentNotNull(null, String.Empty));
CollectionAssert.AreEquivalent(numbers, nums);
}
[TestMethod]
public void CreateParentChildContainersWithSameName()
{
IUnityContainer parent = new UnityContainer();
parent.RegisterType<ITemporary, Temp>("First");
parent = (UnityContainer)parent.CreateChildContainer();
parent.RegisterType<ITemporary, Temp>("First");
List<ITemporary> count = new List<ITemporary>(parent.ResolveAll<ITemporary>());
Assert.AreEqual(1, count.Count);
}
[TestMethod]
public void MoreChildContainers1()
{
UnityContainer parent = new UnityContainer();
parent.RegisterType<ITemporary, Temp>("First");
parent.RegisterType<ITemporary, Temp>("First");
UnityContainer child1 = (UnityContainer)parent.CreateChildContainer();
child1.RegisterType<ITemporary, Temp>("First");
child1.RegisterType<ITemporary, Temp>("First");
UnityContainer child2 = (UnityContainer)child1.CreateChildContainer();
child2.RegisterType<ITemporary, Temp>("First");
child2.RegisterType<ITemporary, Temp>("First");
UnityContainer child3 = (UnityContainer)child2.CreateChildContainer();
child3.RegisterType<ITemporary, Temp>("First");
child3.RegisterType<ITemporary, Temp>("First");
IUnityContainer child4 = child3.CreateChildContainer();
child4.RegisterType<ITemporary, Temp>("First");
ITemporary first = child4.Resolve<ITemporary>("First");
child4.RegisterType<ITemporary, Temp>("First", new ContainerControlledLifetimeManager());
List<ITemporary> count = new List<ITemporary>(child4.ResolveAll<ITemporary>());
Assert.AreEqual(1, count.Count);
}
[TestMethod]
public void MoreChildContainers2()
{
UnityContainer parent = new UnityContainer();
parent.RegisterType<ITemporary, Temp>("First", new HierarchicalLifetimeManager());
UnityContainer child1 = (UnityContainer)parent.CreateChildContainer();
child1.RegisterType<ITemporary, Temp>("First", new HierarchicalLifetimeManager());
var result = parent.Resolve<ITemporary>("First");
var result1 = child1.Resolve<ITemporary>("First");
Assert.AreNotEqual<int>(result.GetHashCode(), result1.GetHashCode());
UnityContainer child2 = (UnityContainer)child1.CreateChildContainer();
child2.RegisterType<ITemporary, Temp>("First", new HierarchicalLifetimeManager());
var result2 = child2.Resolve<ITemporary>("First");
Assert.AreNotEqual<int>(result.GetHashCode(), result2.GetHashCode());
Assert.AreNotEqual<int>(result1.GetHashCode(), result2.GetHashCode());
List<ITemporary> count = new List<ITemporary>(child2.ResolveAll<ITemporary>());
Assert.AreEqual(1, count.Count);
}
[TestMethod]
public void GetObjectAfterDispose()
{
UnityContainer parent = new UnityContainer();
parent.RegisterType<Temp>("First", new ContainerControlledLifetimeManager());
IUnityContainer child = parent.CreateChildContainer();
child.RegisterType<ITemporary>("First", new ContainerControlledLifetimeManager());
parent.Dispose();
AssertHelper.ThrowsException<ResolutionFailedException>(() => child.Resolve<ITemporary>("First"));
}
[TestMethod]
public void VerifyArgumentNotNullOrEmpty()
{
string[] numbers = { "first", "second", "third" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance("1", numbers[0])
.RegisterInstance("2", numbers[1]);
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance("3", numbers[2]);
List<string> nums = new List<string>(child.ResolveAll<string>());
AssertHelper.ThrowsException<ArgumentException>(() => Guard.ArgumentNotNullOrEmpty(String.Empty, String.Empty));
CollectionAssert.AreEquivalent(numbers, nums);
}
[TestMethod]
public void VerifyArgumentNotNullOrEmpty1()
{
string[] numbers = { "first", "second", "third" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance("1", numbers[0])
.RegisterInstance("2", numbers[1]);
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance("3", numbers[2]);
List<string> nums = new List<string>(child.ResolveAll<string>());
AssertHelper.ThrowsException<ArgumentNullException>(() => Guard.ArgumentNotNullOrEmpty(null, null));
CollectionAssert.AreEquivalent(numbers, nums);
}
[TestMethod]
public void VerifyArgumentNotNullOrEmpty2()
{
string[] numbers = { "first", "second", "third" };
UnityContainer parent = new UnityContainer();
parent.RegisterInstance("1", numbers[0])
.RegisterInstance("2", numbers[1]);
IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance("3", numbers[2]);
List<string> nums = new List<string>(child.ResolveAll<string>());
Guard.ArgumentNotNullOrEmpty("first", "numbers");
CollectionAssert.AreEquivalent(numbers, nums);
}
//bug # 3978 http://unity.codeplex.com/WorkItem/View.aspx?WorkItemId=6053
[TestMethod]
public void ChildParentRegisrationOverlapTest()
{
IUnityContainer container = new UnityContainer();
container.RegisterInstance("str1", "string1");
container.RegisterInstance("str2", "string2");
IUnityContainer child = container.CreateChildContainer();
child.RegisterInstance("str2", "string20");
child.RegisterInstance("str3", "string30");
var childStrList = child.ResolveAll<string>();
var parentStrList = container.ResolveAll<string>();
string childString = String.Empty;
string parentString = String.Empty;
foreach (string str in childStrList) { childString = childString + str; }
foreach (string str1 in parentStrList) { parentString = parentString + str1; }
Assert.AreEqual<string>("string1string20string30", childString);
Assert.AreEqual<string>("string1string2", parentString);
}
public interface ITemporary
{
}
public class Temp : ITemporary
{
}
public class Temporary : ITemporary
{
}
public class SpecialTemp : ITemporary //Second level
{
}
public class MyDisposableObject : IDisposable
{
private bool wasDisposed = false;
public bool WasDisposed
{
get { return wasDisposed; }
set { wasDisposed = value; }
}
public void Dispose()
{
wasDisposed = true;
}
}
}
}

Просмотреть файл

@ -199,24 +199,24 @@ namespace Unity.Tests.ChildContainer
[TestMethod] [TestMethod]
public void ChainOfContainers() public void ChainOfContainers()
{ {
UnityContainer parent = new UnityContainer(); var parent = new UnityContainer();
IUnityContainer child = parent.CreateChildContainer(); var child1 = parent.CreateChildContainer();
IUnityContainer child2 = child.CreateChildContainer(); var child2 = child1.CreateChildContainer();
IUnityContainer child3 = child2.CreateChildContainer(); var child3 = child2.CreateChildContainer();
TestContainer obj1 = new TestContainer(); var obj1 = new TestContainer();
parent.RegisterInstance<TestContainer>("InParent", obj1); parent.RegisterInstance("InParent", obj1);
child.RegisterInstance<TestContainer>("InChild", obj1); child1.RegisterInstance("InChild1", obj1);
child2.RegisterInstance<TestContainer>("InChild2", obj1); child2.RegisterInstance("InChild2", obj1);
child3.RegisterInstance<TestContainer>("InChild3", obj1); child3.RegisterInstance("InChild3", obj1);
object objresolve = child3.Resolve<TestContainer>("InParent"); object objresolve = child3.Resolve<TestContainer>("InParent");
object objresolve1 = parent.Resolve<TestContainer>("InChild3"); object objresolve1 = parent.Resolve<TestContainer>("InChild3");
Assert.AreSame(obj1, objresolve); Assert.AreSame(obj1, objresolve);
child.Dispose(); child1.Dispose();
//parent not getting disposed //parent not getting disposed
Assert.IsTrue(obj1.WasDisposed); Assert.IsTrue(obj1.WasDisposed);

Просмотреть файл

@ -1,149 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity;
using Unity.Attributes;
namespace Unity.Tests
{
[TestClass]
public class ConstructorInjectionFixture
{
[TestMethod]
public void ConstPropInjectionSameClassTwice()
{
IUnityContainer uc = new UnityContainer();
uc.RegisterType<InjectTestClass2_Prop>()
.RegisterType<InjectTestClass_Prop>();
InjectTestClass2_Prop obj_test = uc.Resolve<InjectTestClass2_Prop>();
obj_test.Propertyfirst.NameInjectTestClassProp = "First";
obj_test.Propertysecond.NameInjectTestClassProp = "Second";
Assert.AreEqual("Second", obj_test.Propertysecond.NameInjectTestClassProp);
Assert.AreEqual("First", obj_test.Propertyfirst.NameInjectTestClassProp);
}
[TestMethod]// log Bug
public void TestMethodwithParamaterAsInterface()
{
IUnityContainer uc = new UnityContainer();
uc.RegisterType<InjectionTestInterface, InjectionTestClass2>()
.RegisterType<InjectionTestInterface, InjectionTestClass2>("hi")
.RegisterType<InjectionTestInterface, InjectionTestClass1>()
.RegisterType<InjectionTestInterface, InjectionTestClass1>("hello");
InjectionTestInterface obj3 = uc.Resolve<InjectionTestInterface>("hi");
InjectionTestInterface obj2 = uc.Resolve<InjectionTestInterface>("hello");
}
}
/// <summary>
/// ConstructorInjectionFixture class used for property injection testing.
/// </summary>
public class InjectTestClass_Prop
{
private string nameInjectTestClassProp = "In InjectTestClass1_Prop";
public string NameInjectTestClassProp
{
get { return this.nameInjectTestClassProp; }
set { nameInjectTestClassProp = value; }
}
}
/// <summary>
/// ConstructorInjectionFixture class used for injection.
/// </summary>
public class InjectTestClass2_Prop
{
public string Name = "In InjectTestClass2_Prop";
private InjectTestClass_Prop objinject1;
private InjectTestClass_Prop objinject2;
public InjectTestClass_Prop Propertyfirst
{
get { return objinject1; }
set { objinject1 = value; }
}
public InjectTestClass_Prop Propertysecond
{
get { return objinject2; }
set { objinject2 = value; }
}
//InjectTestClass_Prop objinject1_created, InjectTestClass_Prop objinject2_created
[InjectionConstructor]
public InjectTestClass2_Prop(InjectTestClass_Prop objinject1_created, InjectTestClass_Prop objinject2_created)
{
objinject1 = objinject1_created;
objinject2 = objinject2_created;
objinject1.NameInjectTestClassProp = "First time call";
objinject2.NameInjectTestClassProp = "Second time call";
}
}
#region InjectClass
public interface InjectionTestInterface
{
string Text
{
get;
set;
}
}
public class InjectionTestClass : InjectionTestInterface
{
private string name = "InjectionTestClass";
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public string Text
{
get { return this.name; }
set { this.name = value; }
}
}
public class InjectionTestClass1 : InjectionTestInterface
{
private string name = "InjectionTestClass1";
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public string Text
{
get { return this.name; }
set { this.name = value; }
}
}
public class InjectionTestClass2 : InjectionTestInterface
{
private string name = "InjectionTestClass2";
private InjectionTestInterface intobj;
public InjectionTestClass2(InjectionTestInterface intobj1)
{
this.intobj = intobj1;
intobj1.Text = "Hello";
}
public string Text
{
get { return this.name; }
set { this.name = value; }
}
}
#endregion InjectClass
}

Просмотреть файл

@ -1,12 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Exceptions; using Unity.Exceptions;
namespace Unity.Tests namespace Unity.Tests.Container
{ {
[TestClass] [TestClass]
public class ContainerBasicFixture public class ContainerBasicFixture

Просмотреть файл

@ -1,12 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System; using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Attributes; using Unity.Attributes;
using Unity.Exceptions; using Unity.Exceptions;
namespace Unity.Tests namespace Unity.Tests.Container
{ {
[TestClass] [TestClass]
public class ContainerBuildUpFixture public class ContainerBuildUpFixture

Просмотреть файл

@ -2,16 +2,14 @@
using System; using System;
using System.Threading; using System.Threading;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity.Tests.TestDoubles; using Microsoft.Practices.Unity.Tests.TestDoubles;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Builder; using Unity.Builder;
using Unity.Builder.Strategy; using Unity.Builder.Strategy;
using Unity.Exceptions; using Unity.Exceptions;
using Unity.Lifetime; using Unity.Lifetime;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Container
{ {
// Test for a race condition in the ContainerControlledLifetime // Test for a race condition in the ContainerControlledLifetime
// class. // class.
@ -21,9 +19,9 @@ namespace Microsoft.Practices.Unity.Tests
[TestMethod] [TestMethod]
public void ContainerControlledLifetimeReturnsSameInstanceFromMultipleThreads() public void ContainerControlledLifetimeReturnsSameInstanceFromMultipleThreads()
{ {
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer();
.AddExtension(new SpyExtension(new DelayStrategy(), UnityBuildStage.Lifetime)) container.AddExtension(new SpyExtension(new DelayStrategy(), UnityBuildStage.Lifetime));
.RegisterType<object>(new ContainerControlledLifetimeManager()); container.RegisterType<object>(new ContainerControlledLifetimeManager());
object result1 = null; object result1 = null;
object result2 = null; object result2 = null;
@ -38,6 +36,9 @@ namespace Microsoft.Practices.Unity.Tests
result2 = container.Resolve<object>(); result2 = container.Resolve<object>();
}); });
thread1.Name = "1";
thread2.Name = "2";
thread1.Start(); thread1.Start();
thread2.Start(); thread2.Start();
@ -119,6 +120,7 @@ namespace Microsoft.Practices.Unity.Tests
this.shouldThrow = false; this.shouldThrow = false;
throw new Exception("Throwing from buildup chain"); throw new Exception("Throwing from buildup chain");
} }
return null; return null;
} }
} }

Просмотреть файл

@ -1,9 +1,9 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Attributes; using Unity.Attributes;
namespace Unity.Tests namespace Unity.Tests.Container
{ {
[TestClass] [TestClass]
public class ContainerDefaultContentFixture public class ContainerDefaultContentFixture

Просмотреть файл

@ -1,15 +1,12 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Practices.Unity.Tests.TestDoubles; using Microsoft.Practices.Unity.Tests.TestDoubles;
using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Builder; using Unity.Builder;
using Unity.Extension; using Unity.Extension;
using Unity.Tests.TestDoubles;
using IMockConfiguration = Microsoft.Practices.Unity.TestSupport.IMockConfiguration;
using MockContainerExtension = Microsoft.Practices.Unity.TestSupport.MockContainerExtension;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests
{ {
[TestClass] [TestClass]
public class UnityExtensionFixture public class UnityExtensionFixture

Просмотреть файл

@ -4,11 +4,9 @@ using System.Collections.Generic;
using Microsoft.Practices.Unity.Tests.TestObjects; using Microsoft.Practices.Unity.Tests.TestObjects;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Injection; using Unity.Injection;
using Unity.Tests.TestSupport;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests
{ {
/// <summary> /// <summary>
/// Tests for the hierarchical features of the UnityContainer. /// Tests for the hierarchical features of the UnityContainer.
@ -19,11 +17,11 @@ namespace Microsoft.Practices.Unity.Tests
[TestMethod] [TestMethod]
public void ChildBuildsUsingParentsConfiguration() public void ChildBuildsUsingParentsConfiguration()
{ {
UnityContainer parent = new UnityContainer(); var parent = new UnityContainer();
parent.RegisterType<ILogger, MockLogger>(); parent.RegisterType<ILogger, MockLogger>();
IUnityContainer child = parent.CreateChildContainer(); var child = parent.CreateChildContainer();
ILogger logger = child.Resolve<ILogger>(); var logger = child.Resolve<ILogger>();
Assert.IsNotNull(logger); Assert.IsNotNull(logger);
AssertExtensions.IsInstanceOfType(logger, typeof(MockLogger)); AssertExtensions.IsInstanceOfType(logger, typeof(MockLogger));
@ -47,11 +45,11 @@ namespace Microsoft.Practices.Unity.Tests
{ {
string[] databases = { "northwind", "adventureworks", "fabrikam" }; string[] databases = { "northwind", "adventureworks", "fabrikam" };
UnityContainer parent = new UnityContainer(); UnityContainer parent = new UnityContainer();
parent.RegisterInstance<string>("nwnd", databases[0]) parent.RegisterInstance("nwnd", databases[0])
.RegisterInstance<string>("advwks", databases[1]); .RegisterInstance("advwks", databases[1]);
IUnityContainer child = parent.CreateChildContainer() IUnityContainer child = parent.CreateChildContainer()
.RegisterInstance<string>("fbkm", databases[2]); .RegisterInstance("fbkm", databases[2]);
List<string> dbs = new List<string>(child.ResolveAll<string>()); List<string> dbs = new List<string>(child.ResolveAll<string>());
CollectionAssertExtensions.AreEquivalent(databases, dbs); CollectionAssertExtensions.AreEquivalent(databases, dbs);
@ -114,7 +112,7 @@ namespace Microsoft.Practices.Unity.Tests
IUnityContainer child = parent.CreateChildContainer(); IUnityContainer child = parent.CreateChildContainer();
DisposableObject spy = new DisposableObject(); DisposableObject spy = new DisposableObject();
child.RegisterInstance<DisposableObject>(spy); child.RegisterInstance(spy);
parent.Dispose(); parent.Dispose();
Assert.IsTrue(spy.WasDisposed); Assert.IsTrue(spy.WasDisposed);

Просмотреть файл

@ -1,156 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
namespace Microsoft.Practices.Unity.Tests
{
/// <summary>
/// Summary description for ContainerRegistrationsFixture
/// </summary>
[TestClass]
public class ContainerRegistrationsFixture
{
private IUnityContainer container;
[TestInitialize]
public void Setup()
{
container = new UnityContainer();
}
[TestMethod]
public void ContainerListsItselfAsRegistered()
{
Assert.IsTrue(container.IsRegistered(typeof(IUnityContainer)));
}
[TestMethod]
public void ContainerDoesNotListItselfUnderNonDefaultName()
{
Assert.IsFalse(container.IsRegistered(typeof(IUnityContainer), "other"));
}
[TestMethod]
public void ContainerListsItselfAsRegisteredUsingGenericOverload()
{
Assert.IsTrue(container.IsRegistered<IUnityContainer>());
}
[TestMethod]
public void ContainerDoesNotListItselfUnderNonDefaultNameUsingGenericOverload()
{
Assert.IsFalse(container.IsRegistered<IUnityContainer>("other"));
}
[TestMethod]
public void IsRegisteredWorksForRegisteredType()
{
container.RegisterType<ILogger, MockLogger>();
Assert.IsTrue(container.IsRegistered<ILogger>());
}
[TestMethod]
public void ContainerIncludesItselfUnderRegistrations()
{
Assert.IsNotNull(container.Registrations.Where(r => r.RegisteredType == typeof(IUnityContainer)).FirstOrDefault());
}
[TestMethod]
public void NewRegistrationsShowUpInRegistrationsSequence()
{
container.RegisterType<ILogger, MockLogger>()
.RegisterType<ILogger, MockLogger>("second");
var registrations = (from r in container.Registrations
where r.RegisteredType == typeof(ILogger)
select r).ToList();
Assert.AreEqual(2, registrations.Count);
Assert.IsTrue(registrations.Any(r => r.Name == null));
Assert.IsTrue(registrations.Any(r => r.Name == "second"));
}
[TestMethod]
public void TypeMappingShowsUpInRegistrationsCorrectly()
{
container.RegisterType<ILogger, MockLogger>();
var registration =
(from r in container.Registrations where r.RegisteredType == typeof(ILogger) select r).First();
Assert.AreSame(typeof(MockLogger), registration.MappedToType);
}
[TestMethod]
public void NonMappingRegistrationShowsUpInRegistrationsSequence()
{
container.RegisterType<MockLogger>();
var registration = (from r in container.Registrations
where r.RegisteredType == typeof(MockLogger)
select r).First();
Assert.AreSame(registration.RegisteredType, registration.MappedToType);
Assert.IsNull(registration.Name);
}
[TestMethod]
public void RegistrationOfOpenGenericTypeShowsUpInRegistrationsSequence()
{
container.RegisterType(typeof(IDictionary<,>), typeof(Dictionary<,>), "test");
var registration = container.Registrations.First(r => r.RegisteredType == typeof(IDictionary<,>));
Assert.AreSame(typeof(Dictionary<,>), registration.MappedToType);
Assert.AreEqual("test", registration.Name);
}
[TestMethod]
public void RegistrationsInParentContainerAppearInChild()
{
container.RegisterType<ILogger, MockLogger>();
var child = container.CreateChildContainer();
var registration =
(from r in child.Registrations where r.RegisteredType == typeof(ILogger) select r).First();
Assert.AreSame(typeof(MockLogger), registration.MappedToType);
}
[TestMethod]
public void RegistrationsInChildContainerDoNotAppearInParent()
{
var child = container.CreateChildContainer()
.RegisterType<ILogger, MockLogger>("named");
var childRegistration = child.Registrations.Where(r => r.RegisteredType == typeof(ILogger)).First();
var parentRegistration =
container.Registrations.Where(r => r.RegisteredType == typeof(ILogger)).FirstOrDefault();
Assert.IsNull(parentRegistration);
Assert.IsNotNull(childRegistration);
}
[TestMethod]
public void DuplicateRegistrationsInParentAndChildOnlyShowUpOnceInChild()
{
container.RegisterType<ILogger, MockLogger>("one");
var child = container.CreateChildContainer()
.RegisterType<ILogger, SpecialLogger>("one");
var registrations = from r in child.Registrations
where r.RegisteredType == typeof(ILogger)
select r;
Assert.AreEqual(1, registrations.Count());
var childRegistration = registrations.First();
Assert.AreSame(typeof(SpecialLogger), childRegistration.MappedToType);
Assert.AreEqual("one", childRegistration.Name);
}
}
}

Просмотреть файл

@ -356,20 +356,23 @@ namespace Unity.Tests.CollectionSupport
[TestMethod] [TestMethod]
public void Enumerable_DisposingScopeDisposesService() public void Enumerable_DisposingScopeDisposesService()
{ {
EmailService singleton;
OtherEmailService transient3;
using (IUnityContainer provider = new UnityContainer()) using (IUnityContainer provider = new UnityContainer())
{ {
EmailService disposableService;
OtherEmailService transient1;
OtherEmailService transient2;
// Arrange // Arrange
provider.RegisterType<IService, EmailService>("Singleton", new ContainerControlledLifetimeManager()); provider.RegisterType<IService, EmailService>("Singleton", new ContainerControlledLifetimeManager());
provider.RegisterType<IService, EmailService>("Scoped", new HierarchicalLifetimeManager()); provider.RegisterType<IService, EmailService>("Scoped", new HierarchicalLifetimeManager());
provider.RegisterType<IService, OtherEmailService>("Transient", new HierarchicalLifetimeManager()); provider.RegisterType<IService, OtherEmailService>("Transient", new HierarchicalLifetimeManager());
EmailService disposableService;
OtherEmailService transient1;
OtherEmailService transient2;
EmailService singleton;
// Act and Assert // Act and Assert
OtherEmailService transient3 = (OtherEmailService)provider.Resolve<IService>("Transient"); transient3 = (OtherEmailService)provider.Resolve<IService>("Transient");
using (var scope = provider.CreateChildContainer()) using (var scope = provider.CreateChildContainer())
{ {
disposableService = (EmailService)scope.Resolve<IService>("Scoped"); disposableService = (EmailService)scope.Resolve<IService>("Scoped");
@ -387,15 +390,10 @@ namespace Unity.Tests.CollectionSupport
Assert.IsTrue(transient1.Disposed); Assert.IsTrue(transient1.Disposed);
Assert.IsTrue(transient2.Disposed); Assert.IsTrue(transient2.Disposed);
Assert.IsFalse(singleton.Disposed); Assert.IsFalse(singleton.Disposed);
}
var disposableProvider = provider as IDisposable;
if (disposableProvider != null)
{
disposableProvider.Dispose();
Assert.IsTrue(singleton.Disposed);
Assert.IsTrue(transient3.Disposed); Assert.IsTrue(transient3.Disposed);
} Assert.IsTrue(singleton.Disposed);
}
} }
[TestMethod] [TestMethod]

Просмотреть файл

@ -32,7 +32,7 @@ namespace Unity.Tests.Extension
public IMyCustomConfigurator AddPolicy() public IMyCustomConfigurator AddPolicy()
{ {
Context.Policies.Set<IBuildPlanPolicy>(new MyCustomPolicy(), null); Context.Policies.Set(null, null, typeof(IBuildPlanPolicy), new MyCustomPolicy());
this.checkPolicyAdded = true; this.checkPolicyAdded = true;
return this; return this;
} }

Просмотреть файл

@ -4,11 +4,9 @@
using Microsoft.Practices.Unity; using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Tests.TestDoubles; using Microsoft.Practices.Unity.Tests.TestDoubles;
using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Builder; using Unity.Builder;
using Unity.Tests.TestDoubles;
using IMockConfiguration = Microsoft.Practices.Unity.TestSupport.IMockConfiguration;
using MockContainerExtension = Microsoft.Practices.Unity.TestSupport.MockContainerExtension;
namespace Unity.Tests.Extension namespace Unity.Tests.Extension
{ {

Просмотреть файл

@ -17,8 +17,8 @@ namespace Microsoft.Practices.Unity.Tests
[TestMethod] [TestMethod]
public void CanSpecializeGenericTypes() public void CanSpecializeGenericTypes()
{ {
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer();
.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>)); container.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>));
ICommand<User> cmd = container.Resolve<ICommand<User>>(); ICommand<User> cmd = container.Resolve<ICommand<User>>();
AssertExtensions.IsInstanceOfType(cmd, typeof(ConcreteCommand<User>)); AssertExtensions.IsInstanceOfType(cmd, typeof(ConcreteCommand<User>));
} }
@ -34,10 +34,12 @@ namespace Microsoft.Practices.Unity.Tests
[TestMethod] [TestMethod]
public void CanChainGenericTypes() public void CanChainGenericTypes()
{ {
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer();
.RegisterType(typeof(ICommand<>), typeof(LoggingCommand<>), container.RegisterType(typeof(ICommand<>), typeof(LoggingCommand<>), new InjectionConstructor(new ResolvedParameter(typeof(ICommand<>), "concrete")));
new InjectionConstructor(new ResolvedParameter(typeof(ICommand<>), "concrete"))) container.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "concrete");
.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "concrete");
var md = container.Resolve<ICommand<User>>("concrete");
ICommand<User> cmd = container.Resolve<ICommand<User>>(); ICommand<User> cmd = container.Resolve<ICommand<User>>();
LoggingCommand<User> logCmd = (LoggingCommand<User>)cmd; LoggingCommand<User> logCmd = (LoggingCommand<User>)cmd;
@ -50,8 +52,7 @@ namespace Microsoft.Practices.Unity.Tests
public void CanChainGenericTypesViaRegisterTypeMethod() public void CanChainGenericTypesViaRegisterTypeMethod()
{ {
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer()
.RegisterType(typeof(ICommand<>), typeof(LoggingCommand<>), .RegisterType(typeof(ICommand<>), typeof(LoggingCommand<>), new InjectionConstructor(new ResolvedParameter(typeof(ICommand<>), "concrete")))
new InjectionConstructor(new ResolvedParameter(typeof(ICommand<>), "concrete")))
.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "concrete"); .RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "concrete");
ICommand<User> cmd = container.Resolve<ICommand<User>>(); ICommand<User> cmd = container.Resolve<ICommand<User>>();
@ -76,8 +77,7 @@ namespace Microsoft.Practices.Unity.Tests
public void ConfiguredGenericMethodInjectionIsCalled() public void ConfiguredGenericMethodInjectionIsCalled()
{ {
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer()
.RegisterType(typeof(ICommand<>), typeof(LoggingCommand<>), .RegisterType(typeof(ICommand<>), typeof(LoggingCommand<>), new InjectionConstructor(new ResolvedParameter(typeof(ICommand<>), "concrete")),
new InjectionConstructor(new ResolvedParameter(typeof(ICommand<>), "concrete")),
new InjectionMethod("ChainedExecute", new ResolvedParameter(typeof(ICommand<>), "inner"))) new InjectionMethod("ChainedExecute", new ResolvedParameter(typeof(ICommand<>), "inner")))
.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "concrete") .RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "concrete")
.RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "inner"); .RegisterType(typeof(ICommand<>), typeof(ConcreteCommand<>), "inner");
@ -175,9 +175,8 @@ namespace Microsoft.Practices.Unity.Tests
[TestMethod] [TestMethod]
public void ContainerControlledOpenGenericsAreDisposed() public void ContainerControlledOpenGenericsAreDisposed()
{ {
var container = new UnityContainer() var container = new UnityContainer();
.RegisterType(typeof(ICommand<>), typeof(DisposableCommand<>), container.RegisterType(typeof(ICommand<>), typeof(DisposableCommand<>), new ContainerControlledLifetimeManager());
new ContainerControlledLifetimeManager());
var accountCommand = container.Resolve<ICommand<Account>>(); var accountCommand = container.Resolve<ICommand<Account>>();
var userCommand = container.Resolve<ICommand<User>>(); var userCommand = container.Resolve<ICommand<User>>();

Просмотреть файл

@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Injection; using Unity.Injection;
using Unity.Lifetime; using Unity.Lifetime;
@ -26,7 +27,8 @@ namespace Unity.Tests.Generics
public void ResolveConfiguredGenericType() public void ResolveConfiguredGenericType()
{ {
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer()
.RegisterType(typeof(GenericArrayPropertyDependency<>), "testing", new InjectionProperty("Stuff")) .RegisterType(typeof(GenericArrayPropertyDependency<>), "testing",
new InjectionProperty("Stuff"))
.RegisterInstance<string>("first", "first") .RegisterInstance<string>("first", "first")
.RegisterInstance<string>("second", "second"); .RegisterInstance<string>("second", "second");
@ -48,9 +50,10 @@ namespace Unity.Tests.Generics
myDict.Add("One", "two"); myDict.Add("One", "two");
myDict.Add("Two", "three"); myDict.Add("Two", "three");
IUnityContainer container = new UnityContainer() IUnityContainer container = new UnityContainer();
.RegisterInstance(myDict) container.RegisterInstance(myDict);
.RegisterType(typeof(IDictionary<,>), typeof(Dictionary<,>), new ExternallyControlledLifetimeManager()); container.RegisterType(typeof(IDictionary<,>), typeof(Dictionary<,>), new ExternallyControlledLifetimeManager(),
new InjectionConstructor());
IDictionary<string, string> result = container.Resolve<IDictionary<string, string>>(); IDictionary<string, string> result = container.Resolve<IDictionary<string, string>>();
Assert.AreSame(myDict, result); Assert.AreSame(myDict, result);
@ -80,13 +83,13 @@ namespace Unity.Tests.Generics
[TestMethod] [TestMethod]
public void Testmethod_NoLifetimeSpecified() public void Testmethod_NoLifetimeSpecified()
{ {
List<int> myList = new List<int>(); var myList = new List<int>();
IUnityContainer container = new UnityContainer() var container = new UnityContainer()
.RegisterInstance<List<int>>(myList) .RegisterInstance<IList<int>>(myList)
.RegisterType<List<int>>(new InjectionConstructor()); .RegisterType<List<int>>();
List<int> result = container.Resolve<List<int>>(); var result = container.Resolve<IList<int>>();
Assert.AreNotSame(myList, result); Assert.AreSame(myList, result);
} }
/// <summary> /// <summary>
@ -110,13 +113,13 @@ namespace Unity.Tests.Generics
[TestMethod] [TestMethod]
public void Testmethod_ListOfString() public void Testmethod_ListOfString()
{ {
List<string> myList = new List<string>(); var myList = new List<string>();
IUnityContainer container = new UnityContainer() var container = new UnityContainer()
.RegisterInstance<List<string>>(myList) .RegisterInstance<IList<string>>(myList)
.RegisterType<List<string>>(new InjectionConstructor()); .RegisterType<List<string>>();
List<string> result = container.Resolve<List<string>>(); IList<string> result = container.Resolve<IList<string>>();
Assert.AreNotSame(myList, result); Assert.AreSame(myList, result);
} }
/// <summary> /// <summary>
@ -126,12 +129,12 @@ namespace Unity.Tests.Generics
[TestMethod] [TestMethod]
public void Testmethod_ListOfObjectType() public void Testmethod_ListOfObjectType()
{ {
List<Foo> myList = new List<Foo>(); var myList = new List<Foo>();
IUnityContainer container = new UnityContainer() var container = new UnityContainer()
.RegisterInstance<IList<Foo>>(myList) .RegisterInstance(myList)
.RegisterType<IList<Foo>, List<Foo>>(new InjectionConstructor()); .RegisterType<IList<Foo>, List<Foo>>();
IList<Foo> result = container.Resolve<IList<Foo>>(); var result = container.Resolve<IList<Foo>>();
Assert.IsInstanceOfType(result, typeof(List<Foo>)); Assert.IsInstanceOfType(result, typeof(List<Foo>));
} }

Просмотреть файл

@ -6,7 +6,6 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Tests.TestSupport;
namespace Microsoft.Practices.Unity.Tests namespace Microsoft.Practices.Unity.Tests
{ {

Просмотреть файл

@ -1,189 +0,0 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using Microsoft.Practices.Unity.TestSupport;
using Unity;
using Unity.Attributes;
using Unity.Exceptions;
using Unity.Injection;
using Unity.Lifetime;
using Unity.Tests.TestObjects;
using UnityContainer = Unity.UnityContainer;
namespace GitHub
{
[TestClass]
public class Issues
{
[TestMethod]
public void unitycontainer_unity_164()
{
var container = new UnityContainer();
container.RegisterType<ILogger, MockLogger>();
var foo2 = new MockLogger();
container.RegisterType<ILogger>(new InjectionFactory(x => foo2));
var result = container.Resolve<ILogger>();
Assert.AreSame(result, foo2);
}
[TestMethod]
public void unity_156()
{
using (var container = new UnityContainer())
{
var td = new MockLogger();
container.RegisterType<MockLogger>(new ContainerControlledLifetimeManager(), new InjectionFactory(_ => td));
container.RegisterType<ILogger, MockLogger>();
Assert.AreSame(td, container.Resolve<ILogger>());
Assert.AreSame(td, container.Resolve<MockLogger>());
}
using (var container = new UnityContainer())
{
var td = new MockLogger();
container.RegisterType<MockLogger>(new ContainerControlledLifetimeManager(), new InjectionFactory(_ => td));
container.RegisterType<ILogger, MockLogger>();
Assert.AreSame(td, container.Resolve<MockLogger>());
Assert.AreSame(td, container.Resolve<ILogger>());
}
}
[TestMethod]
public void unity_154_5()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<OtherEmailService>(new ContainerControlledLifetimeManager());
container.RegisterType<IService, OtherEmailService>();
container.RegisterType<IOtherService, OtherEmailService>(new InjectionConstructor(container));
Assert.AreNotSame(container.Resolve<IService>(),
container.Resolve<IOtherService>());
}
[TestMethod]
public void unity_154()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<OtherEmailService>(new ContainerControlledLifetimeManager());
container.RegisterType<IService, OtherEmailService>();
container.RegisterType<IOtherService, OtherEmailService>();
Assert.AreSame(container.Resolve<IService>(),
container.Resolve<IOtherService>());
}
[TestMethod]
public void unity_153()
{
IUnityContainer rootContainer = new UnityContainer();
rootContainer.RegisterType<ILogger, MockLogger>(new HierarchicalLifetimeManager());
using (IUnityContainer childContainer = rootContainer.CreateChildContainer())
{
var a = childContainer.Resolve<ILogger>();
var b = childContainer.Resolve<ILogger>();
Assert.AreSame(a, b);
}
}
[TestMethod]
public void Issue_35()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager());
ILogger logger = container.Resolve<ILogger>();
Assert.IsNotNull(logger);
Assert.AreSame(container.Resolve<ILogger>(), logger);
container.RegisterType<MockLogger>(new TransientLifetimeManager());
Assert.AreSame(container.Resolve<ILogger>(), logger);
}
[TestMethod]
public void GitHub_Issue_88() // https://github.com/unitycontainer/unity/issues/88
{
using (var unityContainer = new UnityContainer())
{
unityContainer.RegisterInstance(true);
unityContainer.RegisterInstance("true", true);
unityContainer.RegisterInstance("false", false);
var resolveAll = unityContainer.ResolveAll(typeof(bool));
var arr = resolveAll.Select(o => o.ToString()).ToArray();
}
}
[TestMethod]
public void GitHub_Issue_54() // https://github.com/unitycontainer/unity/issues/54
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType(typeof(ITestClass), typeof(TestClass));
container.RegisterInstance(new TestClass());
var instance = container.Resolve<ITestClass>(); //0
Assert.IsNotNull(instance);
}
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType(typeof(ITestClass), typeof(TestClass));
container.RegisterType<TestClass>(new ContainerControlledLifetimeManager());
try
{
var instance = container.Resolve<ITestClass>(); //2
Assert.IsNull(instance, "Should threw an exception");
}
catch (ResolutionFailedException e)
{
Assert.IsInstanceOfType(e, typeof(ResolutionFailedException));
}
}
}
[TestMethod]
public void GitHub_Issue_35_ConflictTypeMapping()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<ILogger, MockLogger>(new ContainerControlledLifetimeManager());
ILogger logger = container.Resolve<ILogger>();
Assert.IsNotNull(logger);
Assert.AreSame(container.Resolve<ILogger>(), logger);
container.RegisterType<MockLogger>(new TransientLifetimeManager());
Assert.AreSame(container.Resolve<ILogger>(), logger);
}
// Test types
public interface ITestClass
{ }
public class TestClass : ITestClass
{
public TestClass()
{ }
[InjectionConstructor]
public TestClass(TestClass x) //1
{ }
}
}
}

Просмотреть файл

@ -3,10 +3,9 @@
using System; using System;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Injection; using Unity.Injection;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Injection
{ {
[TestClass] [TestClass]
public class InjectedMembersFixture public class InjectedMembersFixture

Просмотреть файл

@ -3,11 +3,9 @@
using System; using System;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Injection; using Unity.Injection;
using Unity.Tests.TestSupport;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Injection
{ {
[TestClass] [TestClass]
public class InjectingArraysFixture public class InjectingArraysFixture

Просмотреть файл

@ -3,10 +3,9 @@
using System; using System;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Injection; using Unity.Injection;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Injection
{ {
[TestClass] [TestClass]
public class InjectionMethodFixture public class InjectionMethodFixture

Просмотреть файл

@ -4,14 +4,14 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Microsoft.Practices.ObjectBuilder2; using Microsoft.Practices.ObjectBuilder2;
using Microsoft.Practices.Unity.Tests;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Injection; using Unity.Injection;
using Unity.Policy; using Unity.Policy;
using Unity.ResolverPolicy; using Unity.ResolverPolicy;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Injection
{ {
// Tests for the DependencyValue class and its derivatives // Tests for the DependencyValue class and its derivatives
[TestClass] [TestClass]

Просмотреть файл

@ -3,11 +3,10 @@
using System; using System;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Attributes; using Unity.Attributes;
using Unity.Injection; using Unity.Injection;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Injection
{ {
[TestClass] [TestClass]
public class MethodInjectionFixture public class MethodInjectionFixture

Просмотреть файл

@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using System; using System;
using Microsoft.Practices.ObjectBuilder2;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity; using Unity;
using Unity.Builder; using Unity.Builder;
@ -209,11 +208,6 @@ namespace Microsoft.Practices.Unity.Tests
throw new NotImplementedException(); throw new NotImplementedException();
} }
public object NewBuildUp(INamedType newBuildKey)
{
return NewBuildupCallback(newBuildKey);
}
public object NewBuildUp(Type type, string name, Action<IBuilderContext> childCustomizationBlock = null) public object NewBuildUp(Type type, string name, Action<IBuilderContext> childCustomizationBlock = null)
{ {
return NewBuildupCallback(new NamedTypeBuildKey(type, name)); return NewBuildupCallback(new NamedTypeBuildKey(type, name));

Просмотреть файл

Просмотреть файл

@ -4,11 +4,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Attributes; using Unity.Attributes;
using Unity.Lifetime; using Unity.Lifetime;
namespace Microsoft.Practices.Unity.Tests namespace Unity.Tests.Lazy
{ {
/// <summary> /// <summary>
/// Summary description for DeferredResolveFixture /// Summary description for DeferredResolveFixture

Просмотреть файл

@ -5,6 +5,8 @@ using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Lifetime; using Unity.Lifetime;
using Unity.Tests.Container;
using Unity.Tests.TestObjects;
namespace Unity.Tests.Lifetime namespace Unity.Tests.Lifetime
@ -292,16 +294,16 @@ namespace Unity.Tests.Lifetime
{ {
IUnityContainer uc = new UnityContainer(); IUnityContainer uc = new UnityContainer();
A aInstance = new A(); var aInstance = new EmailService();
uc.RegisterType<A>(new ContainerControlledLifetimeManager()) uc.RegisterType(null, typeof(EmailService), null, new ContainerControlledLifetimeManager(), null);
.RegisterType<A>("SetA", new ContainerControlledLifetimeManager()) uc.RegisterType<EmailService>("SetA", new ContainerControlledLifetimeManager());
.RegisterInstance<A>(aInstance) uc.RegisterInstance(aInstance);
.RegisterInstance<A>("hello", aInstance) uc.RegisterInstance("hello", aInstance);
.RegisterInstance<A>("hello", aInstance, new ExternallyControlledLifetimeManager()); uc.RegisterInstance("hello", aInstance, new ExternallyControlledLifetimeManager());
A obj = uc.Resolve<A>(); var obj = uc.Resolve<EmailService>();
A obj1 = uc.Resolve<A>("SetA"); var obj1 = uc.Resolve<EmailService>("SetA");
A obj2 = uc.Resolve<A>("hello"); var obj2 = uc.Resolve<EmailService>("hello");
Assert.AreNotSame(obj, obj1); Assert.AreNotSame(obj, obj1);
Assert.AreSame(obj, obj2); Assert.AreSame(obj, obj2);

Просмотреть файл

@ -1,11 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Builder; using Unity.Builder;
using Unity.ObjectBuilder.Policies; using Unity.Policy.Mapping;
namespace Microsoft.Practices.ObjectBuilder2.Tests namespace Unity.Tests.ObjectBuilder
{ {
[TestClass] [TestClass]
public class BuildKeyMappingPolicyTest public class BuildKeyMappingPolicyTest

Просмотреть файл

@ -1,108 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;
using Unity.Builder;
using Unity.Builder.Strategy;
using Unity.ObjectBuilder.Policies;
using Unity.ObjectBuilder.Strategies;
using Unity.Policy;
namespace Microsoft.Practices.ObjectBuilder2.Tests
{
[TestClass]
public class BuildKeyMappingStrategyTest
{
[TestMethod]
public void CanMapGenericsWithIdenticalGenericParameters()
{
MockBuilderContext context = new MockBuilderContext();
context.Policies.Set<IBuildKeyMappingPolicy>(new GenericTypeBuildKeyMappingPolicy(
new NamedTypeBuildKey(typeof(ConcreteType<>))),
new NamedTypeBuildKey(typeof(ITestType<>)));
BuildKeyMappingStrategy strategy = new BuildKeyMappingStrategy();
context.Strategies.Add(strategy);
SpyStrategy spy = new SpyStrategy();
context.Strategies.Add(spy);
context.BuildKey = new NamedTypeBuildKey<ITestType<int>>();
context.Strategies.ExecuteBuildUp(context);
Assert.AreEqual(new NamedTypeBuildKey(typeof(ConcreteType<int>)), spy.BuildKey);
}
[TestMethod]
public void CanMapGenericsWithANonTypeBuildKey()
{
MockBuilderContext context = new MockBuilderContext();
context.Policies.Set<IBuildKeyMappingPolicy>(
new GenericTypeBuildKeyMappingPolicy(new NamedTypeBuildKey(typeof(ConcreteType<>), "two")),
new NamedTypeBuildKey(typeof(ITestType<>), "one"));
BuildKeyMappingStrategy strategy = new BuildKeyMappingStrategy();
context.Strategies.Add(strategy);
SpyStrategy spy = new SpyStrategy();
context.Strategies.Add(spy);
context.BuildKey = new NamedTypeBuildKey(typeof(ITestType<int>), "one");
context.Strategies.ExecuteBuildUp(context);
AssertExtensions.IsInstanceOfType(spy.BuildKey, typeof(NamedTypeBuildKey));
Assert.AreEqual(typeof(ConcreteType<int>), spy.BuildKey.Type);
Assert.AreEqual("two", spy.BuildKey.Name);
}
[TestMethod]
public void CanMapInterfacesToConcreteTypes()
{
MockBuilderContext context = new MockBuilderContext();
context.Policies.Set<IBuildKeyMappingPolicy>(new BuildKeyMappingPolicy(new NamedTypeBuildKey<ConcreteType>()),
new NamedTypeBuildKey<ITestType>());
BuildKeyMappingStrategy strategy = new BuildKeyMappingStrategy();
context.Strategies.Add(strategy);
SpyStrategy spy = new SpyStrategy();
context.Strategies.Add(spy);
context.BuildKey = new NamedTypeBuildKey<ITestType>();
context.Strategies.ExecuteBuildUp(context);
Assert.AreEqual(new NamedTypeBuildKey(typeof(ConcreteType)), spy.BuildKey);
}
[TestMethod]
public void MappingStrategyActuallyReturnsTheBuildKeyThePolicySpecifies()
{
MockBuilderContext context = new MockBuilderContext();
NamedTypeBuildKey fromKey = new NamedTypeBuildKey(typeof(ConcreteType), "id");
NamedTypeBuildKey toKey = new NamedTypeBuildKey(typeof(ITestType), "id");
context.Policies.Set<IBuildKeyMappingPolicy>(new BuildKeyMappingPolicy(toKey), fromKey);
BuildKeyMappingStrategy strategy = new BuildKeyMappingStrategy();
context.Strategies.Add(strategy);
SpyStrategy spy = new SpyStrategy();
context.Strategies.Add(spy);
context.BuildKey = fromKey;
context.Existing = null;
context.Strategies.ExecuteBuildUp(context);
AssertExtensions.IsInstanceOfType(spy.BuildKey, typeof(NamedTypeBuildKey));
Assert.AreEqual(toKey, spy.BuildKey);
}
private class ConcreteType : ITestType { }
private class ConcreteType<T> : ITestType<T> { }
private interface ITestType { }
private interface ITestType<T> { }
private class SpyStrategy : BuilderStrategy
{
public INamedType BuildKey;
public override object PreBuildUp(IBuilderContext context)
{
this.BuildKey = context.BuildKey;
return null;
}
}
}
}

Просмотреть файл

@ -5,6 +5,7 @@ using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity; using Unity;
using Unity.Injection; using Unity.Injection;
using Unity.Tests.TestObjects;
namespace Microsoft.Practices.Unity.Tests namespace Microsoft.Practices.Unity.Tests
{ {

Просмотреть файл

@ -3,10 +3,10 @@
using Microsoft.Practices.Unity.TestSupport; using Microsoft.Practices.Unity.TestSupport;
using Microsoft.VisualStudio.TestTools.UnitTesting; using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity.Builder; using Unity.Builder;
using Unity.ObjectBuilder.Strategies;
using Unity.Policy; using Unity.Policy;
using Unity.Strategies;
namespace Microsoft.Practices.ObjectBuilder2.Tests namespace Unity.Tests.ObjectBuilder
{ {
[TestClass] [TestClass]
public class BuildPlanStrategyFixture public class BuildPlanStrategyFixture
@ -19,7 +19,7 @@ namespace Microsoft.Practices.ObjectBuilder2.Tests
object instance = new object(); object instance = new object();
ReturnInstanceBuildPlan plan = new ReturnInstanceBuildPlan(instance); ReturnInstanceBuildPlan plan = new ReturnInstanceBuildPlan(instance);
context.Policies.Set<IBuildPlanPolicy>(plan, new NamedTypeBuildKey<object>()); context.Policies.Set(typeof(object), null, typeof(IBuildPlanPolicy), plan);
object result = context.ExecuteBuildUp(new NamedTypeBuildKey<object>(), null); object result = context.ExecuteBuildUp(new NamedTypeBuildKey<object>(), null);
@ -33,14 +33,14 @@ namespace Microsoft.Practices.ObjectBuilder2.Tests
MockBuilderContext context = new MockBuilderContext(); MockBuilderContext context = new MockBuilderContext();
context.Strategies.Add(new BuildPlanStrategy()); context.Strategies.Add(new BuildPlanStrategy());
MockBuildPlanCreatorPolicy policy = new MockBuildPlanCreatorPolicy(); MockBuildPlanCreatorPolicy policy = new MockBuildPlanCreatorPolicy();
context.Policies.SetDefault<IBuildPlanCreatorPolicy>(policy); context.Policies.Set(null, null, typeof(IBuildPlanCreatorPolicy),policy);
object result = context.ExecuteBuildUp(new NamedTypeBuildKey<object>(), null); object result = context.ExecuteBuildUp(new NamedTypeBuildKey<object>(), null);
Assert.IsNotNull(result); Assert.IsNotNull(result);
Assert.IsTrue(policy.PolicyWasCreated); Assert.IsTrue(policy.PolicyWasCreated);
IBuildPlanPolicy plan = context.Policies.Get<IBuildPlanPolicy>(new NamedTypeBuildKey(typeof(object))); var plan = context.Policies.GetOrDefault(typeof(IBuildPlanPolicy), new NamedTypeBuildKey(typeof(object)), out _);
Assert.IsNotNull(plan); Assert.IsNotNull(plan);
} }
} }

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше