Open sandboxFocus

Class ImportDependencyAdviceInstance

Represents a request for a dependency (or service) that the target class receives from its constructors, typically from a dependency injection container such as Microsoft.Extensions.DependencyInjection.

Inheritance
ImportDependencyAdviceInstance
Namespace: PostSharp.Aspects.Advices
Assembly: PostSharp.dll
Syntax
public sealed class ImportDependencyAdviceInstance : AdviceInstance
Remarks

An aspect returns an ImportDependencyAdviceInstance from ProvideAdvices(object), so that the request can depend on the configuration of the target. The target class is the class to which the aspect is applied, or the declaring class of the member to which it is applied. For each target class, the request does the following:

  1. If the class declares or inherits a field of the dependency type that it can access, the request resolves to this field, and nothing else changes. Otherwise, if the class declares or inherits a readable instance property of the dependency type that it can access, the request resolves to this property in the same way; several such properties cause the error LA0286. The field or the property is trusted: the request does not check that the class initializes it.
  2. Otherwise, a private read-only field of the dependency type is introduced, as an IntroduceFieldAdviceInstance without a name and with Ignore does. When the field is not private, as specified by Visibility, or when the dependency is lazy, the field stays private and a getter-only property of the dependency type exposes it. A class whose base class exposes the same dependency by such a property uses that property.
  3. A parameter of the dependency type is appended to the instance constructors of the class, and to those of the classes that derive from it, whose base(...) calls pass it, also when they are in another assembly that PostSharp processes. A constructor that already has a parameter of exactly the dependency type uses it.
  4. Each original constructor is kept as a forwarder that passes null for the dependency. A public forwarder becomes protected internal, or internal in a sealed class, so that a dependency injection container sees only the constructors that receive the dependency, while the code of the assembly and the derived classes in other assemblies can still call it.
  5. The constructors assign the field just after the base constructor call, as C# assigns a field from a constructor parameter, and before the aspects are initialized and the body of the constructor runs. When the argument is null, the dependency is resolved from RunTimeServiceLocator: GetRequiredService<T>() for a required dependency, which throws InvalidOperationException when no service is registered, and GetService<T>() for an optional one.

The advices of the aspect instance that made the request receive the dependency through a parameter annotated with ImportMemberAttribute: by the Name of the request, whatever the names of the field and of the property, or without a name, by the dependency type. The parameter receives the property when there is one, and the field otherwise. On a static target, it receives null.

An object of the class can still be created with new in the project, through a forwarder: its dependencies are then resolved from RunTimeServiceLocator, where the application registers a factory for each service. The request also works with OnInstanceConstructedAdvice: the dependencies are assigned before the advice runs.

Applying such an aspect to a public class changes its public constructors. This is a binary breaking change for the consumers of the class. Several requests for the same dependency type in a class give one field and one parameter, which is required when one of the requests is.

Constructors

Name Description
ImportDependencyAdviceInstance(Type)

Initializes a new instance of the ImportDependencyAdviceInstance class.

Properties

Name Description
DependencyType

Gets the type of the dependency.

IsLazy

Gets or sets a value indicating whether the dependency is resolved when it is first used rather than when the object is created. A lazy dependency is received as a Lazy<T> of the dependency type, stored in a field of that type, and exposed by a getter-only property of the dependency type that returns Value. The container must be able to create the Lazy<T>. The default value is false.

IsRequired

Gets or sets a value indicating whether the dependency is required. The default value is true. A required dependency is a mandatory constructor parameter, checked for null; an optional dependency is an optional parameter whose default value is null.

MasterAspectMember

Gets the main field or method of the aspect class that the current AdviceInstance relates to.

Name

Gets or sets the name by which the advices of the aspect import the dependency with ImportMemberAttribute, and the name of the property that exposes it, or null. Without a name, the advices import the dependency by its type, and the property is named after the dependency type, without the I of an interface. When another member has the name, a number is appended to the name of the property.

Visibility

Gets or sets the visibility of the member that exposes the dependency, or null for the default value: Family, or Private when the target class is sealed. A dependency that is not private is exposed by a getter-only property of this visibility, so that derived classes, also in other assemblies, can read it, and so that the dependency can later become lazy without changing that member.

See Also