From 0392d5a7a14b52c1042be28464bacc958991de17 Mon Sep 17 00:00:00 2001 From: Yair Halberstadt Date: Mon, 12 Apr 2021 18:31:12 +0300 Subject: [PATCH] Add doc comments to public apis (#111) --- Directory.Build.props | 4 +++- StrongInject/DecoratorFactoryAttribute.cs | 6 ++++++ StrongInject/FactoryAttribute.cs | 9 ++++++++ StrongInject/FactoryOfAttribute.cs | 11 ++++++++++ StrongInject/Helpers.cs | 4 ++++ StrongInject/IContainer.cs | 7 +++++++ StrongInject/IFactory.cs | 24 ++++++++++++++++++++++ StrongInject/IRequiresInitialization.cs | 6 ++++++ StrongInject/InstanceAttribute.cs | 8 ++++++++ StrongInject/Owned.cs | 20 ++++++++++++++++++ StrongInject/RegisterAttribute.cs | 22 ++++++++++++++++++++ StrongInject/RegisterDecoratorAttribute.cs | 10 +++++++++ StrongInject/RegisterFactoryAttribute.cs | 13 ++++++++++++ StrongInject/RegisterModuleAttribute.cs | 6 ++++++ StrongInject/ValueTaskExtensions.cs | 2 +- 15 files changed, 150 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index c8a53aa..f1c5b63 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,9 @@ CS1591 AD0001 true - 5 + AllEnabledByDefault + preview + true *-* *-* diff --git a/StrongInject/DecoratorFactoryAttribute.cs b/StrongInject/DecoratorFactoryAttribute.cs index 861db6d..3e6357f 100644 --- a/StrongInject/DecoratorFactoryAttribute.cs +++ b/StrongInject/DecoratorFactoryAttribute.cs @@ -2,6 +2,12 @@ namespace StrongInject { + /// + /// Use this to mark a method as a decorater for it's return type. + /// Exactly one of the parameters must be the same type as the return type. + /// When resolving an instance of the return type, once the type has been resolved as normal it will be passed as a parameter to the method. + /// You can mark both normal methods and generic methods with this attribute. + /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public sealed class DecoratorFactoryAttribute : Attribute { diff --git a/StrongInject/FactoryAttribute.cs b/StrongInject/FactoryAttribute.cs index 352342e..1696481 100644 --- a/StrongInject/FactoryAttribute.cs +++ b/StrongInject/FactoryAttribute.cs @@ -2,9 +2,18 @@ namespace StrongInject { + /// + /// Use this to mark a method as a factory. + /// The method will be used to resolve instances of its return type. + /// You can mark both normal methods and generic methods with this attribute. + /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public sealed class FactoryAttribute : Attribute { + /// + /// + /// + /// The scope of each instance resolved from the method - i.e. how often the method will be called. public FactoryAttribute(Scope scope = Scope.InstancePerResolution) { Scope = scope; diff --git a/StrongInject/FactoryOfAttribute.cs b/StrongInject/FactoryOfAttribute.cs index 7d7fc62..94bdb6a 100644 --- a/StrongInject/FactoryOfAttribute.cs +++ b/StrongInject/FactoryOfAttribute.cs @@ -2,9 +2,20 @@ namespace StrongInject { + /// + /// Use this to mark a generic method as a factory, but only to be used to resolve instances of . + /// can be a concrete type or an open generic. + /// You can mark a method with this attribute multiple times. + /// Do not also mark it with the . + /// [AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = false)] public sealed class FactoryOfAttribute : Attribute { + /// + /// + /// + /// The type which the method should be used to resolve + /// The scope of each instance resolved from the method - i.e. how often the method will be called. public FactoryOfAttribute(Type type, Scope scope = Scope.InstancePerResolution) { Type = type; diff --git a/StrongInject/Helpers.cs b/StrongInject/Helpers.cs index 25dccaf..4aae700 100644 --- a/StrongInject/Helpers.cs +++ b/StrongInject/Helpers.cs @@ -1,10 +1,13 @@ using System; +using System.ComponentModel; using System.Threading.Tasks; namespace StrongInject { + [EditorBrowsable(EditorBrowsableState.Never)] public static class Helpers { + [EditorBrowsable(EditorBrowsableState.Never)] public static void Dispose(T instance) { if (instance is IDisposable disposable) @@ -13,6 +16,7 @@ public static void Dispose(T instance) } } + [EditorBrowsable(EditorBrowsableState.Never)] public static ValueTask DisposeAsync(T instance) { if (instance is IAsyncDisposable asyncDisposable) diff --git a/StrongInject/IContainer.cs b/StrongInject/IContainer.cs index f86bedf..45dc2c4 100644 --- a/StrongInject/IContainer.cs +++ b/StrongInject/IContainer.cs @@ -4,6 +4,11 @@ namespace StrongInject { + /// + /// Implement this interface to tell StrongInject to generate implementations for and . + /// You can implement this interface multiple times for different values of , and Single Instances will be shared. + /// + /// public interface IContainer : IDisposable { [EditorBrowsable(EditorBrowsableState.Never)] @@ -11,6 +16,8 @@ public interface IContainer : IDisposable Owned Resolve(); } + /// Implement this interface to tell StrongInject to generate implementations for and . + /// You can implement this interface multiple times for different values of , and Single Instances will be shared. public interface IAsyncContainer : IAsyncDisposable { [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/StrongInject/IFactory.cs b/StrongInject/IFactory.cs index 6581387..e7ccd1b 100644 --- a/StrongInject/IFactory.cs +++ b/StrongInject/IFactory.cs @@ -2,6 +2,18 @@ namespace StrongInject { + /// + /// A type implementing this interface can be registered as a factory for . + /// It can be registered either via the , + /// or by marking a field/property with the and configuring it's . + /// + /// In general it's easier to use factory methods instead (methods marked with the . + /// Only use this if you either need control over the lifetime of the factory, + /// or you need to control disposal of the created type. + /// + /// For example, you may want to implement this if you would like to cache and reuse instances after they've been released. + /// + /// public interface IFactory { T Create(); @@ -13,6 +25,18 @@ void Release(T instance) ; } + /// + /// A type implementing this interface can be registered as an async factory for . + /// It can be registered either via the , + /// or by marking a field/property with the and configuring it's . + /// + /// In general it's easier to use factory methods instead (methods marked with the . + /// Only use this if you either need control over the lifetime of the factory, + /// or you need to control disposal of the created type. + /// + /// For example, you may want to implement this if you would like to cache and reuse instances after they've been released. + /// + /// public interface IAsyncFactory { ValueTask CreateAsync(); diff --git a/StrongInject/IRequiresInitialization.cs b/StrongInject/IRequiresInitialization.cs index 59b8344..ad51721 100644 --- a/StrongInject/IRequiresInitialization.cs +++ b/StrongInject/IRequiresInitialization.cs @@ -2,11 +2,17 @@ namespace StrongInject { + /// + /// Implement this interface to inform StrongInject that a type will need initialization once it is instantiated before it is ready to be used. + /// public interface IRequiresInitialization { void Initialize(); } + /// + /// Implement this interface to inform StrongInject that a type will need asynchronous initialization once it is instantiated before it is ready to be used. + /// public interface IRequiresAsyncInitialization { ValueTask InitializeAsync(); diff --git a/StrongInject/InstanceAttribute.cs b/StrongInject/InstanceAttribute.cs index bb2d80a..1983ddb 100644 --- a/StrongInject/InstanceAttribute.cs +++ b/StrongInject/InstanceAttribute.cs @@ -2,9 +2,17 @@ namespace StrongInject { + /// + /// Use this attribute to register a field or property, so it can be used in resolution. + /// [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public sealed class InstanceAttribute : Attribute { + /// + /// + /// + /// Options to configure how the field/property should be registered. + /// See the documentation on . public InstanceAttribute(Options options = Options.Default) { Options = options; diff --git a/StrongInject/Owned.cs b/StrongInject/Owned.cs index e9d3f85..d750d37 100644 --- a/StrongInject/Owned.cs +++ b/StrongInject/Owned.cs @@ -4,6 +4,16 @@ namespace StrongInject { + /// + /// A disposable wrapper for an instance of . + /// + /// Make sure to dispose this once you are done using . This will dispose and all dependencies of it. + /// + /// Do not dispose directly as that will not dispose its dependencies. + /// + /// Do not use after this is disposed. + /// + /// public sealed class Owned : IDisposable { private readonly Action _dispose; @@ -27,6 +37,16 @@ public void Dispose() } } + /// + /// An async disposable wrapper for an instance of . + /// + /// Make sure to dispose this once you are done using . This will dispose and all dependencies of it. + /// + /// Do not dispose directly as that will not dispose its dependencies. + /// + /// Do not use after this is disposed. + /// + /// public sealed class AsyncOwned : IAsyncDisposable { private readonly Func _dispose; diff --git a/StrongInject/RegisterAttribute.cs b/StrongInject/RegisterAttribute.cs index 7a817d2..0ee3f5a 100644 --- a/StrongInject/RegisterAttribute.cs +++ b/StrongInject/RegisterAttribute.cs @@ -2,13 +2,35 @@ namespace StrongInject { + /// + /// Use this attribute to register a type with StrongInject. + /// The type must have either exactly one public constructor, or exactly two public constructors, one of which is parameterless. + /// By default the type will be registered as an instance of itself. You can modify it to be registered as any of its supertypes. + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class RegisterAttribute : Attribute { + /// + /// + /// + /// The type to be registered + /// An optional list of types for it to be registered as an instance of. + /// If left empty it will be registered as itself. + /// If not left empty you will have to explicitly register it as itself if desired. + /// All types must be supertypes of public RegisterAttribute(Type type, params Type[] registerAs) : this(type, Scope.InstancePerResolution, registerAs) { } + /// + /// + /// + /// The type to be registered + /// The scope of each instance of - i.e. how often will a new instance be created. + /// An optional list of types for it to be registered as an instance of. + /// If left empty it will be registered as itself. + /// If not left empty you will have to explicitly register it as itself if desired. + /// All types must be supertypes of public RegisterAttribute(Type type, Scope scope, params Type[] registerAs) { Type = type; diff --git a/StrongInject/RegisterDecoratorAttribute.cs b/StrongInject/RegisterDecoratorAttribute.cs index f33c829..504e269 100644 --- a/StrongInject/RegisterDecoratorAttribute.cs +++ b/StrongInject/RegisterDecoratorAttribute.cs @@ -2,9 +2,19 @@ namespace StrongInject { + /// + /// Use this attribute to register a decorator for a type. + /// When resolving an instance of the type, once the type has been resolved as normal it will be wrapped by an instance of the decorator. + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class RegisterDecoratorAttribute : Attribute { + /// + /// + /// + /// The type to use as a decorator. Must be a subtype of . + /// The type which will be decorated (wrapped) by . + /// public RegisterDecoratorAttribute(Type type, Type decoratedType, DecoratorOptions decoratorOptions = DecoratorOptions.Default) { Type = type; diff --git a/StrongInject/RegisterFactoryAttribute.cs b/StrongInject/RegisterFactoryAttribute.cs index 0557a9b..f147dd7 100644 --- a/StrongInject/RegisterFactoryAttribute.cs +++ b/StrongInject/RegisterFactoryAttribute.cs @@ -2,9 +2,22 @@ namespace StrongInject { + /// + /// Use this attribute to register a type implementing or as a factory for T, + /// meaning T will be resolved by resolving an instance of the factory, and then calling or . + /// + /// It's usually simpler to write a factory method and mark it with the . + /// Use this only if you need tight control over the lifetime of your factory, or if you want to control disposal of the factory target. + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class RegisterFactoryAttribute : Attribute { + /// + /// + /// + /// The factory to register. Must implement or . + /// The scope of the factory - i.e. how often should a new factory be created? + /// The scope of the factory target - i.e. how often should or be called? public RegisterFactoryAttribute(Type factoryType, Scope factoryScope = Scope.InstancePerResolution, Scope factoryTargetScope = Scope.InstancePerResolution) { FactoryType = factoryType; diff --git a/StrongInject/RegisterModuleAttribute.cs b/StrongInject/RegisterModuleAttribute.cs index 53a5598..356538a 100644 --- a/StrongInject/RegisterModuleAttribute.cs +++ b/StrongInject/RegisterModuleAttribute.cs @@ -2,9 +2,15 @@ namespace StrongInject { + /// + /// Use this attribute to import registrations defined on a different type. + /// [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)] public sealed class RegisterModuleAttribute : Attribute { + /// + /// The module to register + /// An optional list of types which should not be resolved via this module public RegisterModuleAttribute(Type type, params Type[] exclusionList) { Type = type; diff --git a/StrongInject/ValueTaskExtensions.cs b/StrongInject/ValueTaskExtensions.cs index 37ce3f5..52c5072 100644 --- a/StrongInject/ValueTaskExtensions.cs +++ b/StrongInject/ValueTaskExtensions.cs @@ -2,7 +2,7 @@ namespace StrongInject { - public static class ValueTaskExtensions + internal static class ValueTaskExtensions { public static ValueTask AsValueTask(this ValueTask valueTask) {