Skip to content

Commit 5da3ca9

Browse files
author
maximv
committed
adding WithMicrosoftDependencyInjectionRules; fixing things
1 parent efa6d56 commit 5da3ca9

File tree

2 files changed

+62
-34
lines changed

2 files changed

+62
-34
lines changed

src/DryIoc/Container.cs

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5253,18 +5253,25 @@ public DynamicRegistration(Factory factory,
52535253
/// <summary> Defines resolution/registration rules associated with Container instance. They may be different for different containers.</summary>
52545254
public sealed class Rules
52555255
{
5256-
/// Default rules as staring point.
5256+
/// <summary>Default rules as a staring point.</summary>
52575257
public static readonly Rules Default = new Rules();
52585258

5259-
/// Default rules as staring point.
5260-
public static readonly Rules MicrosoftDependencyInjectionRules = new Rules(
5261-
(DEFAULT_SETTINGS | Settings.TrackingDisposableTransients)
5262-
& ~Settings.ThrowOnRegisteringDisposableTransient & ~Settings.VariantGenericTypesInResolvedCollection,
5263-
Rules.SelectLastRegisteredFactory(), Reuse.Transient,
5264-
Made.Of(DryIoc.FactoryMethod.ConstructorWithResolvableArguments),
5265-
IfAlreadyRegistered.AppendNotKeyed,
5266-
DefaultDependencyCountInLambdaToSplitBigObjectGraph, null, null, null, null, null);
5267-
5259+
private static Rules SetMicrosoftDependencyInjectionRules(Rules rules)
5260+
{
5261+
rules._settings |= Settings.TrackingDisposableTransients;
5262+
rules._settings &= ~Settings.ThrowOnRegisteringDisposableTransient;
5263+
rules._settings &= ~Settings.VariantGenericTypesInResolvedCollection;
5264+
rules._factorySelector = SelectLastRegisteredFactory;
5265+
rules._made._factoryMethod = DryIoc.FactoryMethod.ConstructorWithResolvableArguments;
5266+
return rules;
5267+
}
5268+
5269+
/// <summary>The rules implementing the conventions of Microsoft.Extension.DependencyInjection library.</summary>
5270+
public static readonly Rules MicrosoftDependencyInjectionRules = SetMicrosoftDependencyInjectionRules(Default.Clone());
5271+
5272+
/// <summary>Returns the copy of the rules with the applied conventions of Microsoft.Extension.DependencyInjection library.</summary>
5273+
public Rules WithMicrosoftDependencyInjectionRules() => SetMicrosoftDependencyInjectionRules(Clone());
5274+
52685275
/// <summary>Does nothing</summary>
52695276
[Obsolete("Is not used anymore to split the graph - instead use the `DependencyCountInLambdaToSplitBigObjectGraph`")]
52705277
public const int DefaultDependencyDepthToSplitObjectGraph = 20;
@@ -5385,7 +5392,7 @@ public Rules WithDefaultRegistrationServiceKey(object serviceKey) =>
53855392
/// <summary>Rules to select single matched factory default and keyed registered factory/factories.
53865393
/// Selectors applied in specified array order, until first returns not null <see cref="Factory"/>.
53875394
/// Default behavior is to throw on multiple registered default factories, cause it is not obvious what to use.</summary>
5388-
public FactorySelectorRule FactorySelector { get; }
5395+
public FactorySelectorRule FactorySelector => _factorySelector;
53895396

53905397
/// <summary>Sets <see cref="FactorySelector"/></summary>
53915398
public Rules WithFactorySelector(FactorySelectorRule rule) =>
@@ -5590,7 +5597,7 @@ public static DynamicRegistrationProvider AutoFallbackDynamicRegistrations(
55905597

55915598
// We nullify default keys (usually passed by ResolveMany to resolve the specific factory in order)
55925599
// so that `CombineRegisteredWithDynamicFactories` may assign the key again.
5593-
// Given that the implementation types are unchanged then the new keys assignement will be the same the last one,
5600+
// Given that the implementation types are unchanged then the new keys assignment will be the same the last one,
55945601
// so that the factory resolution will correctly match the required factory by key.
55955602
// e.g. bitbucket issue #396
55965603
var theKey = serviceKey is DefaultDynamicKey ? null : serviceKey;
@@ -5914,7 +5921,7 @@ private Rules(Settings settings,
59145921
{
59155922
_settings = settings;
59165923
_made = made;
5917-
FactorySelector = factorySelector;
5924+
_factorySelector = factorySelector;
59185925
DefaultReuse = defaultReuse;
59195926
DefaultIfAlreadyRegistered = defaultIfAlreadyRegistered;
59205927
DependencyCountInLambdaToSplitBigObjectGraph = dependencyCountInLambdaToSplitBigObjectGraph;
@@ -5925,13 +5932,20 @@ private Rules(Settings settings,
59255932
DefaultRegistrationServiceKey = defaultRegistrationServiceKey;
59265933
}
59275934

5928-
private Rules WithSettings(Settings newSettings) =>
5929-
new Rules(newSettings,
5930-
FactorySelector, DefaultReuse, _made, DefaultIfAlreadyRegistered, DependencyCountInLambdaToSplitBigObjectGraph,
5935+
private Rules Clone() =>
5936+
new Rules(_settings, FactorySelector, DefaultReuse,
5937+
_made.Copy(), DefaultIfAlreadyRegistered, DependencyCountInLambdaToSplitBigObjectGraph,
59315938
DependencyResolutionCallExprs, ItemToExpressionConverter,
59325939
DynamicRegistrationProviders, UnknownServiceResolvers, DefaultRegistrationServiceKey);
59335940

5934-
private readonly Made _made;
5941+
private Rules WithSettings(Settings newSettings)
5942+
{
5943+
var newRules = Clone();
5944+
newRules._settings = newSettings;
5945+
return newRules;
5946+
}
5947+
5948+
private Made _made;
59355949

59365950
[Flags]
59375951
private enum Settings
@@ -5970,8 +5984,9 @@ private const Settings DEFAULT_SETTINGS
59705984
| Settings.UseInterpretationForTheFirstResolution;
59715985

59725986
private Settings _settings;
5987+
private FactorySelectorRule _factorySelector;
59735988

5974-
#endregion
5989+
#endregion
59755990
}
59765991

59775992
/// <summary>Wraps constructor or factory method optionally with factory instance to create service.</summary>
@@ -6268,7 +6283,8 @@ internal FactoryMethod(ConstructorInfo ctor, Expression[] resolvedParameterExpre
62686283
public class Made
62696284
{
62706285
/// <summary>Returns delegate to select constructor based on provided request.</summary>
6271-
public FactoryMethodSelector FactoryMethod { get; private set; }
6286+
public FactoryMethodSelector FactoryMethod { get => _factoryMethod; private set => _factoryMethod = value; }
6287+
internal FactoryMethodSelector _factoryMethod;
62726288

62736289
/// <summary>Return type of strongly-typed factory method expression.</summary>
62746290
public Type FactoryMethodKnownResultType { get; private set; }
@@ -6285,7 +6301,7 @@ private enum MadeDetails
62856301
private readonly MadeDetails _details;
62866302

62876303
/// Has any conditional flags
6288-
public bool IsConditional => _details != MadeDetails.NoConditionals;
6304+
public bool IsConditional => _details != MadeDetails.NoConditionals;
62896305

62906306
/// True is made has properties or parameters with custom value.
62916307
/// That's mean the whole made become context based which affects caching.
@@ -6337,17 +6353,15 @@ public override string ToString()
63376353
public static readonly Made Default = new Made();
63386354

63396355
/// <summary>Creates rules with only <see cref="FactoryMethod"/> specified.</summary>
6340-
public static implicit operator Made(FactoryMethodSelector factoryMethod) =>
6341-
Of(factoryMethod);
6356+
public static implicit operator Made(FactoryMethodSelector factoryMethod) => new Made(factoryMethod);
63426357

63436358
/// <summary>Creates rules with only <see cref="Parameters"/> specified.</summary>
6344-
public static implicit operator Made(ParameterSelector parameters) =>
6345-
Of(parameters: parameters);
6359+
public static implicit operator Made(ParameterSelector parameters) => new Made(null, parameters);
63466360

63476361
/// <summary>Creates rules with only <see cref="PropertiesAndFields"/> specified.</summary>
6348-
public static implicit operator Made(PropertiesAndFieldsSelector propertiesAndFields) =>
6349-
Of(propertiesAndFields: propertiesAndFields);
6362+
public static implicit operator Made(PropertiesAndFieldsSelector propertiesAndFields) => new Made(null, null, propertiesAndFields);
63506363

6364+
// todo: @bug fix the spelling for `isConditionalImlementation`
63516365
/// <summary>Specifies injections rules for Constructor, Parameters, Properties and Fields. If no rules specified returns <see cref="Default"/> rules.</summary>
63526366
public static Made Of(FactoryMethodSelector factoryMethod = null,
63536367
ParameterSelector parameters = null, PropertiesAndFieldsSelector propertiesAndFields = null,
@@ -6395,7 +6409,7 @@ public static Made Of(Func<Request, MemberInfo> getMethodOrMember, ServiceInfo f
63956409
/// Where <paramref name="getMethodOrMember"/>Method, or constructor, or member selector.</summary>
63966410
public static Made Of(Func<Request, MemberInfo> getMethodOrMember, Func<Request, ServiceInfo> factoryInfo,
63976411
ParameterSelector parameters = null, PropertiesAndFieldsSelector propertiesAndFields = null) =>
6398-
new Made(r => DryIoc.FactoryMethod.Of(getMethodOrMember(r), factoryInfo(r)),
6412+
new Made(r => DryIoc.FactoryMethod.Of(getMethodOrMember(r), factoryInfo(r)),
63996413
parameters, propertiesAndFields, isImplMemberDependsOnRequest: true);
64006414

64016415
/// <summary>Defines how to select constructor from implementation type.
@@ -6526,11 +6540,11 @@ internal TypedMade(FactoryMethodSelector factoryMethod = null,
65266540
{ }
65276541
}
65286542

6529-
#region Implementation
6543+
#region Implementation
65306544

65316545
internal Made(
65326546
FactoryMethodSelector factoryMethod = null, ParameterSelector parameters = null, PropertiesAndFieldsSelector propertiesAndFields = null,
6533-
Type factoryMethodKnownResultType = null, bool hasCustomValue = false, bool isConditionalImlementation = false,
6547+
Type factoryMethodKnownResultType = null, bool hasCustomValue = false, bool isConditionalImlementation = false,
65346548
bool isImplMemberDependsOnRequest = false)
65356549
{
65366550
FactoryMethod = factoryMethod;
@@ -6554,6 +6568,20 @@ internal Made(FactoryMethod factoryMethod, Type factoryReturnType)
65546568
FactoryMethodKnownResultType = factoryReturnType;
65556569
}
65566570

6571+
private Made(
6572+
FactoryMethodSelector factoryMethod, ParameterSelector parameters, PropertiesAndFieldsSelector propertiesAndFields,
6573+
Type factoryMethodKnownResultType, MadeDetails details)
6574+
{
6575+
FactoryMethod = factoryMethod;
6576+
Parameters = parameters;
6577+
PropertiesAndFields = propertiesAndFields;
6578+
FactoryMethodKnownResultType = factoryMethodKnownResultType;
6579+
_details = details;
6580+
}
6581+
6582+
internal Made Copy() =>
6583+
new Made(FactoryMethod, Parameters, PropertiesAndFields, FactoryMethodKnownResultType, _details);
6584+
65576585
private static ParameterSelector ComposeParameterSelectorFromArgs(ref bool hasCustomValue,
65586586
System.Linq.Expressions.Expression wholeServiceExpr, ParameterInfo[] paramInfos,
65596587
IList<System.Linq.Expressions.Expression> argExprs,
@@ -6617,7 +6645,7 @@ private static PropertiesAndFieldsSelector ComposePropertiesAndFieldsSelector(re
66176645
if (methodCallExpr.Method.Name == Arg.ArgIndexMethodName) // handle custom value
66186646
{
66196647
var getArgValue = GetArgCustomValueProvider(wholeServiceExpr, methodCallExpr, argValues);
6620-
propertiesAndFields = propertiesAndFields.OverrideWith(req =>
6648+
propertiesAndFields = propertiesAndFields.OverrideWith(req =>
66216649
PropertyOrFieldServiceInfo.Of(member).WithDetails(ServiceDetails.Of(getArgValue(req))).One());
66226650
hasCustomValue = true;
66236651
}
@@ -6734,7 +6762,7 @@ private static object GetArgExpressionValueOrThrow(
67346762
argExpr, wholeServiceExpr);
67356763
}
67366764

6737-
#endregion
6765+
#endregion
67386766
}
67396767

67406768
/// <summary>Class for defining parameters/properties/fields service info in <see cref="Made"/> expressions.

test/DryIoc.Microsoft.DependencyInjection.Specification.Tests/ValidateCaptiveTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ namespace DryIoc.Microsoft.DependencyInjection.Specification.Tests
77
public class ValidateCaptiveTests
88
{
99
[Test]
10-
public void ServiceCollection_AddScoped_dependency_in_a_Singleton_ISNOT_Validated_as_captive_dependency()
10+
public void ServiceCollection_AddScoped_dependency_in_a_Singleton_ISNT_Validated_as_captive_dependency()
1111
{
1212
var services = new ServiceCollection();
1313
services.AddScoped<Foo>(); // Actually a `ScopedOrSingleton` due MS.DI convention
1414
services.AddSingleton<Bar>();
1515
services.AddScoped<Buz>(); // Actually a `ScopedOrSingleton` due MS.DI convention
1616

1717
// These two line are "presumably" done by the framework
18-
var providerFactory = new DryIocAdapter.DryIocServiceProviderFactory();
18+
var providerFactory = new DryIocServiceProviderFactory();
1919
var provider = providerFactory.CreateServiceProvider(providerFactory.CreateBuilder(services));
2020

2121
// Getting back the underlying DryIoc container to use its functions (it is always implicitly available).
@@ -36,7 +36,7 @@ public void DryIoc_own_Register_ReuseScope_dependency_in_a_Singleton_IS_Validate
3636
services.AddSingleton<Bar>();
3737

3838
// These two line are "presumably" done by the framework
39-
var providerFactory = new DryIocAdapter.DryIocServiceProviderFactory();
39+
var providerFactory = new DryIocServiceProviderFactory();
4040
var provider = providerFactory.CreateServiceProvider(providerFactory.CreateBuilder(services));
4141

4242
// Getting back the underlying DryIoc container to use its functions (it is always implicitly available).

0 commit comments

Comments
 (0)