diff --git a/architecture/index.html b/architecture/index.html deleted file mode 100644 index 2c93936..0000000 --- a/architecture/index.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - - - - StructureMap - Internals and Architecture - - - - - - - - - - - - - - - - - - - -Fork me on GitHub - - - -
- -
- - -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

Best Practices

-

Previous

Diagnostics

- - -
- - -
-

Internals and Architecture

- -
- -
- -

TODO(Write content!)

- - -
- -
- - - -
-
-
- - - - - - - - - - - - - - - - diff --git a/autofactory/index.html b/autofactory/index.html new file mode 100644 index 0000000..ae163eb --- /dev/null +++ b/autofactory/index.html @@ -0,0 +1,180 @@ + + + + + + + + StructureMap - Auto-factories + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
+ +
+ + +
+
+ + + + + +
+

Auto-factories Edit on GitHub

+ +
+ +
+ + +

When you need to implement Abstract Factory, StructureMap offers a way to do it for you. Let's say you have

+

public interface IDummyService
{
    string Name { get; }
}

+with implementation +

public class DummyService : IDummyService
{
    public string Name { get; set; }
}

+

Now you declare an interface for your factory:

+

public interface ISimpleDummyFactory
{
    IDummyService CreateDummyService();
}

+

All you need to do is to call CreateFactory when configuring the container as shown below:

+

[Fact]
public void Simple_factory_creation()
{
    var container = new Container(cfg =>
    {
        cfg.For<IDummyService>().Use<DummyService>();
        cfg.For<ISimpleDummyFactory>().CreateFactory();
    });

    var factory = container.GetInstance<ISimpleDummyFactory>();

    var component = factory.CreateDummyService();

    component.ShouldNotBeNull();
    component.ShouldBeOfType<DummyService>();
}

+

Default convention

+

As for now, Auto-factories support two types of methods:

+
    +
  1. Methods to list all names of registered implementations.
  2. +
  3. Methods to create object instances i.e. factory methods.
  4. +
+

To declare a method that has to return the names of registered implementations, the method signature must satisfy the following conditions:

+
    +
  1. The name has to start with GetNames
  2. +
  3. It must be a generic method.
  4. +
  5. The method return type must be assignable from List<string> e.g. IList<string>, IEnumerable<string>
  6. +
+

Any other method that has the return type (i.e. doesn't return void), is treated as a factory method. In addition, if the method name starts with GetNamed, the first method argument is used as the name for the named instance. All the rest arguments are passed as explicit arguments to the implementation constructor.

+

It is much easier to see it on an example:

+

public interface IDummyFactory
{
    // This method will return the names of all registered implementations of TService.
    IList<string> GetNames<TService>();

    // This method will just create the default IDummyService implementation.
    IDummyService CreateDummyService();

    // This method will just create the default IDummyService implementation and pass namePart1 and namePart2 as
    // dependencies.
    IDummyService CreateDummyService(string namePart1, string namePart2);

    // This method will create IDummyService implementation with serviceName name.
    IDummyService GetNamedDummyService(string serviceName, string namePart1, string namePart2);

    // Generic methods are also allowed as factory methods.
    TService CreateService<TService>();

    // Something that is common for event-sourcing implementations.
    IHandler<TMessage> CreateHandler<TMessage>();
}

+

Custom convention

+

If the default convention doesn't work for you, you can create and use your custom convention. All you need is to implement IAutoFactoryConventionProvider and use the corresponding CreateFactory overload. IAutoFactoryConventionProvider has a single method to implement:

+
IAutoFactoryMethodDefinition GetMethodDefinition(MethodInfo methodInfo, IList<object> arguments);
+
+

IAutoFactoryMethodDefinition is defined as follows:

+

public interface IAutoFactoryMethodDefinition
{
    AutoFactoryMethodType MethodType { get; }

    Type InstanceType { get; }

    string InstanceName { get; }

    ExplicitArguments ExplicitArguments { get; }
}

+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + diff --git a/best-practices/index.html b/best-practices/index.html index 3bd5137..3259303 100644 --- a/best-practices/index.html +++ b/best-practices/index.html @@ -1,131 +1,187 @@ - + - StructureMap - Best Practices - - - - - - - - - - + StructureMap - Best Practices + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Best Practices Edit on GitHub

+ +
+ +
+ + +

All of these recommendations are the opinions and sole responsiblity of one Jeremy D. Miller. The single best advice I can give you +about using StructureMap is to avoid being too clever with your usage.

+

Use Nested Containers for Per Transaction/Request/Message Scoping

+

In idiomatic StructureMap usage, I strongly recommend using a nested container for short lived operations like:

+
    +
  1. An HTTP request
  2. +
  3. Handling a single service bus message
  4. +
  5. Short lived transactions
  6. +
+

Avoid the Legacy ASP.Net Lifecycles

+

To repeat the section above, I strongly recommend using nested containers instead of the legacy ASP.Net lifecycles to scope +services per HTTP request.

+

Avoid Container.Configure() on the Root Container

+

Unfortunately, the Container.Configure() method is potentially an expensive operation +and can result in some container-wide locks if you change any kind of interception or construction policy. Avoid this mechanism at runtime. If you need +to inject services at runtime, try to do those overrides in an isolated nested container for that +particular request or transaction to avoid hitting any kind of shared lock.

+

Avoid Container.TryGetInstance()

+

Use the container to resolve your dependency relationships or don't. In my opinion, using TryGetInstance() results in unnecessary complexity in your application. My recommendation is to use nullo objects as stand-ins or to use "modular registration" strategies instead (See Fallback Services and Replace or Clear Out Previous Registrations for more information). The ASP.Net team requires this usage for all of their IoC container integrations and you can't fight city hall, so StructureMap 4.0 includes some performance optimizations specifically for the heavy TryGetInstance() usage that I never anticipated.

+

Favor Constructor Injection over Setter Injection

+

I believe that constructor injection is less error prone than setter injection and is more easily traceable later. Setter injection is occasionally easier +to use (in inheritance relationships for an example), but is mostly available in StructureMap as a workaround for code that was not built with dependency +injection in mind (or popular frameworks that were built around Spring.Net usage cough NServiceBus cough).

+

Use Child Containers for Test Isolation

+

See Profiles and Child Containers for more information.

+

Use Registry Classes

+

While you can completely set up a Container object through its constructor function and repeated calls to Container.Configure(), we suggest that you +express any configurations in Registry objects for repeatable configuration later in tests and for a cleaner expression +of the configuration.

+

Do consider breaking your configuration across separate Registry objects for different subsystems if the StructureMap configuration gets complicated.

+

Onion Architecture Assembly Coupling

+

If your choice is between making a direct dependency from one assembly to another strictly to make the StructureMap configuration easy and less error prone or using dynamic assembly loading and configuration strategies with type scanning to comply with the Onion Architecture, I very strongly recommend you favor the less error prone, direct assembly dependencies.

+

Favor Build Policies over Fancy Runtime Decision Making

+

While there are many powerful things you can do with StructureMap at runtime for conditional object resolution with lambdas and IContext, +I recommend trying to "bake in" building decisions upfront with build policies for more efficient object resolution and so that +the container behavior is surfaced through diagnostics like the build plan visualization.

+ +
+ +
+ + + +
+
+
-
- -
- -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

FAQ

-

Previous

Internals and Architecture

- - -
- - -
-

Best Practices

- -
- -
- - -

TODO(Write some content!)

- + -
-
+ + + -
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Build Plans Edit on GitHub

+ +
+ +
+ + +

StructureMap 3.0 introduced the concept of the "Build Plan." The build plan is a textual representation of exactly how StructureMap will build a given Instance, including:

+
    +
  1. What constructor function, if any, StructureMap is going to use for a concrete type
  2. +
  3. How it is resolving the constructor dependencies in a recursive fashion
  4. +
  5. Which setter properties for a concrete type receive dependencies and how those setter dependencies are built
  6. +
  7. The lifecycle used for the Instance
  8. +
  9. All interceptors applied to the Instance
  10. +
  11. Explicitly configured inline dependencies
  12. +
  13. Description of any Lambda or Func<T> that is used to construct the Instance object
  14. +
+

To retrieve the build plan for a configured Instance, use the queryable Container.Model to find the configured Instance and call DescribeBuildPlan(int maxDepth) to get the textual report as shown in this sample below:

+

var container = Container.For<VisualizationRegistry>();

var description = container.Model.For<IDevice>().Default
    .DescribeBuildPlan();

Debug.WriteLine(description);
+

The result of the code above is this textual representation of how StructureMap will build and/or resolve the default of the IDevice plugin type:

+
+PluginType: StructureMap.Testing.Diagnostics.IDevice
+Lifecycle: Transient
+Decorator --> FuncInterceptor of StructureMap.Testing.Diagnostics.IDevice: new DeviceDecorator(IDevice)
+Decorator --> Decorator of type StructureMap.Testing.Diagnostics.CrazyDecorator
+    new CrazyDecorator(IDevice, IEngine, IFoo)
+      ┣ IDevice = The inner IDevice
+      ┃ ┗ new DefaultDevice()
+      ┣ IEngine = **Default**
+      ┗ IFoo = **Default**
+      
+
+

For another example, you can retrieve the build plan for a named instance of a certain build plan with this code:

+

var description = theContainer.Model.For<IDevice>()
    .Find("A")
    .DescribeBuildPlan();
+

See Using the Container Model for more information on using Container.Model.

+

You can find many more examples of finding the build plan description from Container.Model from the unit tests in the StructureMap codebase.

+ +
+ +
+ + + +
+
+
-
- -
- -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

Using the Container Model

-

Previous

Environment Tests

- - -
- - -
-

Build Plans

- -
- -
- - -

TODO(Write some content!)

- + -
-
+ + + -
+ + +
+ +
+ + +
+
+ + + + + +
+

Environment Tests Edit on GitHub

+ +
+ +
+ + +

Years ago I worked with a legacy system that was particularly fragile in its deployment. While my team at the time and I made some serious improvements in the reliability of the automated deployment, the best thing we did was to add a set of environment tests to the deployment that verified that basic elements of the system were working like:

+
    +
  • Could our code access the configured database?
  • +
  • Was a certain COM object registered on the server? (I hated COM then and the years haven't changed my mind)
  • +
  • Could we connect via remoting to another deployed application?
  • +
+

The deployments still frequently failed, but we were able to spot and diagnose the underlying problems much faster with our new environment tests than we could before by trying to run and debug the not-quite-valid application.

+

One of the mechanisms we used for these environment tests was StructureMap's ability to mark methods on configured types as environment tests with the [ValidationMethod] attribute as shown below:

+

public class Database : IDatabase
{
    [ValidationMethod]
    public void TryToConnect()
    {
        // try to open a connection to the configured
        // database connection string

        // throw an exception if the database cannot
        // be reached
    }
}
+

Used in conjunction with StructureMap's ability to validate a container, you can use this technique to quickly support environment tests embedded into your system code.

+ +
+ +
+ + + +
+
+
-
- -
- -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

Build Plans

-

Previous

Validating Container Configuration

- - -
- - -
-

Environment Tests

- -
- -
- - -

TODO(Write some content!)

- + -
-
+ + + -
- +
+ -
- -
+
+ +
- -
-
- - -
-

StructureMap 3.1.6

-
+ +
+
+ - +
-

Next

WhatDoIHave()

-

Previous

Interpreting Exceptions

+ +
+

Diagnostics Edit on GitHub

- -
- - -
-

Diagnostics

- -
+
-
- -

Improving StructureMap's ability to diagnose and explain both configuration and runtime problems was a very big goal -for the latest major release (3.0).

- - +
+ +

Improving StructureMap's ability to diagnose and explain both configuration and runtime problems was a very big goal +for the big 3.0 release and improved with additional type scanning diagnostics for 4.0.

+ -
+
-
+
- -
-
-
+
+
+
@@ -127,6 +125,29 @@

Diagnostics

+ + diff --git a/diagnostics/type-scanning/index.html b/diagnostics/type-scanning/index.html new file mode 100644 index 0000000..9555b3e --- /dev/null +++ b/diagnostics/type-scanning/index.html @@ -0,0 +1,171 @@ + + + + + + + + StructureMap - Type Scanning Diagnostics + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
+ +
+ + +
+
+ + + + + +
+

Type Scanning Diagnostics Edit on GitHub

+ +
+ +
+ + +

Type scanning and conventional auto-registration is a very powerful feature in StructureMap, but it has been frequently troublesome to users when things go wrong. To try to alleviate problems, StructureMap 4.0 introduces some new functionality for detecting and diagnosing problems with type scanning, mostly related to Assembly's being missing.

+

Assert for Assembly Loading Failures

+

At its root, most type scanning and auto-registration schemes in .Net frameworks rely on the Assembly.GetExportedTypes() method. Unfortunately, that method can be brittle and fail whenever any dependency of that Assembly cannot be loaded into the current process, even if your application has no need for that dependency. In StructureMap 3.* and before, that loading exception was essentially swallowed and lost. In StructureMap 4 and above, you can use this method to assert the presence of any assembly load exceptions during type scanning:

+

TypeRepository.AssertNoTypeScanningFailures();
+

The method above will throw an exception listing all the Assembly's that failed during the call to GetExportedTypes() only if there were any failures. Use this method during your application bootstrapping if you want it to fail fast with any type scanning problems.

+

What did StructureMap scan?

+

Confusion of type scanning has been a constant problem with StructureMap usage over the years -- especially if users are trying to dynamically load assemblies from the file system for extensibility. In order to see into what StructureMap has done with type scanning, 4.0 introduces the Container.WhatDidIScan() method.

+

Let's say that you have a Container that is set up with at least two different scanning operations like this sample from the StructureMap unit tests:

+

var container = new Container(_ =>
{
    _.Scan(x =>
    {
        x.TheCallingAssembly();

        x.WithDefaultConventions();
        x.RegisterConcreteTypesAgainstTheFirstInterface();
        x.SingleImplementationsOfInterface();
    });

    _.Scan(x =>
    {
        // Give your scanning operation a descriptive name
        // to help the diagnostics to be more useful
        x.Description = "Second Scanner";

        x.AssembliesFromApplicationBaseDirectory(assem => assem.FullName.Contains("Widget"));
        x.ConnectImplementationsToTypesClosing(typeof(IService<>));
        x.AddAllTypesOf<IWidget>();
    });
});

Debug.WriteLine(container.WhatDidIScan());
+

The resulting textual report is shown below:

+

Sorry for the formatting and color of the text, but the markdown engine does not like the textual report

+

/*
All Scanners
================================================================
Scanner #1
Assemblies
----------
* StructureMap.Testing, Version=4.0.0.51243, Culture=neutral, PublicKeyToken=null

Conventions
--------
* Default I[Name]/[Name] registration convention
* Register all concrete types against the first interface (if any) that they implement
* Register any single implementation of any interface against that interface

Second Scanner
Assemblies
----------
* StructureMap.Testing.GenericWidgets, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
* StructureMap.Testing.Widget, Version=4.0.0.51243, Culture=neutral, PublicKeyToken=null
* StructureMap.Testing.Widget2, Version=4.0.0.51243, Culture=neutral, PublicKeyToken=null
* StructureMap.Testing.Widget3, Version=4.0.0.51243, Culture=neutral, PublicKeyToken=null
* StructureMap.Testing.Widget4, Version=4.0.0.51243, Culture=neutral, PublicKeyToken=null
* StructureMap.Testing.Widget5, Version=4.0.0.51243, Culture=neutral, PublicKeyToken=null

Conventions
--------
* Connect all implementations of open generic type IService<T>
* Find and register all types implementing StructureMap.Testing.Widget.IWidget

*/
+

The textual report will show:

+
    +
  1. All the scanning operations (calls to Registry.Scan()) with a descriptive name, either one supplied by you or the Registry type and an order number.
  2. +
  3. All the assemblies that were part of the scanning operation including the assembly name, version, and a warning if Assembly.GetExportedTypes() failed on that assembly.
  4. +
  5. All the configured scanning conventions inside of the scanning operation
  6. +
+

WhatDidIScan() does not at this time show any type filters or exclusions that may be part of the assembly scanner.

+

See also: Auto-Registration and Conventions

+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + diff --git a/diagnostics/using-the-container-model/index.html b/diagnostics/using-the-container-model/index.html index 655c131..1225f9b 100644 --- a/diagnostics/using-the-container-model/index.html +++ b/diagnostics/using-the-container-model/index.html @@ -1,131 +1,188 @@ - + - StructureMap - Using the Container Model - - - - - - - - - - + StructureMap - Using the Container Model + + + + + + + + + + + - + - + Fork me on GitHub - + + +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Using the Container Model Edit on GitHub

+ +
+ +
+ + +

The queryable Container.Model is a power facility to look into your StructureMap Container and even to eject previously built services from the Container. The Container.Model represents a static view of what a Container already has, and does not account for policies that may allow StructureMap to validly discover types that it may encounter later at runtime.

+

Querying for Plugin Types

+

The WhatDoIHave() mechanism works by just iterating over the Container.Model.PluginTypes collection as shown below:

+

container.Model.PluginTypes.Where(x => x.PluginType.Assembly == Assembly.GetExecutingAssembly())
    .Each(pluginType => Debug.WriteLine(pluginType.PluginType));
+

Working with a Plugin Type

+

The IPluginTypeConfiguration interface allows you to query and manipulate all the configured Instance's for a given plugin type.

+

See the entire IPluginTypeConfiguration interface here.

+

Finding the Default for a Plugin Type

+

To simply find out what the default concrete type would be for a requested plugin type, use one of these two methods:

+

// Finding the concrete type of the default
// IDevice service
container.Model.DefaultTypeFor<IDevice>()
    .ShouldBe(typeof(DefaultDevice));

// Find the configuration model for the default
// IDevice service
container.Model.For<IDevice>().Default
    .ReturnedType.ShouldBe(typeof(DefaultDevice));
+

Finding an Instance by Type and Name

+

Use this syntax to find information about an Instance in a given plugin type and name:

+

var redRule = container.Model.Find<Rule>("Red");
+

All Instances for a Plugin Type

+

This sample shows how you could iterate or query over all the registered instances for a single plugin type:

+

container.Model.For<Rule>().Instances.Each(i =>
{
    Debug.WriteLine(i.Instance.Description);
});
+

Ejecting Services and/or Configuration

+

It's possible to remove singleton scoped objects from a running Container to force a new one to be built or even to completely remove configured instance objects and configuration permanently from a Container. This is typically only used in automated testing to flush static state between tests.

+

To remove and dispose previously built singleton scoped objects from a Container, use this code:

+

// ONLY ejects any built object for this Instance from the SingletonThing
// cache
container.Model.For<IDevice>().Default.EjectObject();
+

To completely eject any singletons and permanently remove all related configuration, use this code:

+

// Removes all configurations and objects already built as singletons
// related to types in the current Assembly
container.Model.EjectAndRemoveTypes(type => type.Assembly == Assembly.GetExecutingAssembly());

// Removes all configurations and objects already built as singletons
// that were registered to IDevice
container.Model.EjectAndRemove(typeof(IDevice));
+

Testing for Registrations

+

To troubleshoot or automate testing of Container configuration, you can use code like the sample below to +test for the presence of expected configurations:

+

// Is there a default instance for IDevice?
container.Model.HasDefaultImplementationFor<IDevice>().ShouldBeTrue();

// Are there any configured instances for IDevice?
container.Model.HasImplementationsFor<IDevice>().ShouldBeTrue();
+

Finding all Possible Implementors of an Interface

+

Forget about what types are registered for whatever plugin types and consider this, what if you have an interface called +IStartable that just denotes objects that will need to be activated after the container is bootstrapped?

+

If our interface is this below:

+

public interface IStartable
{
    bool WasStarted { get; }

    void Start();
}

+

We could walk through the entire StructureMap model and find every registered instance that implements this interface, create each, and call the Start() method like in this code below:

+

var allStartables = container.Model.GetAllPossible<IStartable>();
allStartables.ToArray()
    .Each(x => x.Start());
+

I've also used this mechanism in automated testing to reach out to all singleton services that may have state to clear out their data between tests.

+

Working with Individual Instances

+

You can manipulate an individual instance in several ways:

+

// First, find the model for a single Instance
var instance = container.Model.For<IDevice>().Default;

// build or resolve an object for this Instance cast to
// the type specified to the Get() method
instance.Get<IDevice>().ShouldBeOfType<DefaultDevice>();

// if the instance is configured as a SingletonThing, test
// if the SingletonThing object has already been created
var hasSingletonBeenCreated = instance.ObjectHasBeenCreated();

if (hasSingletonBeenCreated)
{
    // remove the SingletonThing object from the cache so that
    // StructureMap will be forced to rebuild this object
    instance.EjectObject();
}

// test the lifecycle of this instance
instance.Lifecycle.ShouldBeOfType<SingletonLifecycle>();

// Visualize the build plan no more than 3 levels deep
Debug.WriteLine(instance.DescribeBuildPlan(3));

// Get at the underlying Instance model that StructureMap itself
// uses. Be cautious using this.
var rawModel = instance.Instance;

+ +
+ +
+ + + +
+
+
-
- -
- -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

Internals and Architecture

-

Previous

Build Plans

- - -
- - -
-

Using the Container Model

- -
- -
- - -

TODO(Write some content!)

- + -
-
+ + + -
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Validating Container Configuration Edit on GitHub

+ +
+ +
+ + +

To find any potential holes in your StructureMap configuration like missing dependencies, unclear defaults of plugin types, validation errors, or just plain build errors, you can use this method below:

+

container.AssertConfigurationIsValid();
+

Running this method will walk over every single registration in your Container and:

+
    +
  1. Try to create a build plan for that Instance that will flush out any problems with missing dependencies or invalid inline configuration
  2. +
  3. Try to build every single configured Instance
  4. +
  5. Call any methods on built objects decorated with the [ValidationMethod] attribute to perform environment tests. See Environment Tests for more information on this usage.
  6. +
+

If StructureMap encounters any errors of any kind during this method, it will throw an exception summarizing all of the problems that it encountered. That output will look something like:

+
+
+	StructureMap.StructureMapConfigurationException
+	StructureMap Failures:  1 Build/Configuration Failures and 0 Validation Errors
+	
+	Profile 'DEFAULT'
+	
+	-----------------------------------------------------------------------------------------------------
+	Build Error on Instance 'StructureMap.Testing.Diagnostics.NamedWidget'
+	    for PluginType StructureMap.Testing.Diagnostics.IWidget
+	
+	Unable to create a build plan for concrete type StructureMap.Testing.Diagnostics.NamedWidget
+	new NamedWidget(String name)
+	  ┗ String name = Required primitive dependency is not explicitly defined
+
+
+

Standin Dependencies for Runtime Dependencies

+

If you take advantage of StructureMap's ability to supply arguments at runtime, you may need to add fake or stubbed stand in services to StructureMap just to satisfy dependencies while calling Container.AssertConfigurationIsValid(). For example, in FubuMVC we supply several services representing an HTTP request as explicit arguments. In order to use the container validation, we have to register stand in services in the main container.

+ +
+ +
+ + + +
+
+
-
- -
- -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

Environment Tests

-

Previous

WhatDoIHave()

- - -
- - -
-

Validating Container Configuration

- -
- -
- - -

TODO(Write some content!)

- + -
-
+ + + -
+ + +
+ +
+ + +
+
+ + + + + +
+

WhatDoIHave() Edit on GitHub

+ +
+ +
+ + +

The IContainer.WhatDoIHave() method can give you a quick textual report of the current configuration of a running Container:

+

var container = new Container();
var report = container.WhatDoIHave();

Debug.WriteLine(report);
+

If you're familiar with WhatDoIHave() from earlier versions of StructureMap, the usage has been enhanced for 3.0 to allow you +to filter the results for easier usage. The format was also tweaked extensively to (hopefully) improve the usability of this feature.

+

Enough talk, say you have a Container with this configuration:

+

var container = new Container(x =>
{
    x.For<IEngine>().Use<Hemi>().Named("The Hemi");

    x.For<IEngine>().Add<VEight>().Singleton().Named("V8");
    x.For<IEngine>().Add<FourFiftyFour>().AlwaysUnique();
    x.For<IEngine>().Add<StraightSix>().LifecycleIs<ThreadLocalStorageLifecycle>();

    x.For<IEngine>().Add(() => new Rotary()).Named("Rotary");
    x.For<IEngine>().Add(c => c.GetInstance<PluginElectric>());

    x.For<IEngine>().Add(new InlineFour());

    x.For<IEngine>().UseIfNone<VTwelve>();
    x.For<IEngine>().MissingNamedInstanceIs.ConstructedBy(c => new NamedEngine(c.RequestedName));
});
+

If you were to run the code below against this Container:

+

Debug.WriteLine(container.WhatDoIHave());
+

you would get the output shown in this gist.

+

If you're curious, all the raw code for this example is in here.

+

Filtering WhatDoIHave()

+

Filtering the WhatDoIHave() results can be done in these ways:

+

var container = new Container();

// Filter by the Assembly of the Plugin Type
var byAssembly = container.WhatDoIHave(assembly: typeof(IWidget).GetAssembly());

// Only report on the specified Plugin Type
var byPluginType = container.WhatDoIHave(typeof(IWidget));

// Filter to Plugin Type's in the named namespace
// The 'IsInNamespace' test will include child namespaces
var byNamespace = container.WhatDoIHave(@namespace: "StructureMap.Testing.Widget");

// Filter by a case insensitive string.Contains() match
// against the Plugin Type name
var byType = container.WhatDoIHave(typeName: "Widget");
+ +
+ +
+ + + +
+
+
@@ -178,6 +136,29 @@

Filtering WhatDoIHave()

+ + diff --git a/documentation/index.html b/documentation/index.html index b404626..8c986f8 100644 --- a/documentation/index.html +++ b/documentation/index.html @@ -1,137 +1,115 @@ - + - StructureMap - Documentation - - - - - - - - - - + StructureMap - Documentation + + + + + + + + + + + - + - + Fork me on GitHub - + + +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Documentation Edit on GitHub

+ +
+ +
+

The documentation may never be exhaustive, but here are the major sections so far:

+ + +
+ +
+ + + +
+
+
@@ -145,6 +123,29 @@

Documentation

+ + diff --git a/dynamic-interception/index.html b/dynamic-interception/index.html new file mode 100644 index 0000000..12b0d5e --- /dev/null +++ b/dynamic-interception/index.html @@ -0,0 +1,169 @@ + + + + + + + + StructureMap - Aspect Oriented Programming with StructureMap.DynamicInterception + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Aspect Oriented Programming with StructureMap.DynamicInterception Edit on GitHub

+ +
+ +
+ + +

The Interception and Decorators page describes how to use "static" interception of created instances, mainly allowing to apply the Decorator pattern. It is "static" in a sense that you need know what interfaces you want to implement and you need to create decorators implementing all appropriate interfaces. It is almost always fine, but there are cases when you want to implement the same decorating logic for many interfaces which easily breaks the DRY principle. The most common examples are cross-cutting concerns such as logging, caching etc.

+

Dynamic proxy interceptor

+

Let's see it in action. Let's say we have

+

public interface IMathService
{
    int GetSquareRoot(int value);

    Task<int> GetSquareRootAsync(int value);
}
+with implementation +

private class MathService : IMathService
{
    public int GetSquareRoot(int value)
    {
        return (int)Math.Sqrt(value);
    }

    public async Task<int> GetSquareRootAsync(int value)
    {
        await Task.Yield();
        return (int)Math.Sqrt(value);
    }
}
+

If you need to apply dynamic interception to IMathService, first you implement either ISyncInterceptionBehavior or IAsyncInterceptionBehavior depending if your interception code needs to use async/await or not. For demonstration purposes, let's have

+

private class NegatingInterceptor : ISyncInterceptionBehavior
{
    public IMethodInvocationResult Intercept(ISyncMethodInvocation methodInvocation)
    {
        var argument = methodInvocation.GetArgument("value");
        var argumentValue = (int)argument.Value;
        if (argumentValue < 0)
        {
            argument.Value = -argumentValue;
        }
        return methodInvocation.InvokeNext();
    }
}
+and +

private class AsyncCachingInterceptor : IAsyncInterceptionBehavior
{
    private static readonly IDictionary<int, int> PrecalculatedValues = new Dictionary<int, int>
    {
        { 16, 4444 },
        { 10, 5555 },
    };

    public async Task<IMethodInvocationResult> InterceptAsync(IAsyncMethodInvocation methodInvocation)
    {
        var argument = methodInvocation.GetArgument("value");
        var argumentValue = (int)argument.Value;

        int result;
        return PrecalculatedValues.TryGetValue(argumentValue, out result)
            ? methodInvocation.CreateResult(result)
            : await methodInvocation.InvokeNextAsync().ConfigureAwait(false);
    }
}
+

Finally, we register interceptors with help of DynamicProxyInterceptor as follows:

+

[Theory]
[InlineData(111, 10)]
[InlineData(16, 4444)]
[InlineData(-16, 4444)]
public void CallSyncMethodWithSyncThenAsyncInterceptors(int value, int expectedResult)
{
    var container = new Container(x =>
    {
        x.For<IMathService>().Use<MathService>()
            .InterceptWith(new DynamicProxyInterceptor<IMathService>(new IInterceptionBehavior[]
            {
                new NegatingInterceptor(),
                new AsyncCachingInterceptor()
            }));
    });

    var service = container.GetInstance<IMathService>();

    service.GetSquareRoot(value).ShouldBe(expectedResult);
}
+

The idea is simple - for each method call of the intercepted instance, Intercept/InterceptAsync is called passing an IMethodInvocation instance allowing to get information about the intercepted method and modify arguments if needed before passing to the next interceptor. You have a choice to call the next interceptor in the chain via methodInvocation.InvokeNext/methodInvocation.InvokeNextAsync. Alternatively, you can return the result directly from the interceptor via methodInvocation.CreateResult.

+

Finally, you can also throw exceptions from interceptors either directly or by returning methodInvocation.CreateExceptionResult.

+

Dynamic proxy policy

+

As described on the Interception and Decorators page, you can create an interception policy if you need to apply interceptors to many types by certain filter. DynamicProxyInterceptorPolicy makes it easier when it comes to dynamic interceptors. See the example below:

+

[Fact]
public void UseInterceptionPolicy()
{
    var container = new Container(x =>
    {
        x.Policies.Interceptors(new DynamicProxyInterceptorPolicy(new NegatingInterceptor(), new CachingInterceptor()));

        x.For<IMathService>().Use<MathService>();
    });

    var service = container.GetInstance<IMathService>();

    service.GetSquareRoot(-10).ShouldBe(5555);
}
+

Check DynamicProxyInterceptorPolicy constructors to find the most suitable overload for your purposes.

+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + diff --git a/faq/index.html b/faq/index.html deleted file mode 100644 index b321277..0000000 --- a/faq/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - StructureMap - FAQ - - - - - - - - - - - - - - - - - - - -Fork me on GitHub - - - -
- -
- - -
-
- - -
-

StructureMap 3.1.6

-
- - - -

Next

History

-

Previous

Best Practices

- - -
- - -
-

FAQ

- -
- -
- - -

TODO(Write some content!)

- - -
- -
- - - -
-
-
- - - - - - - - - - - - - - - - diff --git a/features/index.html b/features/index.html index e4002fc..df7d84e 100644 --- a/features/index.html +++ b/features/index.html @@ -1,155 +1,151 @@ - + - StructureMap - Features - - - - - - - - - - + StructureMap - Features + + + + + + + + + + + - + - + Fork me on GitHub - + + +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Features Edit on GitHub

+ +
+ +
+ + + +
    +
  • Programmatic Configuration
  • +
  • Conventional "Auto" Registration
  • +
  • Modular configuration
  • +
  • Constructor and Setter Injection
  • +
  • Configurable constructor selection
  • +
  • Customizable setter injection policies
  • +
  • Auto wiring of dependencies
  • +
  • Inline dependency configuration
  • +
  • Service Location
  • +
  • Strategies for registering and utilizing open generic types
  • +
  • Lifecycle management and custom lifecycles
  • +
  • ASP.Net centric lifecycles with StructureMap.Web
  • +
  • Interception and Configurable Decorators
  • +
  • Lazy, Func, and Func<string, T> dependencies
  • +
  • Auto resolution of enumerable types
  • +
  • Auto resolution of concrete types
  • +
  • "Profile's" for multi-tenancy or optional modes
  • +
  • Diagnostics
  • +
  • Auto resolution conventions
  • +
  • "Auto Mocking*
  • +
  • Simple Auto Factory support
  • +
  • Nested and Child Containers
  • +
+

Things StructureMap does not have

+

The following things are features that are not uncommon in other IoC tools or were present in previous versions of StructureMap.

+
    +
  • Xml configuration was removed for the 3.0 release.
  • +
  • Comprehensive attribute based configuration was also removed for the 3.0 release, but there is some very rudimentary support for attibute based +configuration
  • +
  • Complex Auto Factory support (this feature may be part of the StructureMap 4.0 release)
  • +
+ + +
+ +
+ + + +
+
+
@@ -163,6 +159,29 @@

Things StructureMap does not have

+ + diff --git a/generics/index.html b/generics/index.html new file mode 100644 index 0000000..2dfaa6c --- /dev/null +++ b/generics/index.html @@ -0,0 +1,306 @@ + + + + + + + + StructureMap - Generic Types + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
+ +
+ + +
+
+ + + + + +
+

Generic Types Edit on GitHub

+ +
+ +
+ +

StructureMap comes with some power abilities to exploit open generic types in .Net for extensibility +and flexible handling within your system.

+

Example 1: Visualizing an Activity Log

+

I worked years ago on a system that could be used to record and resolve customer support problems. Since it was very workflow heavy in its logic, +we tracked user and system activity as an event stream of small objects that reflected all the different actions or state changes +that could happen to an issue. To render and visualize the activity log to HTML, we used many of the open generic type capabilities shown in +this topic to find and apply the correct HTML rendering strategy for each type of log object in an activity stream.

+

Given a log object, we wanted to look up the right visualizer strategy to render that type of log object to html on the server side.

+

To start, we had an interface like this one that we were going to use to get the HTML for each log object:

+

public interface ILogVisualizer
{
    // If we already know what the type of log we have
    string ToHtml<TLog>(TLog log);

    // If we only know that we have a log object
    string ToHtml(object log);
}
+

So for an example, if we already knew that we had an IssueCreated object, we should be able to use StructureMap like this:

+

// Just setting up a Container and ILogVisualizer
var container = Container.For<VisualizationRegistry>();
var visualizer = container.GetInstance<ILogVisualizer>();

// If I have an IssueCreated lob object...
var created = new IssueCreated();

// I can get the html representation:
var html = visualizer.ToHtml(created);
+

If we had an array of log objects, but we do not already know the specific types, we can still use the more generic ToHtml(object) method like this:

+

var logs = new object[]
{
    new IssueCreated(),
    new TaskAssigned(),
    new Comment(),
    new IssueResolved()
};

// SAMPLE: using-visualizer-knowning-the-type
// Just setting up a Container and ILogVisualizer
var container = Container.For<VisualizationRegistry>();
var visualizer = container.GetInstance<ILogVisualizer>();

var items = logs.Select(visualizer.ToHtml);
var html = string.Join("<hr />", items);
+

The next step is to create a way to identify the visualization strategy for a single type of log object. We certainly could have done this +with a giant switch statement, but we wanted some extensibility for new types of activity log objects and even customer specific log types +that would never, ever be in the main codebase. We settled on an interface like the one shown below that would be responsible for +rendering a particular type of log object ("T" in the type):

+

public interface IVisualizer<TLog>
{
    string ToHtml(TLog log);
}
+

Inside of the concrete implementation of ILogVisualizer we need to be able to pull out and use the correct IVisualizer<T> strategy for a log type. We of course +used a StructureMap Container to do the resolution and lookup, so now we also need to be able to register all the log visualization strategies in some easy way. +On top of that, many of the log types were simple and could just as easily be rendered with a simple html strategy like this class:

+

public class DefaultVisualizer<TLog> : IVisualizer<TLog>
{
    public string ToHtml(TLog log)
    {
        return string.Format("<div>{0}</div>", log);
    }
}
+

Inside of our StructureMap usage, if we don't have a specific visualizer for a given log type, we'd just like to fallback to the default visualizer and proceed.

+

Alright, now that we have a real world problem, let's proceed to the mechanics of the solution.

+

Registering Open Generic Types

+

Let's say to begin with all we want to do is to always use the DefaultVisualizer for each log type. We can do that with code like this below:

+

[Fact]
public void register_open_generic_type()
{
    var container = new Container(_ =>
    {
        _.For(typeof(IVisualizer<>)).Use(typeof(DefaultVisualizer<>));
    });

    Debug.WriteLine(container.WhatDoIHave(@namespace: "StructureMap.Testing.Acceptance.Visualization"));

    container.GetInstance<IVisualizer<IssueCreated>>()
        .ShouldBeOfType<DefaultVisualizer<IssueCreated>>();

    Debug.WriteLine(container.WhatDoIHave(@namespace: "StructureMap.Testing.Acceptance.Visualization"));

    container.GetInstance<IVisualizer<IssueResolved>>()
        .ShouldBeOfType<DefaultVisualizer<IssueResolved>>();
}

+

With the configuration above, there are no specific registrations for IVisualizer<IssueCreated>. At the first request for that +interface, StructureMap will run through its "missing family policies", one of which is +to try to find registrations for an open generic type that could be closed to make a valid registration for the requested type. In the case above, +StructureMap sees that it has registrations for the open generic type IVisualizer<T> that could be used to create registrations for the +closed type IVisualizer<IssueCreated>.

+

Using the WhatDoIHave() diagnostics, the original state of the container for the visualization namespace is:

+
+===========================================================================================================================
+PluginType            Namespace                                         Lifecycle     Description                 Name     
+---------------------------------------------------------------------------------------------------------------------------
+IVisualizer<TLog>     StructureMap.Testing.Acceptance.Visualization     Transient     DefaultVisualizer<TLog>     (Default)
+===========================================================================================================================
+
+

After making a request for IVisualizer<IssueCreated>, the new state is:

+
+====================================================================================================================================================================================
+PluginType                    Namespace                                         Lifecycle     Description                                                                  Name     
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IVisualizer<IssueCreated>     StructureMap.Testing.Acceptance.Visualization     Transient     DefaultVisualizer<IssueCreated> ('548b4256-a7aa-46a3-8072-bd8ef0c5c430')     (Default)
+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IVisualizer<TLog>             StructureMap.Testing.Acceptance.Visualization     Transient     DefaultVisualizer<TLog>                                                      (Default)
+====================================================================================================================================================================================
+
+
+
+

Generic Registrations and Default Fallbacks

+

A powerful feature of generic type support in StructureMap is the ability to register specific handlers for some types, but allow +users to register a "fallback" registration otherwise. In the case of the visualization, some types of log objects may justify some +special HTML rendering while others can happily be rendered with the default visualization strategy. This behavior is demonstrated by +the following code sample:

+

[Fact]
public void generic_defaults()
{
    var container = new Container(_ =>
    {
        // The default visualizer just like we did above
        _.For(typeof(IVisualizer<>)).Use(typeof(DefaultVisualizer<>));

        // Register a specific visualizer for IssueCreated
        _.For<IVisualizer<IssueCreated>>().Use<IssueCreatedVisualizer>();
    });

    // We have a specific visualizer for IssueCreated
    container.GetInstance<IVisualizer<IssueCreated>>()
        .ShouldBeOfType<IssueCreatedVisualizer>();

    // We do not have any special visualizer for TaskAssigned,
    // so fall back to the DefaultVisualizer<T>
    container.GetInstance<IVisualizer<TaskAssigned>>()
        .ShouldBeOfType<DefaultVisualizer<TaskAssigned>>();
}

+

Connecting Generic Implementations with Type Scanning

+ +

For this example, I have two special visualizers for the IssueCreated and IssueResolved log types:

+

public class IssueCreatedVisualizer : IVisualizer<IssueCreated>
{
    public string ToHtml(IssueCreated log)
    {
        return "special html for an issue being created";
    }
}

public class IssueResolvedVisualizer : IVisualizer<IssueResolved>
{
    public string ToHtml(IssueResolved log)
    {
        return "special html for issue resolved";
    }
}
+

In the real project that inspired this example, we had many, many more types of log visualizer strategies and it +could have easily been very tedious to manually register all the different little IVisualizer<T> strategy types in a Registry class by hand. +Fortunately, part of StructureMap's type scanning support is the ConnectImplementationsToTypesClosing() +auto-registration mechanism via generic templates for exactly this kind of scenario.

+

In the sample below, I've set up a type scanning operation that will register any concrete type in the Assembly that contains the VisualizationRegistry +that closes IVisualizer<T> against the proper interface:

+

public class VisualizationRegistry : Registry
{
    public VisualizationRegistry()
    {
        // The main ILogVisualizer service
        For<ILogVisualizer>().Use<LogVisualizer>();

        // A default, fallback visualizer
        For(typeof(IVisualizer<>)).Use(typeof(DefaultVisualizer<>));

        // Auto-register all concrete types that "close"
        // IVisualizer<TLog>
        Scan(x =>
        {
            x.TheCallingAssembly();
            x.ConnectImplementationsToTypesClosing(typeof(IVisualizer<>));
        });

    }
}
+

If we create a Container based on the configuration above, we can see that the type scanning operation picks up the specific visualizers for +IssueCreated and IssueResolved as shown in the diagnostic view below:

+
+==================================================================================================================================================================================
+PluginType                     Namespace                                         Lifecycle     Description                                                               Name     
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ILogVisualizer                 StructureMap.Testing.Acceptance.Visualization     Transient     StructureMap.Testing.Acceptance.Visualization.LogVisualizer               (Default)
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IVisualizer<IssueResolved>     StructureMap.Testing.Acceptance.Visualization     Transient     StructureMap.Testing.Acceptance.Visualization.IssueResolvedVisualizer     (Default)
+                                                                                 Transient     DefaultVisualizer<IssueResolved>                                                   
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IVisualizer<IssueCreated>      StructureMap.Testing.Acceptance.Visualization     Transient     StructureMap.Testing.Acceptance.Visualization.IssueCreatedVisualizer      (Default)
+                                                                                 Transient     DefaultVisualizer<IssueCreated>                                                    
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IVisualizer<TLog>              StructureMap.Testing.Acceptance.Visualization     Transient     DefaultVisualizer<TLog>                                                   (Default)
+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+IVisualizer<TLog>              StructureMap.Testing.Acceptance.Visualization     Transient     DefaultVisualizer<TLog>                                                   (Default)
+==================================================================================================================================================================================
+
+
+

The following sample shows the VisualizationRegistry in action to combine the type scanning registration plus the default fallback behavior for +log types that do not have any special visualization logic:

+

[Fact]
public void visualization_registry()
{
    var container = Container.For<VisualizationRegistry>();

    Debug.WriteLine(container.WhatDoIHave(@namespace: "StructureMap.Testing.Acceptance.Visualization"));

    container.GetInstance<IVisualizer<IssueCreated>>()
        .ShouldBeOfType<IssueCreatedVisualizer>();

    container.GetInstance<IVisualizer<IssueResolved>>()
        .ShouldBeOfType<IssueResolvedVisualizer>();

    // We have no special registration for TaskAssigned,
    // so fallback to the default visualizer
    container.GetInstance<IVisualizer<TaskAssigned>>()
        .ShouldBeOfType<DefaultVisualizer<TaskAssigned>>();
}

+

Building Closed Types with ForGenericType() and ForObject()

+

Working with generic types and the common IHandler<T> pattern can be a little bit tricky if all you have is an object that is declared as an object. Fortunately, +StructureMap has a couple helper methods and mechanisms to help you bridge the gap between DoSomething(object something) and DoSomething<T>(T something).

+

If you remember the full ILogVisualizer interface from above:

+

public interface ILogVisualizer
{
    // If we already know what the type of log we have
    string ToHtml<TLog>(TLog log);

    // If we only know that we have a log object
    string ToHtml(object log);
}
+

The method ToHtml(object log) somehow needs to be able to find the right IVisualizer<T> and execute it to get the HTML representation for a log object. +The StructureMap IContainer provides two different methods called ForObject() and ForGenericType() for exactly this case, as shown below in a possible implementation +of ILogVisualizer:

+

public class LogVisualizer : ILogVisualizer
{
    private readonly IContainer _container;

    // Take in the IContainer directly so that
    // yes, you can use it as a service locator
    public LogVisualizer(IContainer container)
    {
        _container = container;
    }

    // It's easy if you already know what the log
    // type is
    public string ToHtml<TLog>(TLog log)
    {
        return _container.GetInstance<IVisualizer<TLog>>()
            .ToHtml(log);
    }

    public string ToHtml(object log)
    {
        // The ForObject() method uses the 
        // log.GetType() as the parameter to the open
        // type Writer<T>, and then resolves that
        // closed type from the container and
        // casts it to IWriter for you
        return _container.ForObject(log)
            .GetClosedTypeOf(typeof (Writer<>))
            .As<IWriter>()
            .Write(log);
    }

    public string ToHtml2(object log)
    {
        // The ForGenericType() method is again creating
        // a closed type of Writer<T> from the Container
        // and casting it to IWriter
        return _container.ForGenericType(typeof (Writer<>))
            .WithParameters(log.GetType())
            .GetInstanceAs<IWriter>()
            .Write(log);
    }

    // The IWriter and Writer<T> class below are
    // adapters to go from "object" to <T>() signatures
    public interface IWriter
    {
        string Write(object log);
    }

    public class Writer<T> : IWriter
    {
        private readonly IVisualizer<T> _visualizer;

        public Writer(IVisualizer<T> visualizer)
        {
            _visualizer = visualizer;
        }

        public string Write(object log)
        {
            return _visualizer.ToHtml((T) log);
        }
    }
}
+

The two methods are almost identical in result with some slight differences:

+
    +
  1. ForObject(object subject) can only work with open types that have only one generic type parameter, and it will pass the argument subject to the underlying Container as an explicit argument so that you can inject that subject object into the object graph being created.
  2. +
  3. ForGenericType(Type openType) is a little clumsier to use, but can handle any number of generic type parameters
  4. +
+

Example #2: Generic Instance Builder

+

As I recall, the following example was inspired by a question about how to use StructureMap to build out MongoDB MongoCollection objects from some sort of static builder or factory -- but I can't find the discussion on the mailing list as I write this today. This has come up often enough to justify its inclusion in the documentation.

+

Say that you have some sort of persistence tooling that you primarily interact with through an interface like this one below, where TDocument and TQuery are classes in +your persistent domain:

+

public interface IRepository<TDocument, TQuery>
{
}

+

Great, StructureMap handles generic types just fine, so you can just register the various closed types and off you go. Except you can't because the way that your +persistence tooling works requires you to create the IRepository<,> objects with a static builder class like this one below:

+

public static class RepositoryBuilder
{
    public static IRepository<TDocument, TQuery> Build<TDocument, TQuery>()
    {
        return new Repository<TDocument, TQuery>();
    }
}

+

StructureMap has an admittedly non-obvious way to handle this situation by creating a new subclass of Instance that will "know" how to create the real Instance for a closed +type of IRepository<,>.

+

First off, let's create a new Instance type that knows how to build a specific type of IRepository<,> by subclassing the LambdaInstance type and providing a Func to +build our repository type with the static RepositoryBuilder class:

+

public class RepositoryInstance<TDocument, TQuery> : LambdaInstance<IRepository<TDocument, TQuery>>
{
    public RepositoryInstance() : base(() => RepositoryBuilder.Build<TDocument, TQuery>())
    {
    }

    // This is purely to make the diagnostic views prettier
    public override string Description
    {
        get
        {
            return "RepositoryBuilder.Build<{0}, {1}>()"
                .ToFormat(typeof(TDocument).Name, typeof(TQuery).Name);
        }
    }
}

+

As you've probably surmised, the custom RepositoryInstance above is itself an open generic type and cannot be used directly until it has been closed. You could use this class directly if you have a very few document types like this:

+

var container = new Container(_ =>
{
    _.For<IRepository<string, int>>().UseInstance(new RepositoryInstance<string, int>());

    // or skip the custom Instance with:

    _.For<IRepository<string, int>>().Use(() => RepositoryBuilder.Build<string, int>());
});
+

To handle the problem in a more generic way, we can create a second custom subclass of Instance for the open type IRepository<,> that will help StructureMap understand how +to build the specific closed types of IRepository<,> at runtime:

+

public class RepositoryInstanceFactory : Instance
{
    // This is the key part here. This method is called by
    // StructureMap to "find" an Instance for a closed
    // type of IRepository<,>
    public override Instance CloseType(Type[] types)
    {
        // StructureMap will cache the object built out of this,
        // so the expensive Reflection hit only happens
        // once
        var instanceType = typeof(RepositoryInstance<,>).MakeGenericType(types);
        return Activator.CreateInstance(instanceType).As<Instance>();
    }

    // Don't worry about this one, never gets called
    public override IDependencySource ToDependencySource(Type pluginType)
    {
        throw new NotSupportedException();
    }

    public override string Description
    {
        get { return "Build Repository<T, T1>() with RepositoryBuilder"; }
    }

    public override Type ReturnedType
    {
        get { return typeof(Repository<,>); }
    }
}

+

The key part of the class above is the CloseType(Type[] types) method. At that point, we can determine the right type of RepositoryInstance<,> to build the requested type of IRepository<,>, then use some reflection to create and return that custom Instance.

+

Here's a unit test that exercises and demonstrates this functionality from end to end:

+

[Fact]
public void show_the_workaround_for_generic_builders()
{
    var container = new Container(_ =>
    {
        _.For(typeof(IRepository<,>)).Use(new RepositoryInstanceFactory());
    });

    container.GetInstance<IRepository<string, int>>()
        .ShouldBeOfType<Repository<string, int>>();

    Debug.WriteLine(container.WhatDoIHave(assembly: GetType().GetAssembly()));
}

+

After requesting IRepository<string, int> for the first time, the container configuration from Container.WhatDoIHave() is:

+
+===================================================================================================================================================
+PluginType                         Namespace                           Lifecycle     Description                                          Name     
+---------------------------------------------------------------------------------------------------------------------------------------------------
+IRepository<String, Int32>         StructureMap.Testing.Acceptance     Transient     RepositoryBuilder.Build<String, Int32>()             (Default)
+---------------------------------------------------------------------------------------------------------------------------------------------------
+IRepository<TDocument, TQuery>     StructureMap.Testing.Acceptance     Transient     Build Repository<T, T1>() with RepositoryBuilder     (Default)
+===================================================================================================================================================
+
+

Example 3: Interception Policy against Generic Types

+

Several years ago I described an approach for using an Event Aggregator in a WPF application that relied on StructureMap interception to register any object that +StructureMap built with the active EventAggregator for the system if that object was recognized as a listener to the event aggregator. I thought that approach worked out quite well, so let's talk about how you could implement +that same design with the improved interception model introduced by StructureMap 3.0 (the event aggregator and StructureMap interception worked out well, +but I'm very happy now that I ditched the old WPF client and replaced it with a web application using React.js instead).

+

First off, let's say that we're going to have this interface for our event aggregator:

+

public interface IEventAggregator
{
    // Sending messages
    void SendMessage<T>(T message);

    void SendMessage<T>() where T : new();

    // Explicit registration
    void AddListener(object listener);

    void RemoveListener(object listener);
}

+

To register a listener for a particular type of event notification, you would implement an interface called IListener<T> shown below +and directly add that object to the IEventAggregator:

+

public interface IListener<T>
{
    void Handle(T message);
}

+

In the application I'm describing, all of the listener objects were presenters or screen controls that were created by StructureMap, so it was convenient to allow StructureMap to register newly created objects with the IEventAggregator in an activation interceptor.

+

What we want to do though is have an interception policy that only applies to any concrete type that implements some interface that +closes IListener<T>:

+

public class EventListenerRegistration : IInterceptorPolicy
{
    public string Description
    {
        get { return "Adds the constructed object to the EventAggregator"; }
    }

    public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
    {
        if (instance.ReturnedType.FindInterfacesThatClose(typeof(IListener<>)).Any())
        {
            Expression<Action<IContext, object>> register =
                (c, o) => c.GetInstance<IEventAggregator>().AddListener(o);
            yield return new ActivatorInterceptor<object>(register);
        }
    }
}

+

To see our new interception policy in action, see this unit test from GitHub:

+

[Fact]
public void use_the_event_listener_registration()
{
    var container = new Container(x =>
    {
        x.Policies.Interceptors(new EventListenerRegistration());
        x.For<IEventAggregator>().Use<EventAggregator>().Singleton();
    });

    var events = container.GetInstance<IEventAggregator>();
    var listener = container.GetInstance<BooMessageListener>();

    var message = new BooMessage();

    events.SendMessage(message);

    listener.Messages.Single().ShouldBeTheSameAs(message);
}

+ +
+ +
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + diff --git a/get-structuremap/index.html b/get-structuremap/index.html index d988ff8..ae70601 100644 --- a/get-structuremap/index.html +++ b/get-structuremap/index.html @@ -1,151 +1,132 @@ - + - StructureMap - Get StructureMap - - - - - - - - - - + StructureMap - Get StructureMap + + + + + + + + + + + - + - + Fork me on GitHub - + + +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Get StructureMap Edit on GitHub

+ +
+ +
+ + +

Current Release

+

The current version of StructureMap will always be available on Nuget. See the Release Notes for more information.

+

Supported Platforms

+

The original StructureMap.dll has been broken up into a couple pieces. The main assembly will be targeting PCL compliance thanks to the diligent efforts of Frank Quednau, and that means that anything to do with ASP.Net or falls outside of the PCL core has been devolved into separate assemblies and eventually into different Nuget packages. This means that StructureMap 3.* will theoretically support WP8 and other versions of .Net for the very first time.

+

At this point StructureMap 3.* has been used on .Net 4, 4.5, WP8, and WP8.1.

+

StructureMap 4.5+ will not work on Xamarin iOS because it depends on System.Reflection.Emit, which is not available in MonoTouch. StructureMap 4.4 works for at least basic scenarios on that platform. Nobody in the core StructureMap team is currently working with Xamarin mobile runtimes, but we are interested in verifying StructureMap on new platforms if any volunteers are interested in helping us out.

+

Binaries

+

Binaries of StructureMap are available via NuGet:

+
PM> Install-Package StructureMap
+
+

or if you need a strong named version of StructureMap:

+
PM> Install-Package structuremap-signed
+
+

The StructureMap team believes strong naming to be a blight upon the .Net land and we really wish folks would quit using it, but we understand that some circumstances absolutely require it.

+

Source

+

StructureMap's source is hosted on GitHub. If you want to fix a bug or just want to tinker with an idea, we love receiving pull requests! Start by creating your own fork on Github.

+

The StructureMap build tooling has recently changed. See the GitHub README for more information on how to build and work with the StructureMap codebase.

+ +
+ +
+ + + +
+
+
@@ -159,6 +140,29 @@

Source

+ + diff --git a/glossary/index.html b/glossary/index.html index 999ebec..b129b57 100644 --- a/glossary/index.html +++ b/glossary/index.html @@ -1,305 +1,179 @@ - + - StructureMap - Glossary - - - - - - - - - - + StructureMap - Glossary + + + + + + + + + + + - + - + Fork me on GitHub - + + +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

Glossary Edit on GitHub

+ +
+ +
+ +

There are some terms that reoccur throughout the documentation and show up in the StructureMap API. Understanding these terms and how they relate to StructureMap isn't a prerequisite to using StructureMap, but it helps.

+

Container

+

Tools like StructureMap are generally known as Inversion of Control (IoC) Containers or Dependency Injection (DI) Containers. In the Java world they are also known as Lightweight Containers to differentiate them from the older EJB Containers.

+

A container is a tool that can help you composing object graphs and managing their scope (lifecycle). Altough you can do Inversion of Control and Dependency Injection manually, using tools like StructureMap makes you far more productive and succesfull in doing so.

+

Obviously there is more to a container than resolving services and managing their scope, but in the core that's just what it is. Before you can do so you need to tell StructureMap, the container, how it must compose those objects graphs and what their lifecycle is. This is called registration and can be done in various mixed ways. The strongly recommend way would be using the Registry DSL. In your registration you're basically mapping abstractions to concrete types and defining their lifecycle.

+

A simple example of a container using the Registry DSL:

+

public class FooBarRegistry : Registry
{
    public FooBarRegistry()
    {
        For<IFoo>().Use<Foo>();
        For<IBar>().Use<Bar>();
    }
}

+

var container = new Container(c => { c.AddRegistry<FooBarRegistry>(); });
+

Because we didn't specify the lifecycle for both registrations, the default Transient lifecycle will be used. This will instruct the container to create a new instance for every request for a plugin type IFoo or IBar.

+

More advanced features that the container can do are things like: Interception, Auto-Wiring, Forwarding Types.

+

Nested Container

+

A nested container is used to mark the scope of short lived transactions or web requests and track and clean up objects implementing the IDisposable interface for that operation.

+

You can ask an existing container to create a nested container for you like in the following example:

+

using (var nested = someExistingContainer.GetNestedContainer())
{
    // pull other objects from the nested container and do work with those services
    var service = nested.GetInstance<IService>();
    service.DoSomething();
}
+

For more detailed information about nested containers and their special properties you can read the Nested Containers (Per Request/Transaction) topic.

+

PluginType and PluggedType

+

The term plugin type is used throughout the code and documentation to mean the type that you want to register or resolve. More generally this type is known as the service type. This type can be a concrete class or in most cases, it will be a form of abstraction like an abstract class or interface.

+

The term plugged type means the actual concrete type that you get when you request the plugin type. This type must obviously implement the plugin type contract.

+

In your registration you could have something like this:

+

public class FooRegistry : Registry
{
    public FooRegistry()
    {
        For<IFoo>().Use<Foo>();
    }
}

+

//For<PLUGINTYPE>().Use<PLUGGEDTYPE>()

            var container = new Container(c => { c.AddRegistry<FooRegistry>(); });

            container.GetInstance<IFoo>();

//container.GetInstance<PLUGINTYPE>()
+

If you request an object of IFoo, you'll get an instance of the Foo class. In this case, IFoo is the plugin type (what you're asking for) and Foo is the plugged type (the concrete class you'll get that fulfills, implements the plugin type contract).

+

PluginFamily

+

This term you will not see so often because it's mostly used by StructureMap itself. A PluginFamily represents a CLR type (the plugin type) that StructureMap can build, and all of the possible plugged types that implement the CLR type.

+

In the following code StructureMap internally creates one PluginFamily of the plugin type IFoo with two instances Foo and SomeOtherFoo, where Foo is the default instance because it's registered through For<PLUGIN_TYPE>().Use<PLUGGED_TYPE>().

+

var container = new Container(c =>
{
    c.For<IFoo>().Use<Foo>();
    c.For<IFoo>().Add<SomeOtherFoo>();
});
+

Before StructureMap 3.0 you have probably seen the term used in an exception message when you request a plugin type that doesn't have a default instance defined.

+
StructureMap Exception Code:  202
+No Default Instance defined for PluginFamily [plugin type]
+
+

This specific exception message is gone in 3.0 because the exception messages were modernized.

+

Plugin Graph

+

A PluginGraph is the configuration model of the runtime configuration of a StructureMap container. The PluginGraph model can be manipulated directly in StructureMap 3.0 for +any kind of special convention that doesn't fit into the existing conventional support.

+

Instance

+

In StructureMap terms, an "Instance" is a configured and named strategy to build or locate a named object instance for a requested Plugin Type. An "Instance" does not automatically equate to a concrete type. For example, let's say that we're building a system to automate a warehouse. Our system might consume an interface called IShippingService that acts as a Gateway to various ways of shipping boxes out of our warehouse.

+

public interface IShippingService
{
    void ShipIt();
}

+

Our warehouse system might have to interact with three types of shipping: domestic, international, and intra-company or internal shipments. The internal shipping service runs in process with the warehouse application, but domestic and international shipping is done by invoking external web services. The registration of the IShippingService Instances might look like this:

+

public class ShippingRegistry : Registry
{
    public ShippingRegistry()
    {
        For<IShippingService>().AddInstances(x =>
        {
            x.Type<ShippingWebService>()
                .Ctor<string>("url").Is("a url")
                .Named("Domestic");

            x.Type<ShippingWebService>()
                .Ctor<string>("url").Is("a different url")
                .Named("International");

            x.Type<InternalShippingService>().Named("Internal");
        });
    }
}

+

In the registration code above, there are three "Instances." You can access the various IShippingService Instance's by name:

+

var container = new Container(new ShippingRegistry());

// Accessing the IShippingService Instance's by name
var internationalService = container.GetInstance<IShippingService>("International");
var domesticService = container.GetInstance<IShippingService>("Domestic");
var internalService = container.GetInstance<IShippingService>("Internal");

+

Asking for the "International" or the "Domestic" instance of IShippingService will both return an object of type ShippingWebService, but the two objects will be differently configured with unique Url's.

+

There is an actual class in StructureMap that represents an "Instance."

+

When you call Container.GetInstance<T>("the instance that I want") or Container.GetInstance<T>(), the internal Container object is locating the correct Instance object and then using the Instance's internal build plan to resolve or construct the actual object.

+

A StructureMap "Instance" is a close analogue for what many other IoC tools call a "Component."

+

Lifecycle (or Scope)

+

The power of an IoC container isn't just in building object graphs for you, it's also about scoping an object graph to what StructureMap calls a lifecycle. Think of it this way: +when you ask StructureMap for a service or (much more commonly) when StructureMap is filling a dependency behind the scenes, do you want:

+
    +
  • A brand new, unique object each time?
  • +
  • The exact same object as the rest of the graph is using?
  • +
  • The exact same object every single time throughout the application?
  • +
+

Registry

+

A Registry or a sub class of Registry is a class that let's you create reusable configuration for StructureMap containers.

+

Profile

+

StructureMap 3.0 features a complete rewrite of the ancient Profile functionality where you can create your base Container configuration with additional Profile +configuration that overrides one or more of the parent Container defaults. The Profile functionality was originally meant to handle differences between +development, testing, and production environments but has been more commonly used for multi-tenancy situations. Think of a Profile as an application or tenant mode.

+

Auto wiring

+

You'd never get anything done if you had to tell StructureMap how to build each and every constructor or setter dependency on every concrete class. Fortunately, StructureMap like +most IoC container tools, supports the concept of auto-wiring -- meaning that StructureMap can happily infer dependency requirements from constructor functions and setter +rules and fill those dependencies with the default configuration for the declared dependency type.

+

Let's just see it in action:

+

public interface Xman
{
}

public class Cyclops : Xman
{
}

public interface Avenger
{
}

public class IronMan : Avenger
{
}

public class CrossoverEvent
{
    public Xman Xman { get; set; }
    public Avenger Avenger { get; set; }

    public CrossoverEvent(Xman xman, Avenger avenger)
    {
        Xman = xman;
        Avenger = avenger;
    }
}

public class UsingCrossover
{
    [Fact]
    public void showing_auto_wiring()
    {
        var container = new Container(x =>
        {
            x.For<Xman>().Use<Cyclops>();
            x.For<Avenger>().Use<IronMan>();
        });

        // Notice that at no point did we define how to
        // build CrossoverEvent.
        var @event = container.GetInstance<CrossoverEvent>();
        @event.Avenger.ShouldBeOfType<IronMan>();
        @event.Xman.ShouldBeOfType<Cyclops>();
    }
}

+ +
+ +
+ + + +
+
+
@@ -313,6 +187,29 @@

Auto wiring

+ + diff --git a/history/index.html b/history/index.html index 1b233bf..d36313f 100644 --- a/history/index.html +++ b/history/index.html @@ -1,127 +1,125 @@ - + - StructureMap - History - - - - - - - - - - + StructureMap - History + + + + + + + + + + + - + - + Fork me on GitHub - + + +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ + +
+

History Edit on GitHub

+ +
+ +
+ + +

StructureMap was originally conceived in 2002 as the world's greatest object/relational mapping tool (and frankly a way for me to +prove to prospective employers that I could actually code so I could move on from my non-coding architect position at that time). +What exists today is the descendent of the overly grandiose configuration subsystem for that failed ORM concept (hence the name "StructureMap").

+

StructureMap was resurrected in the spring of 2004 as an "Inversion of Control" tool after I read about the http://picocontainer.codehaus.org IoC tool written in Java by several folks at my company at that time. In June of 2004 StructureMap went into its first production application and was also publicly +released on the old Sourceforge.net website. As such, StructureMap is the oldest, continuously used IoC tool for .Net development.

+

The current release (3.*) represents the lessons learned from over 10 years of usage and other than a handful of class names bears very little +internal resemblance to the original codebase.

+

StructureMap moved to GitHub in 2010 and is now distributed via Nuget.

+

To learn more about the StructureMap journey, see the Joys and Pains of a Long Lived Codebase on InfoQ from QCon 2008, or check out +Jeremy Miller's updated retrospective talk at CodeMash 2015.

+ +
+ +
+ + + +
+
+
@@ -135,6 +133,29 @@

History

+ + diff --git a/index.html b/index.html index 3d5cd57..e7e693c 100644 --- a/index.html +++ b/index.html @@ -9,6 +9,7 @@ StructureMap + @@ -34,8 +35,15 @@
  • Join the chat at https://gitter.im/structuremap/structuremap
  • +
  • + Edit on GitHub +
  • - +
    @@ -47,7 +55,7 @@

    StructureMap

    StructureMap is the oldest, continuously used IoC/DI container for .Net dating back to its first public release and production usage all the way back in June 2004 on .Net 1.1. -The current 3.* release represents 10+ years of lessons learned in the StructureMap and greater .Net community -- while also wiping away a great deal of legacy design +The current 4.* release represents 12+ years of lessons learned in the StructureMap and greater .Net community -- while also wiping away a great deal of legacy design decisions that no longer make sense today.

    Learn more »

    @@ -83,7 +91,28 @@

    Integrations

    + diff --git a/instances/index.html b/instances/index.html new file mode 100644 index 0000000..ab22c0b --- /dev/null +++ b/instances/index.html @@ -0,0 +1,161 @@ + + + + + + + + StructureMap - Custom Instance Types + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Custom Instance Types Edit on GitHub

    + +
    + +
    + +

    Most users will never need to implement a custom Instance type, but it does come up here and there. The easiest way is probably to +subclass LambdaInstance as shown below:

    +
    
    public class FuncInstance<T> : LambdaInstance<Func<T>>
    {
        // Pass a Func<IContext, T> into the base constructor
        // Use a static method for cleaner syntax to avoid the 
        // nasty Lambda syntax formatting as needed
        public FuncInstance() : base(s => s.GetInstance<IContainer>().GetInstance<T>)
        {
        }
    
        public override string Description
        {
            get { return "Constructor for Func<{0}>".ToFormat(typeof (T).Name); }
        }
    }
    
    +

    The other common customization is as a generic builder template

    +

    If neither of these approaches will easily work for your custom Instance, you may want to contact the StructureMap team +via the gitter link above and we can help walk you through a custom subclass of Instance -- or more likely, talk you out +of it somehow.

    +

    Missing Name Instance Template

    +

    New to StructureMap 4.0 is the Instance.ToNamedClone(name) method that is used behind the scenes by the Handling Missing Named Instances feature.

    +
    
    public virtual Instance ToNamedClone(string name)
    
    +

    Custom Instance types can override this method to provide a brand new Instance for a name. This functionality may be useful for multi-tenancy situations.

    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/integrations/index.html b/integrations/index.html index 9413184..2199255 100644 --- a/integrations/index.html +++ b/integrations/index.html @@ -1,128 +1,138 @@ - + - StructureMap - Integrating StructureMap into Common .Net Frameworks - - - - - - - - - - + StructureMap - Integrating StructureMap into Common .Net Frameworks + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Integrating StructureMap into Common .Net Frameworks Edit on GitHub

    + +
    + +
    + +

    Want to see more integrations or samples of how to integrate StructureMap with various .Net development tools? Let us know in Gitter or Github, or better yet, we take pull requests for documentation.

    +

    ASP.NET MVC 5

    +

    The StructureMap team recommends the StructureMap.MVC5 NuGet package for integrating +StructureMap into ASP.NET MVC. The design is necessarily odd to work around ASP.NET limitations, but you do get the all +important "nested container per HTTP request" pattern that we recommend.

    +

    ASP.NET Web API

    +

    The easiest way to integrate StructureMap with ASP.NET Web API is with the WebApi.StructureMap NuGet package. This package requires StructureMap 4.1 or higher. +Use the StructureMap.WebApi2 NuGet package for older versions of StructureMap or combined ASP.NET MVC and Web API projects where you already use the StructureMap.MVC5 NuGet package.

    +

    ASP.NET Core

    +

    See the StructureMap.Microsoft.DependencyInjection project and NuGet package for integration with ASP.NET Core.

    +

    NServiceBus

    +

    Use the NServiceBus StructureMap NuGet package for integrating StructureMap 3 into +NServiceBus.

    +

    NancyFx

    +

    NancyFx provides the Nancy.Bootstrappers.StructureMap NuGet package. The early +versions of the NancyFx integration with StructureMap were deeply flawed but improved in later versions, so do make sure that you are using the latest version of the bootstrapper.

    +

    MassTransit

    +

    Use the MassTransit.StructureMap NuGet package. Unfortunately, this package +depends on the signed version of StructureMap, so prepare yourself for version conflicts, +binding redirects, and the fusion log viewer. See the MassTransit documentation on using StructureMap for more information.

    +

    Entity Framework

    +

    The best example is this blog post from Jimmy Bogard.

    +

    AutoMapper

    +

    See My AutoMapper setup for StructureMap from Martijn Burgers.

    + +
    + +
    + + + +
    +
    +
    @@ -136,6 +146,29 @@

    Integrating StructureMap into Common .Net Frameworks

    + + diff --git a/interception-and-decorators/index.html b/interception-and-decorators/index.html index 8a99dcc..8911a77 100644 --- a/interception-and-decorators/index.html +++ b/interception-and-decorators/index.html @@ -1,131 +1,244 @@ - + - StructureMap - Interception and Decorators - - - - - - - - - - + StructureMap - Interception and Decorators + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Interception and Decorators Edit on GitHub

    + +
    + +
    + + +

    All of the samples from this topic are part of the user acceptance tests in the main codebase. There is also another example of using an interception policy with +open generic types at the bottom of Generic Types

    +

    Improving the interception facilities and the means of applying decorators during object construction was one of the primary +goals of the big 3.0 release and is significantly different than the older 2.5/2.6 model.

    +

    Interception in StructureMap really comes +in two basic flavors:

    +
      +
    1. Activates - Do some action on or with an object just created or resolved by StructureMap
    2. +
    3. Decorates - Wrap (or optionally replace) an object just created with either a dynamic proxy or some sort of decorator
    4. +
    +

    Interceptors can be configured explicitly on a single Instance registration, on all registrations to a PluginFamily, or conventionally +to any concrete type implementing an interface, inheriting from a certain base class, or by some sort of user-supplied +criteria.

    +

    Any type of Instance can be intercepted, meaning that even object literal values supplied to StructureMap at registration can be +intercepted when they are resolved as dependencies or through service location calls.

    +

    See the Glossary for a refresher on terms like Instance and PluginFamily.

    +

    Also see Working with the IContext at Build Time for more information about using the Container state within interception.

    +

    Activation Interceptors

    +

    For right now, all activation interceptors are either using or subclassing the ActivatorInterceptor<T> class.

    +

    This class has two constructor functions that interest us:

    +

    To create an activator interceptor that acts on an object that can be cast to type T:

    +
    
    public ActivatorInterceptor(Expression<Action<T>> action, string description = null)
    
    +

    To create an activator interceptor that acts on an object that can be cast to type T and +also uses the IContext service supplied by StructureMap itself.

    +
    
    public ActivatorInterceptor(Expression<Action<IContext, T>> action, string description = null)
    {
        _action = action;
        _description = description;
    }
    
    +

    In both cases, the description is optional and is only used for diagnostic purposes in the build plan visualization. If +omitted, StructureMap tries to do a ToString() on the Expression for the description and that frequently suffices to understand what's going on in the build plan.

    +

    Please note that the Lambda supplied to ActivatorInterceptor<T> must be a .Net Expression so cannot be a multi-line Lambda. +You can get around this limitation for more complex activation needs by simply making a wrapping method and using that +to express the activation.

    +

    Decorators

    +

    To demonstrate a decorator in action, say that we have an interface called IWidget, and when we build any instance +of IWidget we want those objects decorated by another type of IWidget that I clumsily named WidgetHolder in the +acceptance tests:

    +
    
    public class WidgetHolder : IWidget
    {
        private readonly IWidget _inner;
    
        public WidgetHolder(IWidget inner)
        {
            _inner = inner;
        }
    
        public IWidget Inner
        {
            get { return _inner; }
        }
    }
    
    
    +

    Now, to see the decorator mechanism in action:

    +
    
    [Fact]
    public void decorator_example()
    {
        var container = new Container(_ =>
        {
            // This usage adds the WidgetHolder as a decorator
            // on all IWidget registrations and makes AWidget
            // the default
            _.For<IWidget>().DecorateAllWith<WidgetHolder>();
            _.For<IWidget>().Use<AWidget>();
        });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<WidgetHolder>()
            .Inner.ShouldBeOfType<AWidget>();
    }
    
    
    +

    In effect, doing a decorator this way has the same effect (and build plan) as:

    +
    
    var container = new Container(_ =>
    {
        _.For<IWidget>().Use<WidgetHolder>()
            .Ctor<IWidget>().Is<AWidget>();
    });
    
    +

    Custom Decorator Interceptors

    +

    The simplest usage is to just declare a type that will be the decorating type like we did above, but if you need some +other mechanism for decorators like runtime AOP interception or you want to build the decorating object yourself, StructureMap +provides the FuncInterceptor<T> type where T is the type you want to decorate.

    +

    These objects can be created in two ways, by a user-supplied Expression<Func<T, T>> and optional description:

    +
    
    public FuncInterceptor(Expression<Func<T, T>> expression, string description = null)
    
    +

    and by a user-supplied Expression<Func<IContext, T, T>> and optional description.

    +
    
    public FuncInterceptor(Expression<Func<IContext, T, T>> expression, string description = null)
    
    +

    In both cases, the description field is only used for diagnostic purposes.

    +

    Interception Policies

    +

    The Registry DSL includes shorthand methods for the most common ways of configuring decorators +and activators by an individual Instance or by matching on implementing types. For more customized interception policies +that don't fit these mechanisms, StructureMap allows you to directly define an interception policy with a class +implementing this interface below:

    +
    
    public interface IInterceptorPolicy : IDescribed
    {
        IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance);
    }
    
    +

    For a simple example, let's say that we want to decorate any IWidget object with the +WidgetHolder class from earlier. We could build a small custom interceptor policy +like this one:

    +
    
    public class CustomInterception : IInterceptorPolicy
    {
        public string Description
        {
            get { return "good interception policy"; }
        }
    
        public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
        {
            if (pluginType == typeof(IWidget))
            {
                // DecoratorInterceptor is the simple case of wrapping one type with another
                // concrete type that takes the first as a dependency
                yield return new DecoratorInterceptor(typeof(IWidget), typeof(WidgetHolder));
            }
        }
    }
    
    
    +

    To use this custom interception policy, use the Policies.Interceptor() methods like this example:

    +
    
    [Fact]
    public void use_a_custom_interception_policy()
    {
        var container = new Container(x =>
        {
            x.Policies.Interceptors(new CustomInterception());
    
            x.For<IWidget>().Use<AWidget>();
        });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<WidgetHolder>()
            .Inner.ShouldBeOfType<AWidget>();
    }
    
    
    +

    As a helper for creating your own interception policies, you can also use the InterceptorPolicy<T> base class +to conventionally apply some sort of IInterceptor to any number of Instance's:

    +
    
    public InterceptorPolicy(IInterceptor interceptor, Func<Instance, bool> filter = null)
    
    +

    Here's an example of InterceptorPolicy<T> in usage from the acceptance tests:

    +
    
    [Fact]
    public void apply_policy_selectively_with_a_func()
    {
        var activator1 = new ActivatorInterceptor<ITarget>(x => x.Activate());
        var policy = new InterceptorPolicy<ITarget>(activator1, i => i.Name.StartsWith("A"));
    
        var container = new Container(x =>
        {
            x.Policies.Interceptors(policy);
            x.For<ITarget>().AddInstances(targets =>
            {
                targets.Type<ATarget>().Named("A");
                targets.Type<ATarget>().Named("A1");
                targets.Type<ATarget>().Named("A2");
                targets.Type<ATarget>().Named("B");
                targets.Type<ATarget>().Named("C");
                targets.Type<ATarget>().Named("D");
            });
        });
    
        container.GetInstance<ITarget>("A").ShouldBeOfType<ATarget>().WasActivated.ShouldBeTrue();
        container.GetInstance<ITarget>("A1").ShouldBeOfType<ATarget>().WasActivated.ShouldBeTrue();
        container.GetInstance<ITarget>("A2").ShouldBeOfType<ATarget>().WasActivated.ShouldBeTrue();
        container.GetInstance<ITarget>("B").ShouldBeOfType<ATarget>().WasActivated.ShouldBeFalse();
        container.GetInstance<ITarget>("C").ShouldBeOfType<ATarget>().WasActivated.ShouldBeFalse();
        container.GetInstance<ITarget>("D").ShouldBeOfType<ATarget>().WasActivated.ShouldBeFalse();
    }
    
    public class ATarget : ITarget
    {
        public void Activate()
        {
            WasActivated = true;
        }
    
        public bool WasActivated { get; set; }
    
        public void Debug()
        {
            throw new NotImplementedException();
        }
    }
    
    
    +

    Some quick things to note:

    +
      +
    1. For decorator interceptors, InterceptorPolicy<T> will only apply if the pluginType matches T
    2. +
    3. For activation interceptors, InterceptorPolicy<T> will apply to any concrete type returned by an Instance that can be +cast to T
    4. +
    +

    Apply Activation Interception by Type

    +

    Let's say that in your system you have a marker interface or in this case an abstract class that exposes a single +Activate() method to start up stateful, long-running services created within your container:

    +
    
    public abstract class Activateable
    {
        public bool Activated { get; set; }
    
        public void Activate()
        {
            Activated = true;
        }
    }
    
    
    +

    An implementation of Activateable from StructureMap's unit tests is shown below:

    +
    
    public class AWidget : Activateable, IWidget
    {
    }
    
    
    +

    If you decide that you'd like StructureMap to call the Activate() method on any object it creates as +part of its object creation and resolution process, we can register an interception policy in a Registry +like this:

    +
    
    [Fact]
    public void activate_by_action()
    {
        var container = new Container(x =>
        {
            x.For<IWidget>().Use<AWidget>();
            x.For<Activateable>()
                .OnCreationForAll("Mark the object as activated", o => o.Activated = true);
        });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<AWidget>()
            .Activated.ShouldBeTrue();
    }
    
    
    +

    There are several overloads of OnCreationForAll() covering cases with and without IContext

    +

    Apply Decoration across a Plugin Type

    +

    As shown above, you can use the Registry.For<T>().DecorateAllWith<TDecorator>() to apply decorators to all Instance's +registered to a Plugin Type:

    +
    
    [Fact]
    public void decorate_with_type()
    {
        var container = new Container(x =>
        {
            x.For<IWidget>().DecorateAllWith<WidgetHolder>();
            x.For<IWidget>().Use<AWidget>();
        });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<WidgetHolder>()
            .Inner
            .ShouldBeOfType<AWidget>();
    }
    
    
    +

    There are also several other overloads of DecorateAllWith() for user supplied expressions, filters, and descriptions. See the +acceptance tests for interception in the StructureMap codebase for many more sample usages.

    +

    Add Interception to a Single Instance

    +

    You can also define interceptors directly to individual Instance's inside of a StructureMap Registry using the +OnCreation() and DecorateWith methods or the more generic Instance.AddInterceptor() method. Here is some sample +usage from StructureMap's unit tests on interception:

    +
    
    _container = new Container(r =>
    {
        r.For<ContextRecorder>().Use(recorder);
    
        r.For<IService>().AddInstances(x =>
        {
            x.Type<ColorService>()
                // Registers an activation action on this Instance
                .OnCreation("last service", s => _lastService = s)
                .Named("Intercepted")
                .Ctor<string>("color").Is("Red");
    
            x.Type<ColorService>()
                // Activation using IContext
                .OnCreation("last touched", (c, s) => c.GetInstance<ContextRecorder>().WasTouched = true)
                .Named("InterceptedWithContext")
                .Ctor<string>("color").Is("Red");
    
            x.Type<ColorService>()
                .Named("NotIntercepted")
                .Ctor<string>("color").Is("Blue");
    
            x.Object(new ColorService("Yellow"))
                .Named("Yellow")
                .OnCreation("set the last service", s => _lastService = s);
    
            x.ConstructedBy(() => new ColorService("Purple")).Named("Purple")
                // Applies a decorator to this instance. Not sure *why*
                // you'd want to do it this way
                .DecorateWith(s => new DecoratorService(s));
    
            x.ConstructedBy(() => new ColorService("Purple")).Named("DecoratedWithContext")
                // Fancier decorator
                .DecorateWith("decorated with context", (c, s) =>
                {
                    c.GetInstance<ContextRecorder>().WasTouched = true;
                    return new DecoratorService(s);
                });
    
            x.Type<ColorService>().Named("Decorated").DecorateWith(
                s => new DecoratorService(s))
                .Ctor<string>("color").Is("Orange");
    
            x.Object(new ColorService("Yellow")).Named("Bad")
                .OnCreation("throw exception", obj => { throw new Exception("Bad!"); });
        });
    
    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Interpreting Exceptions

    -

    Previous

    Object Lifecycles

    - - -
    - - -
    -

    Interception and Decorators

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Interpreting Exceptions Edit on GitHub

    + +
    + +
    + + +

    Improving the exception messages was one of the primary goals of the big StructureMap 3.0 release. StructureMap exceptions should +show a "StructureMap-specific stacktrace" describing where in the object graph StructureMap was when an exception occurred, while +trying hard not to obscure the actual problems. In some cases, StructureMap will append diagnostic views +to the exception output. If you are still using StructureMap 2.5-2.6, the better exception messages alone are a justification for upgrading.

    +

    StructureMap throws a couple custom exceptions, all of which implement a base StructureMapException type:

    +
      +
    1. StructureMapBuildException -- a failure was detected during an attempt to build or resolve a requested object or dependency, but outside of +StructureMap code. This exception wraps the actual exception and adds StructureMap-specific contextual information. Always check the inner +exception when this exception is thrown.
    2. +
    3. StructureMapInterceptorException -- a configured interceptor failed during object construction. See the inner exception.
    4. +
    5. StructureMapBuildPlanException -- StructureMap is missing some kind of configuration or needs more explicit registrations in order to +build an Instance. In a few cases, this exception will be thrown if StructureMap cannot create and compile a Func internally for the +Instance.
    6. +
    7. StructureMapConfigurationException -- thrown by the container validation mechanism
    8. +
    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Diagnostics

    -

    Previous

    Interception and Decorators

    - - -
    - - -
    -

    Interpreting Exceptions

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Configuring Lifecycles Edit on GitHub

    + +
    + +
    + + +

    Unless designated otherwise, StructureMap uses Transient as the default scope for all configured Instance's.

    + +

    The resolution of the lifecycle for any given Instance is to check:

    +
      +
    1. Use the explicitly configured lifecycle for the Instance
    2. +
    3. If no lifecycle is configured for the Instance, use the explicitly configured lifecycle for the Plugin Type
    4. +
    5. If no lifecycle is configured for either the Instance or the Plugin Type, use the default Transient lifecycle
    6. +
    +

    The lifecycle precedence rules and the syntax for configuring object lifecycles are shown below:

    +
    
    [Fact]
    public void lifecycle_precedence()
    {
        var container = new Container(x =>
        {
            x.For<IWidget>().Use<AWidget>();
    
            // Configure the default lifecycle for
            // a PluginType (Rule)
            x.For<Rule>().Singleton();
            x.For<Rule>().Add<ARule>().Named("C");
    
            // Configure the lifecycle for a single Instance
            x.For<Rule>().Add<ARule>().Named("A").Transient();
            x.For<Rule>().Add<ARule>().Named("B").AlwaysUnique();
        });
    
        // The default lifecycle is Transient
        container.Model.For<IWidget>().Default
            .Lifecycle.ShouldBeOfType<TransientLifecycle>();
    
        // Override at the Family
        container.Model.For<Rule>().Lifecycle.ShouldBeOfType<SingletonLifecycle>();
        container.Model.For<Rule>().Find("C").Lifecycle.ShouldBeOfType<SingletonLifecycle>();
    
        // 'C' is the default lifecycle for Rule (SingletonThing)
        container.GetInstance<Rule>("C")
            .ShouldBeTheSameAs(container.GetInstance<Rule>("C"));
    
        // 'A' is a transient
        container.GetInstance<Rule>("A")
            .ShouldNotBeTheSameAs(container.GetInstance<Rule>("A"));
    
        using (var nested = container.GetNestedContainer())
        {
            // 'B' is always unique
            nested.GetInstance<Rule>("B")
                .ShouldNotBeTheSameAs(nested.GetInstance<Rule>("B"));
        }
    }
    
    
    +

    Using Attributes

    +

    New in StructureMap 4.0 are some simple attributes to mark either a complete Plugin Type or a single Instance as either +a singleton or using the always unique lifecycle:

    +

    The usage is shown below:

    +
    
    [AlwaysUnique]
    public interface IShouldBeUnique { }
    
    [Singleton] // because the most wonderful thing about Tiggers is that I'm the only one....
    public class Tigger { }
    
    
    +

    See Using Attributes for Configuration for information about adding your own custom attibutes for other lifecycles.

    + +
    + +
    + + + +
    +
    +
    @@ -177,6 +139,29 @@

    Configuring Lifecycles

    + + diff --git a/object-lifecycle/custom-lifecycles/index.html b/object-lifecycle/custom-lifecycles/index.html index c8931b8..24ca822 100644 --- a/object-lifecycle/custom-lifecycles/index.html +++ b/object-lifecycle/custom-lifecycles/index.html @@ -1,161 +1,120 @@ - + - StructureMap - Custom Lifecycles - - - - - - - - - - + StructureMap - Custom Lifecycles + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Custom Lifecycles Edit on GitHub

    + +
    + +
    + + +

    Lifecycles in StructureMap are pluggable. To create your own custom lifecycle, make an implementation of the ILifecycle interface like this one:

    +
    
    public class CustomLifecycle : ILifecycle
    {
        public static LifecycleObjectCache Cache = new LifecycleObjectCache();
    
        public string Description
        {
            get { return "Custom"; }
        }
    
        public void EjectAll(ILifecycleContext context)
        {
            // Here you'd remove all the existing objects
            // from the cache and call IDisposable.Dispose()
            // as appropriate
        }
    
        public IObjectCache FindCache(ILifecycleContext context)
        {
            // using the context, "find" the appropriate
            // IObjectCache object
            return Cache;
        }
    }
    
    
    +

    Registering your custom lifecycle can be done like this:

    +
    
    public class UsingCustomLifecycle : Registry
    {
        public UsingCustomLifecycle()
        {
            // at the Plugin Type level
            For<IService>().LifecycleIs<CustomLifecycle>();
    
            // at the Instance level
            For<IService>().Use<AService>()
                .LifecycleIs<CustomLifecycle>();
        }
    }
    
    
    +

    Most of the built in ILifecycle implementations use LifecycleObjectCache internally, but you may also need to create your own IObjectCache implementation.

    + +
    + +
    + + + +
    +
    +
    @@ -169,6 +128,29 @@

    Custom Lifecycles

    + + diff --git a/object-lifecycle/index.html b/object-lifecycle/index.html index da8b376..694ac48 100644 --- a/object-lifecycle/index.html +++ b/object-lifecycle/index.html @@ -1,189 +1,133 @@ - + - StructureMap - Object Lifecycles - - - - - - - - - - + StructureMap - Object Lifecycles + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Object Lifecycles Edit on GitHub

    + +
    + +
    + + +

    One of the most valuable functions of using an IoC container tool is its ability to manage the object lifecycle (creating and disposing objects) and scoping (shared objects) +of your system's services so you can focus on the actual functionality instead of busy work.

    +

    Some services like data cache's and event aggregators in your system will need to be shared across requests, screens, and handlers. +Other services should be created new every time you ask the container for one. Another set of services need to be scoped to an HTTP request or a logical transaction such that +every request to the container for a service originating within the context of a single HTTP request gets the same object instance.

    +

    In all the cases above, StructureMap will assemble object graphs for you using the correct scoping of each dependency. Likewise, in some cases, StructureMap can help you +with object cleanup by calling IDisposable.Dispose() as appropriate when an object lifecyle is completed.

    + + +

    Motivation for Container Managed Scope

    +

    In the bad old days, we used the infamous Singleton pattern +as shown below for objects that really needed to be scoped as one single instance for the entire system:

    +
    
    public class EvilSingleton
    {
        public static readonly EvilSingleton Instance = new EvilSingleton();
    
        private EvilSingleton()
        {
        }
    
        public void DoSomething()
        {
            // do something with the static data here
        }
    }
    
    
    public class EvilSingletonUser
    {
        public void DoWork()
        {
            EvilSingleton.Instance.DoSomething();
        }
    }
    
    
    +

    The code above isn't terribly difficult to write or understand, but using a Singleton has some negative effects on your code as explained in Singletons are Evil and my own writing at Chill out on the Singleton Fetish.

    +

    Instead, let's just use StructureMap to handle the singleton scoping instead and rewrite the code sample above as:

    +
    
    public class SingletonService { }
    
    public class SingletonUser
    {
        public SingletonUser(SingletonService singleton)
        {
        }
    }
    
    public class SingletonScopeRegistry : Registry
    {
        public SingletonScopeRegistry()
        {
            For<SingletonService>().Singleton();
        }
    }
    
    +

    The big advantage to the second, StructureMap-managed singleton scoping is that my DependencyUser class does not have to have any knowledge of +how the ISingletonDependency object is built and certainly no coupling to the hard Singleton mechanics from the first sample that was so harmful in the past.

    + +
    + +
    + + + +
    +
    +
    @@ -197,6 +141,29 @@

    Motivation for Container Managed Scope

    + + diff --git a/object-lifecycle/supported-lifecycles/index.html b/object-lifecycle/supported-lifecycles/index.html index ca13c52..904343d 100644 --- a/object-lifecycle/supported-lifecycles/index.html +++ b/object-lifecycle/supported-lifecycles/index.html @@ -1,463 +1,156 @@ - + - StructureMap - Supported Lifecycles - - - - - - - - - - + StructureMap - Supported Lifecycles + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Supported Lifecycles Edit on GitHub

    + +
    + +
    + + +

    Out of the box, the core StructureMap assembly supports these lifecycles:

    +
      +
    • Transient -- The default lifecycle. A new object is created for each logical request to resolve an object graph from the container.
    • +
    • Singleton -- Only one object instance will be created for the container and any children or nested containers created by that container
    • +
    • ContainerScoped -- Only one object instance will be created for unique root, child, or nested container
    • +
    • AlwaysUnique -- A new object instance is created every time, even within the same object graph
    • +
    • ThreadLocal -- Only one object instance will be created for the currently executing Thread
    • +
    +

    Transient

    +

    Older versions of StructureMap referred to Transient as PerRequest, which might be a more accurate reflection of how this lifecycle behaves but +causes some confusion with ASP.NET HTTP scoping. The easiest way to think of Transient is that a single object instance will be created for each top level +call to Container.GetInstance() (or any other object resolution method on the IContainer interface). Transient objects resolved from a nested container, Transients are scoped to the lifecycle +of the nested container itself. See Nested Containers (Per Request/Transaction) for more information.

    +

    StructureMap's behavior for transient objects that implement IDisposable changed in 4.0 to introduce an "opt-in" tracking mode. Please see StructureMap and IDisposable for the details.

    +

    The following unit test demonstrates how Transient lifecycles work in both root and nested containers.

    +
    
    [Fact]
    public void Transient()
    {
        var c = new Container(x => { x.For<IService>().Use<Service>().Transient(); });
    
        // In a normal container, you get a new object
        // instance of the Service class in subsequent
        // requests
        c.GetInstance<IService>()
            .ShouldNotBeTheSameAs(c.GetInstance<IService>())
            .ShouldNotBeTheSameAs(c.GetInstance<IService>());
    
        // Within a nested container, 'Transient' now
        // means within the Nested Container.
        // A nested container is effectively one request
        using (var nested = c.GetNestedContainer())
        {
            nested.GetInstance<IService>()
                .ShouldBeTheSameAs(nested.GetInstance<IService>())
                .ShouldBeTheSameAs(nested.GetInstance<IService>());
        }
    }
    
    
    +

    Also note that a transient dependency will +be created exactly once in an object graph resolved from IContainer.GetInstance(Type). Imagine that you are building an +object graph with various objects that all need to apply some work to a shared unit of work object (think NHibernate's ISession, Entity Framework's DbContext, RavenDb's IDocumentSession):

    +
    
    public interface IUnitOfWork
    {
    }
    
    public class DefaultUnitOfWork : IUnitOfWork
    {
    }
    
    public class Worker1
    {
        public IUnitOfWork Uow { get; set; }
    
        public Worker1(IUnitOfWork uow)
        {
            Uow = uow;
        }
    }
    
    public class Worker2
    {
        public IUnitOfWork Uow { get; set; }
    
        public Worker2(IUnitOfWork uow)
        {
            Uow = uow;
        }
    }
    
    public class WorkerCoordinator
    {
        public IUnitOfWork Uow { get; set; }
        public Worker1 Worker1 { get; set; }
        public Worker2 Worker2 { get; set; }
    
        public WorkerCoordinator(IUnitOfWork uow, Worker1 worker1, Worker2 worker2)
        {
            Uow = uow;
            Worker1 = worker1;
            Worker2 = worker2;
        }
    }
    
    [Fact]
    public void transient_scoped_Instance_is_built_once_per_resolution_to_the_Container()
    {
        var container = new Container(_ => { _.For<IUnitOfWork>().Use<DefaultUnitOfWork>(); });
    
        var coordinator = container.GetInstance<WorkerCoordinator>();
    
        // The IUnitOfWork object instance is the same for
        // all the objects in the object graph that had
        // a constructor dependency on IUnitOfWork
        coordinator.Uow
            .ShouldBeTheSameAs(coordinator.Worker1.Uow);
    
        coordinator.Uow
            .ShouldBeTheSameAs(coordinator.Worker2.Uow);
    
        coordinator.Worker1.Uow
            .ShouldBeTheSameAs(coordinator.Worker2.Uow);
    }
    
    
    +

    AlwaysUnique

    +

    Very simply, using the AlwaysUnique means that a new object instance will be created every single time a configured Instance is either requested +from a Container or as a dependency to another object. The AlwaysUnique lifecycle is a "fire and forget" operation as the object instances are neither tracked nor disposed by StructureMap.

    + +
    
    [Fact]
    public void Always_Unique()
    {
        var c = new Container(x => { x.For<IService>().Use<Service>().AlwaysUnique(); });
    
        // In a normal container, you get a new object
        // instance of the Service class in subsequent
        // requests
        c.GetInstance<IService>()
            .ShouldNotBeTheSameAs(c.GetInstance<IService>())
            .ShouldNotBeTheSameAs(c.GetInstance<IService>());
    
        // Within a nested container, 'Transient' now
        // means within the Nested Container.
        // A nested container is effectively one request
        using (var nested = c.GetNestedContainer())
        {
            nested.GetInstance<IService>()
                .ShouldNotBeTheSameAs(nested.GetInstance<IService>())
                .ShouldNotBeTheSameAs(nested.GetInstance<IService>());
        }
    
        // Even in a single request,
        var holder = c.GetInstance<ServiceUserHolder>();
        holder.Service.ShouldNotBeTheSameAs(holder.User.Service);
    }
    
    
    +

    Singleton

    +

    StructureMap 3.0 fixed the dreaded singletons with nested container's bug that was so problematic in 2.6.

    +
    
    [Fact]
    public void singletons_are_disposed_when_the_container_is_disposed()
    {
        var container = new Container(_ =>
        {
            _.ForSingletonOf<DisposableSingleton>();
        });
    
        // As a singleton-scoped object, every request for DisposableSingleton
        // will return the same object
        var singleton = container.GetInstance<DisposableSingleton>();
        singleton.ShouldBeSameAs(container.GetInstance<DisposableSingleton>());
        singleton.ShouldBeSameAs(container.GetInstance<DisposableSingleton>());
        singleton.ShouldBeSameAs(container.GetInstance<DisposableSingleton>());
        singleton.ShouldBeSameAs(container.GetInstance<DisposableSingleton>());
    
        singleton.WasDisposed.ShouldBeFalse();
    
        // now, dispose the Container
        container.Dispose();
    
        // the SingletonThing scoped object should be disposed
        singleton.WasDisposed.ShouldBeTrue();
    }
    
    
    +

    Do note that objects created as the singleton scope will be disposed when the Container is disposed if they +implement the IDisposable interface:

    +
    
    public interface IUnitOfWork
    {
    }
    
    public class DefaultUnitOfWork : IUnitOfWork
    {
    }
    
    public class Worker1
    {
        public IUnitOfWork Uow { get; set; }
    
        public Worker1(IUnitOfWork uow)
        {
            Uow = uow;
        }
    }
    
    public class Worker2
    {
        public IUnitOfWork Uow { get; set; }
    
        public Worker2(IUnitOfWork uow)
        {
            Uow = uow;
        }
    }
    
    public class WorkerCoordinator
    {
        public IUnitOfWork Uow { get; set; }
        public Worker1 Worker1 { get; set; }
        public Worker2 Worker2 { get; set; }
    
        public WorkerCoordinator(IUnitOfWork uow, Worker1 worker1, Worker2 worker2)
        {
            Uow = uow;
            Worker1 = worker1;
            Worker2 = worker2;
        }
    }
    
    [Fact]
    public void transient_scoped_Instance_is_built_once_per_resolution_to_the_Container()
    {
        var container = new Container(_ => { _.For<IUnitOfWork>().Use<DefaultUnitOfWork>(); });
    
        var coordinator = container.GetInstance<WorkerCoordinator>();
    
        // The IUnitOfWork object instance is the same for
        // all the objects in the object graph that had
        // a constructor dependency on IUnitOfWork
        coordinator.Uow
            .ShouldBeTheSameAs(coordinator.Worker1.Uow);
    
        coordinator.Uow
            .ShouldBeTheSameAs(coordinator.Worker2.Uow);
    
        coordinator.Worker1.Uow
            .ShouldBeTheSameAs(coordinator.Worker2.Uow);
    }
    
    
    +

    ContainerScoped

    +

    New in StructureMap 4.0 is the ContainerScoped lifecycle that was designed specifically for compliance with the new ASP.Net DNX adapter model. +ContainerScoped in this case means that a registration will be built once per Container, such that the root container, any child or profile +container, and every single nested container will build its own object instance.

    +

    The acceptance test for ContainerScoped is shown below:

    +
    
    [Fact]
    public void container_scoping_with_root_child_and_nested_container()
    {
        var container = new Container(_ =>
        {
            _.ForConcreteType<Disposable>().Configure.ContainerScoped();
        });
    
        var child = container.CreateChildContainer();
    
        var nested = container.GetNestedContainer();
    
        // Always the same object when requested from the root container
        var mainDisposable = container.GetInstance<Disposable>();
        mainDisposable
            .ShouldBeTheSameAs(container.GetInstance<Disposable>());
    
        // Always the same object when requested from a child container
        var childDisposable = child.GetInstance<Disposable>();
        childDisposable
            .ShouldBeTheSameAs(child.GetInstance<Disposable>());
    
        // Always the same object when requested from a nested container
        var nestedDisposable = nested.GetInstance<Disposable>();
        nestedDisposable
            .ShouldBeTheSameAs(nested.GetInstance<Disposable>());
    
        // It should be a different object instance for
        // all three containers
        mainDisposable
            .ShouldNotBeTheSameAs(childDisposable);
    
        mainDisposable
            .ShouldNotBeTheSameAs(nestedDisposable);
    
        childDisposable
            .ShouldNotBeTheSameAs(nestedDisposable);
    
        // When the nested container is disposed,
        // it should dispose all the container scoped objects,
        // but not impact the other containers
        nested.Dispose();
        nestedDisposable.WasDisposed.ShouldBeTrue();
        childDisposable.WasDisposed.ShouldBeFalse();
        mainDisposable.WasDisposed.ShouldBeFalse();
    
        // Same for the child container
        child.Dispose();
        childDisposable.WasDisposed.ShouldBeTrue();
        mainDisposable.WasDisposed.ShouldBeFalse();
    
        // Same for the main container
        container.Dispose();
        mainDisposable.WasDisposed.ShouldBeTrue();
    }
    
    
    +

    ThreadLocal

    +

    The ThreadLocalStorage based lifecycle is seldom used, but the easiest example of using it and explanation is the integration test:

    +
    
    
    public class ThreadLocalStorageLifecycleTester
    {
        public ThreadLocalStorageLifecycleTester()
        {
            _lifecycle = new ThreadLocalStorageLifecycle();
    
            container = new Container(x => x.For<Rule>(Lifecycles.ThreadLocal).Use(() => new ColorRule("Red")));
        }
    
        private ThreadLocalStorageLifecycle _lifecycle;
        private ColorRule _rule1;
        private ColorRule _rule2;
        private ColorRule _rule3;
        private Container container;
    
        private void findRule1()
        {
            _rule1 = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
    
            var rule = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
            _rule1.ShouldBeTheSameAs(rule);
        }
    
        private void findRule2()
        {
            _rule2 = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
    
            var rule = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
            _rule2.ShouldBeTheSameAs(rule);
        }
    
        private void findRule3()
        {
            _rule3 = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
    
            var rule = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
            _rule3.ShouldBeTheSameAs(rule);
    
            rule = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
            _rule3.ShouldBeTheSameAs(rule);
    
            rule = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
            _rule3.ShouldBeTheSameAs(rule);
    
            rule = container.GetInstance<Rule>().ShouldBeOfType<ColorRule>();
            _rule3.ShouldBeTheSameAs(rule);
        }
    
        [Fact]
        public void object_has_been_created()
        {
            container.Model.For<Rule>().Default.ObjectHasBeenCreated().ShouldBeFalse();
            var r1 = container.GetInstance<Rule>();
            container.Model.For<Rule>().Default.ObjectHasBeenCreated().ShouldBeTrue();
        }
    
        [Fact]
        public void FindUniqueInstancePerThread()
        {
            var t1 = new Thread(findRule1);
            var t2 = new Thread(findRule2);
            var t3 = new Thread(findRule3);
    
            t1.Start();
            t2.Start();
            t3.Start();
    
            t1.Join();
            t2.Join();
            t3.Join();
    
            _rule1.ShouldNotBeTheSameAs(_rule2);
            _rule1.ShouldNotBeTheSameAs(_rule3);
            _rule2.ShouldNotBeTheSameAs(_rule3);
            (_rule1.ID != _rule2.ID).ShouldBeTrue();
            (_rule1.ID != _rule3.ID).ShouldBeTrue();
            (_rule2.ID != _rule3.ID).ShouldBeTrue();
        }
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -471,6 +164,29 @@

    Legacy ASP.Net Lifecycles

    + + diff --git a/quickstart/index.html b/quickstart/index.html index 5d8f22c..223677e 100644 --- a/quickstart/index.html +++ b/quickstart/index.html @@ -1,211 +1,152 @@ - + - StructureMap - A Gentle Quickstart - - - - - - - - - - + StructureMap - A Gentle Quickstart + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    A Gentle Quickstart Edit on GitHub

    + +
    + +
    + + +

    The first thing you should know is that StructureMap (and other IoC tools like it) are designed to +make compositional and modular software designs easier to build by offloading the grubby mechanics of +resolving dependencies, reading configuration data, and assembling object graphs to the IoC tool instead +of cluttering up your application code.

    +

    Before you get started with StructureMap it's recommended that you first get comfortable with the Software Design Concepts +of Dependency Injection +and Inversion Of Control. +It's important that you structure and build your application with these concepts in mind to fully utilize StructureMap's abilities.

    +

    Assuming that you're already familiar with those concepts, or you'd really rather skip the pedantry and jump right into concrete code, the first thing to do is, go Get StructureMap and jump into usage.

    +

    Main Usage

    +

    By and large, you really only do two kinds of things with StructureMap:

    +
      +
    1. Configure the container by registering the what and how StructureMap should build or find requested services based on a type and/or name.

      +
    2. +
    3. Resolve object instances of a service or dependency built out with all of its dependencies.

      +
    4. +
    +

    So let's say that you have a simple object model like so:

    +
    
    public interface IBar
    {
    }
    
    public class Bar : IBar
    {
    }
    
    public interface IFoo
    {
    }
    
    public class Foo : IFoo
    {
        public IBar Bar { get; private set; }
    
        public Foo(IBar bar)
        {
            Bar = bar;
        }
    }
    
    
    +

    You could explicitly build a StructureMap Container object to build these types like this:

    +
    
    // Configure and build a brand new
    // StructureMap Container object
                var container = new Container(_ =>
                {
                    _.For<IFoo>().Use<Foo>();
                    _.For<IBar>().Use<Bar>();
                });
    
    // Now, resolve a new object instance of IFoo
                container.GetInstance<IFoo>()
                    // should be type Foo
                    .ShouldBeOfType<Foo>()
    
                    // and the IBar dependency too
                    .Bar.ShouldBeOfType<Bar>();
    
    
    
    +

    or utilize StructureMap's type scanning conventions to configure the relationships and do the same thing like this:

    +
    
    var container = new Container(_ =>
    {
        _.Scan(x =>
        {
            x.TheCallingAssembly();
            x.WithDefaultConventions();
        });
    });
    
    container.GetInstance<IFoo>()
        .ShouldBeOfType<Foo>()
        .Bar.ShouldBeOfType<Bar>();
    
    
    +

    Integrating StructureMap within your application

    +

    At some point you will want to integrate StructureMap into your application. Whether you are using Windows Presentation Foundation (WPF), FubuMVC, ASP.NET WebForms, ASP.NET MVC or any other framework or technology, you will have to do some sort of plumbing and bootstrapping. Depending on the used technology or framework there can be important integration points that you will have to use to fully enable the power of StructureMap.

    +

    While StructureMap doesn't provide integration support out of the box for all of the frameworks and technologies out there, we do find it important to help you get started with integrating StructureMap into your application. That said, StructureMap does provide integration support for FubuMVC (a web framework, which is part of the same family as StructureMap).

    +

    What to do when things go wrong?

    +

    StructureMap, and any other IoC tool for that matter, is configuration intensive, which means that their will be problems in that configuration. We're all moving to more convention based type registration, so more stuff is happening off stage and out of your sight, making debugging the configuration even trickier. Not to worry (too much), StructureMap has some diagnostic abilities to help you solve configuration problems:

    + +

    Need Help?

    + + +
    + +
    + + + +
    +
    +
    @@ -219,6 +160,29 @@

    Need Help?

    + + diff --git a/registration/attributes/index.html b/registration/attributes/index.html new file mode 100644 index 0000000..3b78e1e --- /dev/null +++ b/registration/attributes/index.html @@ -0,0 +1,202 @@ + + + + + + + + StructureMap - Using Attributes for Configuration + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Using Attributes for Configuration Edit on GitHub

    + +
    + +
    + +

    In the early days of StructureMap we had several attributes for basic configuration that we'd just as soon +forget ever existed. Further more, the StructureMap strongly believes that the usage of StructureMap should +have as little impact on application code as possible -- and forcing users to spray .Net attributes all over +their own code is in clear violation of this philosophy. In other words, we don't want to be MEF.

    +

    That being said, there are plenty of times when simple attribute usage is effective for one-off deviations from +your normal registration conventions or cause less harm than having to constantly change a centralized Registry or +just seem more clear and understandable to users than a convention. For those usages, StructureMap 4.0 has introduced a +new base class that can be extended and used to explicitly customize your StructureMap configuration:

    +
    
    public abstract class StructureMapAttribute : Attribute
    {
        public virtual void Alter(PluginFamily family)
        {
        }
    
        public virtual void Alter(IConfiguredInstance instance)
        {
        }
    
        public virtual void Alter(IConfiguredInstance instance, PropertyInfo property)
        {
        }
    
        public virtual void Alter(IConfiguredInstance instance, ParameterInfo parameter)
        {
        }
    }
    
    +

    There's a couple thing to note, here about this new attibute:

    +
      +
    • StructureMap internals are looking for any attribute of the base class. Attributes that affect types are read and applied early, +while attributes decorating properties or constructor parameters are only read and applied during the creation of Build Plans.
    • +
    • Unlike many other frameworks, the attributes in StructureMap are not executed at build time. Instead, StructureMap uses attributes one time +to determine the build plan.
    • +
    +

    Attribute Targeting Plugin Type or Concrete Type

    +

    Take the new [Singleton] attribute shown below:

    +
    
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface)]
    public class SingletonAttribute : StructureMapAttribute
    {
        // This method will affect the configuration for the
        // entire plugin type
        public override void Alter(PluginFamily family)
        {
            family.SetLifecycleTo<SingletonLifecycle>();
        }
    
        // This method will affect single registrations
        public override void Alter(IConfiguredInstance instance)
        {
            instance.SetLifecycleTo<SingletonLifecycle>();
        }
    }
    
    +

    This new attribute can be used on either the plugin type (typically an interface) or on a concrete type +to make an individual type registration be a singleton. You can see the usage on some types below:

    +
    
    [Singleton] // ALL Instance's of ITeamCache will be singletons by default
    public interface ITeamCache { }
    
    public class TeamCache : ITeamCache { }
    
    public class OtherTeamCache : ITeamCache { }
    
    public interface ITeam { }
    
    public class Chargers : ITeam { }
    
    [Singleton] // This specific type will be a singleton
    public class Chiefs : ITeam { }
    
    
    +

    Attribute Targeting Constructor Parameters or Setter Properties

    +

    As an example, let's say that you want a new attribute type that can decorate either properties or constructor parameters +to say "use the value from the old .Net AppSettings collection as the value for this property/parameter." To build that new +custom attribute, you would create a new attribute that subclasses StructureMapAttribute and override the two methods shown below:

    +
    
    public class AppSettingAttribute : StructureMapAttribute
    {
        private readonly string _key;
    
        public AppSettingAttribute(string key)
        {
            _key = key;
        }
    
        public override void Alter(IConfiguredInstance instance, PropertyInfo property)
        {
            var value = System.Configuration.ConfigurationManager.AppSettings[_key];
    
            instance.Dependencies.AddForProperty(property, value);
        }
    
        public override void Alter(IConfiguredInstance instance, ParameterInfo parameter)
        {
            var value = System.Configuration.ConfigurationManager.AppSettings[_key];
    
            instance.Dependencies.AddForConstructorParameter(parameter, value);
        }
    }
    
    
    +

    To test out the new attribute above, say we have a concrete type like this one that we +decorate with the new [AppSetting] attribute:

    +
    
    public class AppSettingTarget
    {
        public string Name { get; set; }
    
        [AppSetting("homestate")]
        public string HomeState { get; set; }
    
        public AppSettingTarget([AppSetting("name")]string name)
        {
            Name = name;
        }
    }
    
    
    +

    The following unit test demonstrates our new custom [AppSetting] attribute in action:

    +
    
    [Fact]
    public void using_parameter_and_property_attibutes()
    {
        System.Configuration.ConfigurationManager.AppSettings["name"] = "Jeremy";
        System.Configuration.ConfigurationManager.AppSettings["homestate"] = "Missouri";
    
        System.Configuration.ConfigurationManager.AppSettings["name"].ShouldBe("Jeremy");
    
        var container = new Container();
    
        var target = container.GetInstance<AppSettingTarget>();
    
        target.Name.ShouldBe("Jeremy");
        target.HomeState.ShouldBe("Missouri");
    
        Debug.WriteLine(container.Model.For<AppSettingTarget>().Default.DescribeBuildPlan());
    }
    
    
    +

    The build plan for AppSettingTarget is determined by the active StructureMap +container to be this:

    +
    +PluginType: StructureMap.Testing.Acceptance.attribute_usage+AppSettingTarget
    +Lifecycle: Transient
    +new AppSettingTarget(String name)
    +  ┗ String name = Value: Jeremy
    +Set String HomeState = Value: Missouri
    +
    +

    Note that the values retrieved from AppSettings are essentially hard coded into the underlying builder function that StructureMap compiled for +AppSettingTarget. You could instead add a "lambda builder" dependency so that StructureMap had to +use the live value for AppSettings as it constructs objects.

    +

    Built In Attributes

    +

    StructureMap supplies a handful of built in attributes for customizing configuration:

    +
      +
    • [ValidationMethod] - Allows you to expose Environment Tests in your StructureMap registrations
    • +
    • [SetterProperty] - See Setter Injection
    • +
    • [DefaultConstructor] - Declare which constructor function should be used by StructureMap. See Constructor Selection for more information
    • +
    • [AlwaysUnique] and [Singleton] - These attributes, new for StructureMap 4.0, just add another mechanism for lifecycle configuration
    • +
    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/registration/auto-registration-and-conventions/index.html b/registration/auto-registration-and-conventions/index.html index 27184ec..c8a7c81 100644 --- a/registration/auto-registration-and-conventions/index.html +++ b/registration/auto-registration-and-conventions/index.html @@ -1,288 +1,199 @@ - + - StructureMap - Auto-Registration and Conventions - - - - - - - - - - + StructureMap - Auto-Registration and Conventions + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Auto-Registration and Conventions Edit on GitHub

    + +
    + +
    + + + +

    StructureMap has rich support for registering types by scanning assemblies and applying conventional registrations. +Between scanning and default conventions, configurations are often just a few +lines.

    +

    Also see Type Scanning Diagnostics for help in understanding the assembly scanning behavior in your system.

    +

    Registry.Scan()

    +

    Assembly scanning operations are defined by the Registry.Scan() method demonstrated below:

    +
    
    public class BasicScanning : Registry
    {
        public BasicScanning()
        {
            Scan(_ =>
            {
                // Declare which assemblies to scan
                _.Assembly("StructureMap.Testing");
                _.AssemblyContainingType<IWidget>();
    
                // Filter types
                _.Exclude(type => type.Name.Contains("Bad"));
    
                // A custom registration convention
                _.Convention<MySpecialRegistrationConvention>();
    
                // Built in registration conventions
                _.AddAllTypesOf<IWidget>().NameBy(x => x.Name.Replace("Widget", ""));
                _.WithDefaultConventions();
            });
        }
    }
    
    +

    Please note (because I've been asked this several times over the years) that each call to Registry.Scan() is an entirely atomic operation that has no impact on previous or subsequent calls.

    +

    Any given call to Registry.Scan() consists of three different things:

    +
      +
    1. One or more assemblies to scan for types
    2. +
    3. One or more registration conventions
    4. +
    5. Optionally, set filters to only include certain types or exclude other types from being processed by the scanning operation
    6. +
    +

    Scan the Calling Assembly

    +

    One of the easiest ways to register types is by scanning the assembly your +registry is placed in.

    +

    Note if you have other registries, StructureMap will not automatically +find them.

    +
    
    [Fact]
    public void scan_but_ignore_registries_by_default()
    {
        Scan(x => { x.TheCallingAssembly(); });
    
        TestingRegistry.WasUsed.ShouldBeFalse();
    }
    
    
    +

    Note that this method is an extension method in the StructureMap.Net4 assembly and cannot be used +if you target PCL compliance.

    +

    Scan for Registries

    +

    StructureMap can automatically include other registries with theLookForRegistries +method.

    +
    
    [Fact]
    public void Search_for_registries_when_explicitly_told()
    {
        Scan(x =>
        {
            x.TheCallingAssembly();
            x.LookForRegistries();
        });
    
        TestingRegistry.WasUsed.ShouldBeTrue();
    }
    
    
    +

    As of 4.0, this operation is now recursive and StructureMap has always been idempotent about adding Registry types

    +

    Search for Assemblies on the File System

    +

    StructureMap provides facilities for registering types by finding assemblies in the application bin path:

    +
    
    [Fact]
    public void scan_all_assemblies_in_a_folder()
    {
        Scan(x => x.AssembliesFromPath(assemblyScanningFolder));
        shouldHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldNotHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    [Fact]
    public void scan_all_assemblies_in_a_folder_with_path_filter()
    {
        Scan(x => x.AssembliesFromPath(assemblyScanningFolder, path => !path.Contains("Widget5")));
        shouldNotHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldNotHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    [Fact]
    public void scan_all_assemblies_in_application_base_directory()
    {
        Scan(x => x.AssembliesFromApplicationBaseDirectory());
        shouldHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldNotHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    [Fact]
    public void scan_all_assemblies_in_application_base_directory_with_path_filter()
    {
        Scan(x => x.AssembliesFromApplicationBaseDirectory(path => !path.Contains("Widget5")));
        shouldNotHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldNotHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    
    +

    Do note that StructureMap 4.0 does not search for .exe files in the assembly search. The StructureMap team felt this was +problematic and "nobody would ever actually want to do that." We were wrong, and due to many user requests, you can now +opt in to scanning .exe files with a new public method on AssemblyScanner shown below:

    +
    
    [Fact]
    public void scan_all_assemblies_in_a_folder_including_exe()
    {
        Scan(x => x.AssembliesAndExecutablesFromPath(assemblyScanningFolder));
    
        shouldHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    [Fact]
    public void scan_all_assemblies_in_a_folder_including_exe_with_path_filter()
    {
        Scan(x => x.AssembliesAndExecutablesFromPath(assemblyScanningFolder, path => !path.Contains("Widget5")));
    
        shouldNotHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    
    [Fact]
    public void scan_all_assemblies_in_application_base_directory_including_exe()
    {
        Scan(x => x.AssembliesAndExecutablesFromApplicationBaseDirectory());
    
        shouldHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    [Fact]
    public void scan_all_assemblies_in_application_base_directory_including_exe_with_path_filter()
    {
        Scan(x => x.AssembliesAndExecutablesFromApplicationBaseDirectory(path => !path.Contains("Widget5")));
    
        shouldNotHaveFamilyWithSameName<IInterfaceInWidget5>();
        shouldHaveFamilyWithSameName<IWorker>();
        shouldHaveFamilyWithSameName<IDefinedInExe>();
    }
    
    
    +

    Do be aware that while this technique is very powerful for extensibility, it's been extremely problematic for +some folks in the past. The StructureMap team's recommendation for using this feature is to:

    +
      +
    1. Make sure you have some kind of filter on the assemblies scanned for performance and predictability reasons. Either a naming convention or filter +by an assembly attribute to narrow where StructureMap looks
    2. +
    3. Get familiar with the new type scanning diagnostics introduced in 4.0;-)
    4. +
    +

    Behind the scenes, StructureMap is using the Assembly.GetExportedTypes() method from the .Net CLR to find types and this +mechanism is very sensitive to missing dependencies. Again, thanks to the new type scanning diagnostics, +you now have some visibility into assembly loading failures that used to be silently swallowed internally.

    +

    Excluding Types

    +

    StructureMap also makes it easy to exclude types, either individually or by namespace. +The following examples also show how StructureMap can register an assembly by providing +a type within that assembly.

    +

    Excluding additional types or namespaces is as easy as calling the corresponding method +again.

    +
    
    [Fact]
    public void use_a_single_exclude_of_type()
    {
        Scan(x =>
        {
            x.AssemblyContainingType<ITypeThatHasAttributeButIsNotInRegistry>();
            x.ExcludeType<ITypeThatHasAttributeButIsNotInRegistry>();
        });
    
        shouldHaveFamily<IInterfaceInWidget5>();
        shouldNotHaveFamily<ITypeThatHasAttributeButIsNotInRegistry>();
    }
    
    [Fact]
    public void use_a_single_exclude2()
    {
        Scan(x =>
        {
            x.AssemblyContainingType<ITypeThatHasAttributeButIsNotInRegistry>();
            x.ExcludeNamespace("StructureMap.Testing.Widget5");
        });
    
        shouldNotHaveFamily<IInterfaceInWidget5>();
        shouldNotHaveFamily<ITypeThatHasAttributeButIsNotInRegistry>();
    }
    
    [Fact]
    public void use_a_single_exclude3()
    {
        Scan(x =>
        {
            x.AssemblyContainingType<ITypeThatHasAttributeButIsNotInRegistry>();
            x.ExcludeNamespaceContainingType<ITypeThatHasAttributeButIsNotInRegistry>();
        });
    
        shouldNotHaveFamily<IInterfaceInWidget5>();
        shouldNotHaveFamily<ITypeThatHasAttributeButIsNotInRegistry>();
    }
    
    
    +

    Custom Registration Conventions

    +

    It's just not possible (or desirable) for StructureMap to include every possible type of auto registration +convention users might want, but that's okay because StructureMap allows you to create and use your own +conventions through the IRegistrationConvention interface:

    +
    
    public interface IRegistrationConvention
    {
        void ScanTypes(TypeSet types, Registry registry);
    }
    
    +

    Let's say that you'd like a custom convention that just registers a concrete type against all the interfaces +that it implements. You could then build a custom IRegistrationConvention class like the following example:

    +
    
    public interface IFoo
    {
    }
    
    public interface IBar
    {
    }
    
    public interface IBaz
    {
    }
    
    public class BusyGuy : IFoo, IBar, IBaz
    {
    }
    
    // Custom IRegistrationConvention
    public class AllInterfacesConvention : IRegistrationConvention
    {
        public void ScanTypes(TypeSet types, Registry registry)
        {
            // Only work on concrete types
            types.FindTypes(TypeClassification.Concretes | TypeClassification.Closed).Each(type =>
            {
                // Register against all the interfaces implemented
                // by this concrete class
                type.GetInterfaces().Each(@interface => registry.For(@interface).Use(type));
            });
        }
    }
    
    [Fact]
    public void use_custom_registration_convention()
    {
        var container = new Container(_ =>
        {
            _.Scan(x =>
            {
                // You're probably going to want to tightly filter
                // the Type's that are applicable to avoid unwanted
                // registrations
                x.TheCallingAssembly();
                x.IncludeNamespaceContainingType<BusyGuy>();
    
                // Register the custom policy
                x.Convention<AllInterfacesConvention>();
            });
        });
    
        container.GetInstance<IFoo>().ShouldBeOfType<BusyGuy>();
        container.GetInstance<IBar>().ShouldBeOfType<BusyGuy>();
        container.GetInstance<IBaz>().ShouldBeOfType<BusyGuy>();
    }
    
    
    +

    Composite Decorators

    +

    Sometimes you need to have many implementations of an interface, and to have all of them used together, which usually involves creating another implementation of the interface which takes all the others as dependencies.

    +

    If you try this in StructureMap, it will throw an exception as it detects a bi-directional dependency. This is because by default an IEnumerable<T> constructor parameter will be populated with all instances of T, which would include the implementation with the IEnumerable<T>parameter!

    +

    We can use a custom IRegistrationConvention however to tell StructureMap that when it constructs a Composite, it should only include implementations which are not the Composite:

    +
    
    public interface ISomething
    {
        IEnumerable<string> GetNames();
    }
    
    public class One : ISomething
    {
        public IEnumerable<string> GetNames() => new[] { "one" };
    }
    
    public class Two : ISomething
    {
        public IEnumerable<string> GetNames() => new[] { "two" };
    }
    
    public class SomethingComposite : ISomething
    {
        private readonly IEnumerable<ISomething> _others;
    
        public SomethingComposite(IEnumerable<ISomething> others)
        {
            _others = others;
        }
    
        public IEnumerable<string> GetNames() => _others.SelectMany(other => other.GetNames());
    }
    
    // Custom IRegistrationConvention
    public class CompositeDecorator<TComposite, TDependents> : IRegistrationConvention
        where TComposite : TDependents
    {
        public void ScanTypes(TypeSet types, Registry registry)
        {
            var dependents = types
                .FindTypes(TypeClassification.Concretes)
                .Where(t => t.CanBeCastTo<TDependents>() && t.HasConstructors())
                .Where(t => t != typeof(TComposite))
                .ToList();
    
            registry.For<TDependents>()
                .Use<TComposite>()
                .EnumerableOf<TDependents>().Contains(x => dependents.ForEach(t => x.Type(t)));
        }
    }
    
    [Fact]
    public void use_custom_registration_convention_2()
    {
        var container = new Container(_ =>
        {
            _.Scan(x =>
            {
                x.AssemblyContainingType<ISomething>();
                x.Convention<CompositeDecorator<SomethingComposite, ISomething>>();
            });
        });
    
        var composite = container.GetInstance<ISomething>();
    
        composite.ShouldBeOfType<SomethingComposite>();
        composite.GetNames().ShouldBe(new[] { "one", "two" }, ignoreOrder: true);
    }
    
    
    +

    The Default ISomething/Something Convention

    +

    The "default" convention simply tries to connect concrete classes to interfaces using +the I[Something]/[Something] naming convention as shown in this sample:

    +
    
    public interface ISpaceship { }
    
    public class Spaceship : ISpaceship { }
    
    public interface IRocket { }
    
    public class Rocket : IRocket { }
    
    [Fact]
    public void default_scanning_in_action()
    {
        var container = new Container(_ =>
        {
            _.Scan(x =>
            {
                x.Assembly("StructureMap.Testing");
                x.WithDefaultConventions();
            });
        });
    
        container.GetInstance<ISpaceship>().ShouldBeOfType<Spaceship>();
        container.GetInstance<IRocket>().ShouldBeOfType<Rocket>();
    }
    
    
    +

    The StructureMap team contains some VB6 veterans who hate Hungarian Notation, but can't shake the "I" nomenclature.

    +

    Registering the Single Implementation of an Interface

    +

    To tell StructureMap to automatically register any interface that only has one concrete implementation, use this method:

    +
    
    public interface ISong { }
    
    public class TheOnlySong : ISong { }
    
    [Fact]
    public void only_implementation()
    {
        var container = new Container(_ =>
        {
            _.Scan(x =>
            {
                x.TheCallingAssembly();
                x.SingleImplementationsOfInterface();
            });
        });
    
        container.GetInstance<ISong>()
            .ShouldBeOfType<TheOnlySong>();
    }
    
    
    +

    Register all Concrete Types of an Interface

    +

    To add all concrete types that can be cast to a named plugin type, use this syntax:

    +
    
    public interface IFantasySeries { }
    
    public class WheelOfTime : IFantasySeries { }
    
    public class GameOfThrones : IFantasySeries { }
    
    public class BlackCompany : IFantasySeries { }
    
    [Fact]
    public void register_all_types_of_an_interface()
    {
        var container = new Container(_ =>
        {
            _.Scan(x =>
            {
                x.TheCallingAssembly();
    
                x.AddAllTypesOf<IFantasySeries>();
    
                // or
    
                x.AddAllTypesOf(typeof(IFantasySeries))
                    .NameBy(type => type.Name.ToLower());
            });
        });
    
        container.Model.For<IFantasySeries>()
            .Instances.Select(x => x.ReturnedType)
            .OrderBy(x => x.Name)
            .ShouldHaveTheSameElementsAs(typeof(BlackCompany), typeof(GameOfThrones), typeof(WheelOfTime));
    }
    
    
    +

    Note, "T" does not have to be an interface, it's all based on the ability to cast a concrete type to the "T"

    +

    Generic Types

    +

    See Generic Types for an example of using the ConnectImplementationsToTypesClosing +mechanism for generic types.

    +

    Register Concrete Types against the First Interface

    +

    The last built in registration convention is a mechanism to register all concrete types +that implement at least one interface against the first interface that they implement.

    +
    
    container = new Container(x =>
    {
        x.Scan(o =>
        {
            o.TheCallingAssembly();
            o.RegisterConcreteTypesAgainstTheFirstInterface();
    
            o.Exclude(t => t.CanBeCastTo(typeof(IGateway)));
        });
    });
    
    + +
    + +
    + + + +
    +
    +
    @@ -296,6 +207,29 @@

    Custom Registration Conventions

    + + diff --git a/registration/changing-configuration-at-runtime/index.html b/registration/changing-configuration-at-runtime/index.html index abfb810..027528e 100644 --- a/registration/changing-configuration-at-runtime/index.html +++ b/registration/changing-configuration-at-runtime/index.html @@ -1,151 +1,127 @@ - + - StructureMap - Changing Configuration at Runtime - - - - - - - - - - + StructureMap - Changing Configuration at Runtime + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Changing Configuration at Runtime Edit on GitHub

    + +
    + +
    + + + +

    If you need to add or change configuration to an existing StructureMap Container object, you can use the IContainer.Configure() method +to add or change your container at runtime as shown below:

    +
    
    [Fact]
    public void change_default_in_an_existing_container()
    {
        var container = new Container(x => { x.For<IFoo>().Use<AFoo>(); });
    
        container.GetInstance<IFoo>().ShouldBeOfType<AFoo>();
    
        // Now, change the container configuration
        container.Configure(x => x.For<IFoo>().Use<BFoo>());
    
        // The default of IFoo is now different
        container.GetInstance<IFoo>().ShouldBeOfType<BFoo>();
    
        // or use the Inject method that's just syntactical
        // sugar for replacing the default of one type at a time
    
        container.Inject<IFoo>(new CFoo());
    
        container.GetInstance<IFoo>().ShouldBeOfType<CFoo>();
    }
    
    
    +

    Best Practices

    +

    First off, the best advice on this functionality is don't use it outside of testing scenarios on the root container. The Configure() method has to use a threading lock around the internal object model of a StructureMap container and can cause serious contention at runtime if you try to override services in the main application controller. Some frameworks (looking at you NancyFx) have abused this functionality quite badly in the past and the result was not pretty.

    +
      +
    • Do favor writing configuration to StructureMap Registry objects, then applying that Registry to a container rather than repeatedly calling Configure()
    • +
    • Do not call Configure() on the main application container after the initial configuration. Use nested or child containers that are not shared across threads or HTTP requests if you need to override services at runtime
    • +
    • There's a potential performance hit from using Configure() at runtime because StructureMap has to recycle its internal Build Plan's based on +the potential new configuration.
    • +
    + +
    + +
    + + + +
    +
    +
    @@ -159,6 +135,29 @@

    Best Practices

    + + diff --git a/registration/clear-or-replace/index.html b/registration/clear-or-replace/index.html new file mode 100644 index 0000000..80757eb --- /dev/null +++ b/registration/clear-or-replace/index.html @@ -0,0 +1,178 @@ + + + + + + + + StructureMap - Replace or Clear Out Previous Registrations + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Replace or Clear Out Previous Registrations Edit on GitHub

    + +
    + +
    + +

    Several members of the StructureMap team were also very active in a now semi-defunct web framework called FubuMVC +that was built with quite a bit of extensibility in mind. One of the extensibility mechanisms that was successful in FubuMVC was the ability for applications or addon libraries to swap out the default services in the main StructureMap application container.

    +

    The approach we took for this extensibility was what I flippantly call the "Mongolian BBQ" architecture. The framework should take the application specific registrations, the framework defaults, and all the discovered addons and figure out how to order the registrations to enforce the following levels of registration precedence:

    +
      +
    1. The application specific registrations should always win out
    2. +
    3. Package or extension specific overrides
    4. +
    5. Default framework service registrations
    6. +
    +

    To make this kind of modular and adaptive registration work, FubuMVC introduced a couple concepts that we've now pulled back into StructureMap:

    +
      +
    1. The Fallback Services introduced in the previous topic where you can make a registration that effectively tells StructureMap to "use this registration if nobody else tells you something differently".
    2. +
    3. The new Registry.For().ClearAll() mechanism shown in this topic that tells StructureMap to "disregard what everyone else said to use".
    4. +
    +

    Typically in FubuMVC, we would use fallback service registrations for most of the framework defaults and occasionally use the ClearAll() type mechanics down the line as an analogue to the CSS !important keyword to make a particular registration take precedence in the face of multiple registrations.

    +

    In usage, let's say that our application needs some type of IWidget service to run. For an important client, they want to deploy our system with +a special version, so we will create a new StructureMap Registry to apply their specific registrations using the ClearAll() mechanism to +insure that the important client gets their way:

    +
    
    public class ImportantClientWidget : IWidget { }
    
    public class ImportantClientServices : Registry
    {
        public ImportantClientServices()
        {
            For<IWidget>().ClearAll().Use<ImportantClientWidget>();
        }
    }
    
    
    +

    In usage, the ClearAll() stomps all over the default registration before adding their own:

    +
    
    [Fact]
    public void clear_all_in_action()
    {
        var container = new Container(_ =>
        {
            _.For<IWidget>().Use<AWidget>();
    
            _.IncludeRegistry<ImportantClientServices>();
        });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<ImportantClientWidget>();
    
        Debug.WriteLine(container.WhatDoIHave(pluginType: typeof(IWidget)));
    }
    
    
    +

    If you were to check the WhatDoIHave() view for IWidget, you would see only the ImportantClientWidget:

    +
    +==============================================================================================================================================
    +PluginType     Namespace                           Lifecycle     Description                                                         Name     
    +----------------------------------------------------------------------------------------------------------------------------------------------
    +IWidget        StructureMap.Testing.Acceptance     Transient     StructureMap.Testing.Acceptance.clear_all+ImportantClientWidget     (Default)
    +==============================================================================================================================================
    +
    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/registration/configured-instance/index.html b/registration/configured-instance/index.html new file mode 100644 index 0000000..5979e10 --- /dev/null +++ b/registration/configured-instance/index.html @@ -0,0 +1,207 @@ + + + + + + + + StructureMap - Working with IConfiguredInstance + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Working with IConfiguredInstance Edit on GitHub

    + +
    + +
    + +

    The most common way for StructureMap to build or resolve a requested object is to build a concrete type directly by calling a +public constructor function and optionally filling values in public setter properties. For this type of object construction, +StructureMap exposes the IConfiguredInstance interface as a means of querying and modifying how a concrete type will be +created or resolved. While the Registry DSL fluent interface provides the main way of explicitly configuring concrete type creation, +the IConfiguredInstance interface is meant to support conventional registration, +configuration attributes, and construction policies.

    +
    
    public interface IConfiguredInstance
    {
        string Name { get; set; }
    
        Type PluggedType { get; }
    
        DependencyCollection Dependencies { get; }
    
        void AddInterceptor(IInterceptor interceptor);
    
        void SetLifecycleTo<T>() where T : ILifecycle, new();
    
        void SetLifecycleTo(ILifecycle lifecycle);
    
        ILifecycle Lifecycle { get; }
    
        ConstructorInfo Constructor { get; set; }
    
        bool HasBuildPlan();
    
        void ClearBuildPlan();
    }
    
    +

    Changing the Instance Lifecycle

    +

    You can override the lifecycle of a single IConfiguredInstance by calling the LifecycleIs() methods and either supplying a +type of ILifecycle or an ILifecycle object. As a quick helper, there are also extension methods for common lifecycles:

    +
    
    IConfiguredInstance instance
        = new ConfiguredInstance(typeof(WidgetHolder));
    
    // Use the SingletonThing lifecycle
    instance.Singleton();
    
    // or supply an ILifecycle type
    instance.SetLifecycleTo<ThreadLocalStorageLifecycle>();
    
    // or supply an ILifecycle object
    instance.SetLifecycleTo(new Lifecycles_Samples.MyCustomLifecycle());
    
    // or override to the default "transient" lifecycle
    instance.DefaultLifecycle();
    
    +

    Reflecting over Constructor Parameters

    +

    To find the constructor function parameters of an IConfiguredInstance, just use this syntax (it's just .Net Reflection):

    +
    
    public class GuyWithArguments
    {
        public GuyWithArguments(IWidget widget, Rule rule)
        {
        }
    }
    
    [Fact]
    public void reflecting_over_constructor_args()
    {
        IConfiguredInstance instance = new SmartInstance<GuyWithArguments>()
            // I'm just forcing it to assign the constructor function
            .SelectConstructor(() => new GuyWithArguments(null, null));
    
        instance.Constructor.GetParameters().Select(x => x.Name)
            .ShouldHaveTheSameElementsAs("widget", "rule");
    }
    
    
    +

    The constructor function selection process takes place as the very first step in creating a build plan and will be +available in any kind of construction policy or configuration attribute on +parameters or properties.

    +

    Reflecting over Setter Properties

    +

    There's a helper extension method off of `IConfiguredInstance' for finding all of the settable properties +that StructureMap can work with as shown below:

    +
    
    public class GuyWithProperties
    {
        public IWidget Widget { get; set; }
        public Rule Rule { get; private set; }
    }
    
    [Fact]
    public void get_settable_properties()
    {
        IConfiguredInstance instance
            = new ConfiguredInstance(typeof(GuyWithProperties));
    
        instance.SettableProperties()
            .Single().Name.ShouldBe("Widget");
    }
    
    
    +

    Working with Dependencies

    +

    The IConfiguredInstance.Dependencies property is a collection of Argument objects that model inline dependencies. A +single Argument can refer to a public property or the parameter in a constructor function and consists of:

    +
      +
    1. Type - the dependency type that would match a property or parameter argument
    2. +
    3. Name - matches the name of a property or parameter argument
    4. +
    5. Dependency - either an object or value of the dependency type or an Instance object that can be used to build the dependency
    6. +
    +

    When StructureMap determines a build plan for a concrete type, it reflects over all the +parameters in the chosen constructor function and then the settable properties looking for any explicitly configured +dependencies by searching in order for:

    +
      +
    1. An exact match by dependency type and name
    2. +
    3. A partial match by dependency type only
    4. +
    5. A partial match by name only
    6. +
    +

    For primitive arguments like strings or numbers, the logic is to search first by name, then by type. All searching is done in +the order that the Argument objects are registered, so do watch the order in which you add arguments. There is a method to +insert new arguments at the front of the list if you need to do any kind of overrides of previous behavior.

    +

    There are several Add() overloads on IConfiguredInstance.Dependencies to add dependencies, or you can use the two helper +methods for constructor parameters and setter properties shown in the following sections.

    +

    Add a Dependency for a Setter Property

    +

    If you already have a PropertyInfo for the concrete type (like you might in a policy or attribute usage) and you want to register an inline dependency, there is the +Dependencies.AddForProperty() method as a convenience. For the actual value of the dependency, it needs to either be an object +that can be cast to the property type or an Instance object that returns a type that can be cast to the property type.

    +

    With a value:

    +
    
    [Fact]
    public void dependency_with_setter_with_value()
    {
        var instance
            = new ConfiguredInstance(typeof(GuyWithProperties));
        var prop = instance.PluggedType.GetProperty("Widget");
    
        var myWidget = new ColorWidget("red");
        instance.Dependencies.AddForProperty(prop, myWidget);
    
        var container = new Container();
    
        container.GetInstance<GuyWithProperties>(instance)
            .Widget.ShouldBeTheSameAs(myWidget);
    }
    
    
    +

    With an Instance for the dependency value:

    +
    
    [Fact]
    public void dependency_with_setter_with_instance()
    {
        var instance
            = new ConfiguredInstance(typeof(GuyWithProperties));
        var prop = instance.PluggedType.GetProperty("Widget");
    
        var dependency = new SmartInstance<AWidget>();
        instance.Dependencies.AddForProperty(prop, dependency);
    
        var container = new Container();
    
        container.GetInstance<GuyWithProperties>(instance)
            .Widget.ShouldBeOfType<AWidget>();
    }
    
    
    +

    Add a Dependency for a Constructor Parameter

    +

    Likewise, you can add a dependency for a specific constructor parameter as either the actual value or an Instance object with the AddForConstructorParameter helper method:

    +
    
    public class GuyWithDatabaseConnection
    {
        public string ConnectionString { get; set; }
    
        public GuyWithDatabaseConnection(string connectionString)
        {
            ConnectionString = connectionString;
        }
    }
    
    [Fact]
    public void specify_dependency_by_constructor_parameter()
    {
        var instance = ConstructorInstance
            .For<GuyWithDatabaseConnection>();
    
        var parameter = instance.Constructor.GetParameters().Single();
        parameter.Name.ShouldBe("connectionString");
    
        var connString =
            "I haven't used sql server in years and I don't remember what connection strings look like";
    
        instance.Dependencies.AddForConstructorParameter(parameter, connString);
    
        var guy = new Container().GetInstance<GuyWithDatabaseConnection>(instance);
    
        guy.ConnectionString.ShouldBe(connString);
    }
    
    
    +

    Adding Interceptors

    +

    You can add interceptors directly to a single IConfiguredInstance with code like this:

    +
    
    
    public class SimpleWidget
    {
        public bool WasIntercepted = false;
    
        public void Intercept()
        {
            WasIntercepted = true;
        }
    }
    
    [Fact]
    public void add_interceptor()
    {
        var interceptor =
            new ActivatorInterceptor<SimpleWidget>(w => w.Intercept());
        var instance = new SmartInstance<SimpleWidget>();
    
        instance.AddInterceptor(interceptor);
    
        new Container().GetInstance<SimpleWidget>(instance)
            .WasIntercepted.ShouldBeTrue();
    }
    
    
    +

    See Interception and Decorators for more information.

    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/registration/configuring-the-raw-model/index.html b/registration/configuring-the-raw-model/index.html deleted file mode 100644 index e79005c..0000000 --- a/registration/configuring-the-raw-model/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - StructureMap - Configuring the Raw Model - - - - - - - - - - - - - - - - - - - -Fork me on GitHub - - - -
    - -
    - - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Fallback Services

    -

    Previous

    Constructor Selection

    - - -
    - - -
    -

    Configuring the Raw Model

    - -
    - -
    - - -

    TODO(Write some content!)

    - - -
    - -
    - - - -
    -
    -
    - - - - - - - - - - - - - - - - diff --git a/registration/constructor-selection/index.html b/registration/constructor-selection/index.html index b874dd4..7fb043c 100644 --- a/registration/constructor-selection/index.html +++ b/registration/constructor-selection/index.html @@ -1,317 +1,152 @@ - + - StructureMap - Constructor Selection - - - - - - - - - - + StructureMap - Constructor Selection + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Constructor Selection Edit on GitHub

    + +
    + +
    + + +

    StructureMap 3.* greatly improves the control over the selection of constructor functions to build concrete types +by allowing users to override the constructor selection on specific Instance's and register custom rules for +selecting constructors to override the basic StructureMap behavior.

    + +

    Greediest Constructor

    +

    If there are multiple public constructor functions on a concrete class, StructureMap's default behavior is to +select the "greediest" constructor, i.e., the constructor function with the most parameters. In the case of two or more +constructor functions with the same number of parameters StructureMap will simply take the first constructor encountered +in that subset of constructors.

    +

    The default constructor selection is demonstrated below:

    +
    
    public class GreaterThanRule : Rule
    {
        public string Attribute { get; set; }
        public int Value { get; set; }
    
        public GreaterThanRule()
        {
        }
    
        public GreaterThanRule(string attribute, int value)
        {
            Attribute = attribute;
            Value = value;
        }
    
        public GreaterThanRule(IWidget widget, Rule rule)
        {
        }
    }
    
    [Fact]
    public void using_the_greediest_ctor()
    {
        var container = new Container(_ =>
        {
            _.ForConcreteType<GreaterThanRule>().Configure
                .Ctor<string>("attribute").Is("foo")
                .Ctor<int>("value").Is(42);
        });
    
        var rule = container.GetInstance<GreaterThanRule>();
        rule.Attribute.ShouldBe("foo");
        rule.Value.ShouldBe(42);
    }
    
    
    +

    New in StructureMap 4.0, the "greediest constructor selection" will bypass any constructor function that requires "simple" arguments +like strings, numbers, or enumeration values that are not explicitly configured for the instance.

    +

    You can see this behavior shown below:

    +
    
    public class DbContext
    {
        public string ConnectionString { get; set; }
    
        public DbContext(string connectionString)
        {
            ConnectionString = connectionString;
        }
    
        public DbContext() : this("default value")
        {
        }
    }
    
    [Fact]
    public void should_bypass_ctor_with_unresolvable_simple_args()
    {
        var container = new Container();
        container.GetInstance<DbContext>()
            .ConnectionString.ShouldBe("default value");
    }
    
    [Fact]
    public void should_use_greediest_ctor_that_has_all_of_simple_dependencies()
    {
        var container = new Container(_ =>
        {
            _.ForConcreteType<DbContext>().Configure
                .Ctor<string>("connectionString").Is("not the default");
        });
    
        container.GetInstance<DbContext>()
            .ConnectionString.ShouldBe("not the default");
    }
    
    
    +

    Explicitly Selecting a Constructor

    +

    To override the constructor selection explicitly on a case by case basis, you +can use the SelectConstructor(Expression) method in the Registry DSL +as shown below:

    +
    
    public class Thingie
    {
        public Thingie(IWidget widget)
        {
            CorrectCtorWasUsed = true;
        }
    
        public bool CorrectCtorWasUsed { get; set; }
    
        public Thingie(IWidget widget, IService service)
        {
            Assert.True(false, "I should not have been called");
        }
    }
    
    [Fact]
    public void override_the_constructor_selection()
    {
        var container = new Container(_ =>
        {
            _.For<IWidget>().Use<AWidget>();
    
            _.ForConcreteType<Thingie>().Configure
    
                // StructureMap parses the expression passed
                // into the method below to determine the
                // constructor
                .SelectConstructor(() => new Thingie(null));
        });
    
        container.GetInstance<Thingie>()
            .CorrectCtorWasUsed
            .ShouldBeTrue();
    }
    
    
    +

    [DefaultConstructor] Attribute

    +

    Alternatively, you can override the choice of constructor function by using the +older [DefaultConstructor] attribute like this:

    +
    
    public class AttributedThing
    {
        // Normally the greediest ctor would be
        // selected, but using this attribute
        // will overrid that behavior
        [DefaultConstructor]
        public AttributedThing(IWidget widget)
        {
            CorrectCtorWasUsed = true;
        }
    
        public bool CorrectCtorWasUsed { get; set; }
    
        public AttributedThing(IWidget widget, IService service)
        {
            Assert.True(false, "I should not have been called");
        }
    }
    
    [Fact]
    public void select_constructor_by_attribute()
    {
        var container = new Container(_ => { _.For<IWidget>().Use<AWidget>(); });
    
        container.GetInstance<AttributedThing>()
            .CorrectCtorWasUsed
            .ShouldBeTrue();
    }
    
    
    +

    Custom Constructor Selection Rule

    +

    If the constructor selection logic isn't what you want, you can systematically +override the selection rules by registering one or more custom IConstructorSelector +policies to a Container. Do note that you can register more than one policy and they +will be executed from last one registered to the first one registered.

    +

    Let's say that you want to control the constructor selection for all concrete +subclasses of an abstract class like this hiearchy:

    +
    
    public abstract class BaseThing
    {
        public BaseThing(IWidget widget)
        {
            CorrectCtorWasUsed = true;
        }
    
        public bool CorrectCtorWasUsed { get; set; }
    
        public BaseThing(IWidget widget, IService service)
        {
            Assert.True(false, "I should not have been called");
        }
    }
    
    public class Thing1 : BaseThing
    {
        public Thing1(IWidget widget) : base(widget)
        {
        }
    
        public Thing1(IWidget widget, IService service) : base(widget, service)
        {
        }
    }
    
    public class Thing2 : BaseThing
    {
        public Thing2(IWidget widget) : base(widget)
        {
        }
    
        public Thing2(IWidget widget, IService service) : base(widget, service)
        {
        }
    }
    
    
    +

    You could create a custom IConstructorSelector like this one below to override +the constructor behavior for only subclasses of BaseThing:

    +
    
    public class ThingCtorRule : IConstructorSelector
    {
        public ConstructorInfo Find(Type pluggedType, DependencyCollection dependencies, PluginGraph graph)
        {
            // if this rule does not apply to the pluggedType,
            // just return null to denote "not applicable"
            if (!pluggedType.CanBeCastTo<BaseThing>()) return null;
    
            return pluggedType.GetConstructor(new[] { typeof(IWidget) });
        }
    }
    
    
    +

    Finally, you can register your custom rule as shown below:

    +
    
    [Fact]
    public void use_a_custom_constructor_selector()
    {
        var container = new Container(_ =>
        {
            _.For<IWidget>().Use<AWidget>();
    
            _.Policies.ConstructorSelector<ThingCtorRule>();
        });
    
        container.GetInstance<Thing1>()
            .CorrectCtorWasUsed.ShouldBeTrue();
    
        container.GetInstance<Thing2>()
            .CorrectCtorWasUsed.ShouldBeTrue();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -325,6 +160,29 @@

    Custom Constructor Selection Rule

    + + diff --git a/registration/existing-objects/index.html b/registration/existing-objects/index.html new file mode 100644 index 0000000..542e1ea --- /dev/null +++ b/registration/existing-objects/index.html @@ -0,0 +1,157 @@ + + + + + + + + StructureMap - Registering Existing Objects + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Registering Existing Objects Edit on GitHub

    + +
    + +
    + +

    It's frequently common to register existing objects with a StructureMap Container and there are +overloads of the Registry.For().Use(object) and Registry.For().Add(object) methods to do just that:

    +
    
    [Fact]
    public void should_be_able_to_resolve_from_the_generic_family_expression()
    {
        var widget = new AWidget();
        var container = new Container(x => x.For(typeof(IWidget)).Use(widget).Named("mine"));
    
        container.GetInstance<IWidget>("mine").ShouldBeTheSameAs(widget);
    }
    
    
    +

    Injecting an existing object into the Container makes it a de facto singleton, but the Container treats it with a +special scope called ObjectLifecycle if you happen to look into the WhatDoIHave() diagnostics.

    +

    StructureMap will attempt to call the IDisposable.Dispose() on any objects that are directly injected into a Container +that implement IDisposable when the Container itself is disposed.

    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/registration/fallback-services/index.html b/registration/fallback-services/index.html index f16b88a..f5e1151 100644 --- a/registration/fallback-services/index.html +++ b/registration/fallback-services/index.html @@ -1,131 +1,162 @@ - + - StructureMap - Fallback Services - - - - - - - - - - + StructureMap - Fallback Services + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Fallback Services Edit on GitHub

    + +
    + +
    + + +

    The following is a technique that was stolen from FubuMVC where we used +the idea of default or "fallback" registrations to make it mechanically simple for the core framework to declare +the default service registrations in the Container for what FubuMVC needed while allowing applications to happily +override specific registrations without having to worry about the order in which the registrations were done.

    +

    To see this in practice, say you have an application that will support client specific modularity that might allow +business clients to override the base StructureMap registrations. This is a perfect use case for +defining the application defaults with UseIfNone() as shown in this example below:

    +
    
    public class DefaultServices : Registry
    {
        public DefaultServices()
        {
            // If nobody else provides a default
            // for IWidget, use AWidget
            For<IWidget>().UseIfNone<AWidget>();
        }
    }
    
    public class SpecificServices : Registry
    {
        public SpecificServices()
        {
            // Use BWidget for IWidget, period
            For<IWidget>().Use<BWidget>();
        }
    }
    
    
    +

    In application usage, you would add the default UseIfNone() registrations, and optionally pick +up additional extension Registry objects from extension assemblies as shown in this example:

    +
    
    [AttributeUsage(AttributeTargets.Assembly)]
    public class ProductModuleAttribute : Attribute
    {
    }
    
    public class ApplicationRegistry : Registry
    {
        public ApplicationRegistry()
        {
            // Use the default services as fallbacks
            IncludeRegistry<DefaultServices>();
    
            // Dependending on what assemblies are present,
            // this might find specific registrations that
            // will take precedence over the UseIfNone()
            // registrations in DefaultServices
            Scan(_ =>
            {
                _.AssembliesFromApplicationBaseDirectory(
                    assem => assem.HasAttribute<ProductModuleAttribute>());
    
                _.LookForRegistries();
            });
        }
    }
    
    [Fact]
    public void see_use_if_none_in_action()
    {
        var container1 = Container.For<DefaultServices>();
    
        // No other registrations, so fallback
        // to AWidget
        container1.GetInstance<IWidget>()
            .ShouldBeOfType<AWidget>();
    
        var container2 = new Container(_ =>
        {
            // add both registries above
            // NOTE: the order does not matter for IWidget
    
            _.IncludeRegistry<SpecificServices>();
            _.IncludeRegistry<DefaultServices>();
        });
    
        // The registration in SpecificServices
        // should win out
        container2.GetInstance<IWidget>()
            .ShouldBeOfType<BWidget>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Resolving Services

    -

    Previous

    Configuring the Raw Model

    - - -
    - - -
    -

    Fallback Services

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Registration Edit on GitHub

    + +
    + +
    + + +

    As of the 3.0 release, StructureMap provides a streamlined fluent interface called the Registry DSL to configure a StructureMap +Container with both explicit registrations and conventional auto-registrations. StructureMap no longer supports Xml configuration or MEF-style attribute configuration -- but there is some facility for rolling your own attribute-based configuration support.

    +

    The first step in using StructureMap is configuring a Container object. The following examples are based on the usage of the Registry DSL.

    +

    Let's say that you have a simple set of services like this:

    +
    
    public interface IBar
    {
    }
    
    public class Bar : IBar
    {
    }
    
    public interface IFoo
    {
    }
    
    public class Foo : IFoo
    {
        public IBar Bar { get; private set; }
    
        public Foo(IBar bar)
        {
            Bar = bar;
        }
    }
    
    
    +

    A simple configuration of a StructureMap Container might then be:

    +
    
    // Example #1 - Create an container instance and directly pass in the configuration.
                var container1 = new Container(c =>
                {
                    c.For<IFoo>().Use<Foo>();
                    c.For<IBar>().Use<Bar>();
                });
    
    // Example #2 - Create an container instance but add configuration later.
                var container2 = new Container();
    
                container2.Configure(c =>
                {
                    c.For<IFoo>().Use<Foo>();
                    c.For<IBar>().Use<Bar>();
                });
    
    +

    Initializing or configuring the container is usually done at application startup and is located as close as possible to the application's entry point. +This place is sometimes referred to as the composition root of the application. +In our example we are composing our application's object graph by connecting abstractions to concrete types.

    +

    We are using the fluent API For<TInterface>().Use<TConcrete>() which registers a default instance for a given plugin type (the TInterface type in this case). In our example we want an new instance of Foo every time we request the abstraction IFoo.

    +

    The recommended way of using the Registry DSL is by defining one or more Registry classes. Typically, you would subclass the Registry class, +then use the Fluent API methods exposed by the Registry class to describe a Container configuration.

    +

    Here's a sample Registry class used to configure the same types as in our previous example:

    +
    
    public class FooBarRegistry : Registry
    {
        public FooBarRegistry()
        {
            For<IFoo>().Use<Foo>();
            For<IBar>().Use<Bar>();
        }
    }
    
    
    +

    When you set up a Container , you need to simply direct the Container to use the configuration in that Registry class.

    +
    
    // Example #1
                var container1 = new Container(new FooBarRegistry());
    
    // Example #2
                var container2 = new Container(c => { c.AddRegistry<FooBarRegistry>(); });
    
    // Example #3 -- create a container for a single Registry
                var container3 = Container.For<FooBarRegistry>();
    
    + +

    In real world applications you also have to deal with repetitive similar registrations. Such registrations are tedious, easy to forget and can be a weak spot in your application. StructureMap provides Auto-Registration and Conventions which mitigates this pain and eases the maintenance burden. StructureMap exposes this feature through the Registry DSL by the Scan method.

    +

    In our example there is an reoccuring pattern, we are connecting the plugin type ISomething to a concrete type Something, meaning IFoo to Foo and IBar to Bar. Wouldn't it be cool if we could write a convention for exactly doing that? Fortunatly StructureMap has already one build in. Let's see how we can create an container with the same configuration as in the above examples.

    +
    
    // Example #1
                var container1 = new Container(c =>
                    c.Scan(scanner =>
                    {
                        scanner.TheCallingAssembly();
                        scanner.WithDefaultConventions();
                    }));
    
    // Example #2
                var container2 = new Container();
    
                container2.Configure(c =>
                    c.Scan(scanner =>
                    {
                        scanner.TheCallingAssembly();
                        scanner.WithDefaultConventions();
                    }));
    
    
    
    +

    We instruct the scanner to scan through the calling assembly with default conventions on. This will find and register the default instance for IFoo and IBar which are obviously the concrete types Foo and Bar. Now whenever you add an additional interface IMoreFoo and a class MoreFoo to your application's code base, it's automatically picked up by the scanner.

    +

    Sometimes classes need to be supplied with some primitive value in its constructor. For example the System.Data.SqlClient.SqlConnection needs to be supplied with the connection string in its constructor. No problem, just set up the value of the constructor argument in the bootstrapping:

    +
    
    var container = new Container(c =>
    {
        //just for demo purposes, normally you don't want to embed the connection string directly into code.
        c.For<IDbConnection>().Use<SqlConnection>().Ctor<string>().Is("YOUR_CONNECTION_STRING");
        //a better way would be providing a delegate that retrieves the value from your app config.    
    });
    
    +

    So far you have seen an couple of ways to work with the Registry DSL and configure a Container object. We have seen examples of configuration that allow us to build objects that don't depend on anything like the Bar class, or do depend on other types like the Foo class needs an instance of IBar. In our last example we have seen configuration for objects that need some primitive types like strings in its constructor function.

    + +
    + +
    + + + +
    +
    +
    @@ -245,6 +148,29 @@

    Registration

    + + diff --git a/registration/inline-dependencies/index.html b/registration/inline-dependencies/index.html index 603042a..fafd2c9 100644 --- a/registration/inline-dependencies/index.html +++ b/registration/inline-dependencies/index.html @@ -1,483 +1,159 @@ - + - StructureMap - Inline Dependencies - - - - - - - - - - + StructureMap - Inline Dependencies + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Inline Dependencies Edit on GitHub

    + +
    + +
    + + +

    While you generally allow StructureMap to just use auto-wiring to fill the dependencies of a concrete type, there are times +when you may want to explicitly configure individual dependencies on a case by case basis. In the case of primitive types +like strings or numbers, StructureMap will not do any auto-wiring, so it's incumbent upon you the user to supply the dependency.

    +

    Let's say we have a simple class called ColorWidget like the following:

    +
    
    public class ColorWidget : IWidget
    {
        public string Color { get; set; }
    
        public ColorWidget(string color)
        {
            Color = color;
        }
    }
    
    
    +

    To register the ColorWidget, you would supply the value of the color parameter to the constructor function like so:

    +
    
    [Fact]
    public void inline_usage_of_primitive_constructor_argument()
    {
        var container = new Container(_ =>
        {
            _.For<IWidget>().Use<ColorWidget>()
                .Ctor<string>().Is("Red");
        });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<ColorWidget>()
            .Color.ShouldBe("Red");
    }
    
    
    + +

    Event Condition Action Rules

    +

    The ability to explicitly define dependencies inline isn't commonly used these days, but was actually one of the very core use cases in the initial versions of StructureMap. One of the first usages of StructureMap in a production application was in a configurable rules engine using an Event-Condition-Action architecture where the conditions and actions were configured in StructureMap as inline dependencies of Rule objects. Using StructureMap's old Xml configuration, we could define rules for new customers by registering rule objects with the container that reused existing condition and action classes in new configurations.

    +

    To make that concrete and establish a sample problem domain, consider these types:

    +
    
    public class SomeEvent
    {
    }
    
    public interface ICondition
    {
        bool Matches(SomeEvent @event);
    }
    
    public interface IAction
    {
        void PerformWork(SomeEvent @event);
    }
    
    public interface IEventRule
    {
        void ProcessEvent(SomeEvent @event);
    }
    
    
    +

    Now, let's move on to seeing how we could use inline dependency configuration to register new rules.

    +

    Constructor Parameters by Type

    +

    First off, let's say that we have a SimpleRule that takes a single condition and action:

    +
    
    public class SimpleRule : IEventRule
    {
        private readonly ICondition _condition;
        private readonly IAction _action;
    
        public SimpleRule(ICondition condition, IAction action)
        {
            _condition = condition;
            _action = action;
        }
    
        public void ProcessEvent(SomeEvent @event)
        {
            if (_condition.Matches(@event))
            {
                _action.PerformWork(@event);
            }
        }
    }
    
    
    +

    Now, since SimpleRule has only a single dependency on both IAction and ICondition, we can create new rules by registering new Instance's +of SimpleRule with different combinations of its dependencies:

    +
    
    public class InlineCtorArgs : Registry
    {
        public InlineCtorArgs()
        {
            // Defining args by type
            For<IEventRule>().Use<SimpleRule>()
                .Ctor<ICondition>().Is<Condition1>()
                .Ctor<IAction>().Is<Action1>()
                .Named("One");
    
            // Pass the explicit values for dependencies
            For<IEventRule>().Use<SimpleRule>()
                .Ctor<ICondition>().Is(new Condition2())
                .Ctor<IAction>().Is(new Action2())
                .Named("Two");
    
            // Use Lambda construction
            For<IEventRule>().Use<SimpleRule>()
                .Ctor<ICondition>().Is(() => new Condition3())
                .Ctor<IAction>().Is("some crazy builder", c => c.GetInstance<Action3>())
                .Named("Three");
    
            // Rarely used, but gives you a "do any crazy thing" option
            // Pass in your own Instance object
            For<IEventRule>().Use<SimpleRule>()
                .Ctor<IAction>().Is(new MySpecialActionInstance());
    
            // Inline configuration of your dependency's dependencies
    
            For<IEventRule>().Use<SimpleRule>()
                .Ctor<ICondition>().IsSpecial(_ => _.Type<BigCondition>().Ctor<int>().Is(100))
    
                // or
                .Ctor<ICondition>().Is(new SmartInstance<BigCondition>().Ctor<int>().Is(100));
        }
    
        public class BigCondition : ICondition
        {
            public BigCondition(int number)
            {
            }
    
            public bool Matches(SomeEvent @event)
            {
                throw new NotImplementedException();
            }
        }
    
        public class MySpecialActionInstance : LambdaInstance<Action3>
        {
            public MySpecialActionInstance()
                : base(() => new Action3())
            {
            }
        }
    }
    
    
    +

    The inline dependency configuration using the Ctor<T>().Is() syntax supports all the common StructureMap configuration options: define by type, by lambdas, by value, or if you really want to risk severe eye strain, you can use your own Instance objects and define the configuration of your dependency's dependencies.

    +

    Specifying the Argument Name

    +

    If for some reason you need to specify an inline constructor argument dependency, and the concrete type has more than one dependency for that type, +you just need to specify the parameter name as shown in this sample:

    +
    
    public class DualConditionRule : IEventRule
    {
        private readonly ICondition _first;
        private readonly ICondition _second;
        private readonly IAction _action;
    
        public DualConditionRule(ICondition first, ICondition second, IAction action)
        {
            _first = first;
            _second = second;
            _action = action;
        }
    
        public void ProcessEvent(SomeEvent @event)
        {
            if (_first.Matches(@event) || _second.Matches(@event))
            {
                _action.PerformWork(@event);
            }
        }
    }
    
    public class DualConditionRuleRegistry : Registry
    {
        public DualConditionRuleRegistry()
        {
            // In this case, because DualConditionRule
            // has two different
            For<IEventRule>().Use<DualConditionRule>()
                .Ctor<ICondition>("first").Is<Condition1>()
                .Ctor<ICondition>("second").Is<Condition2>();
        }
    }
    
    
    +

    Setter Dependencies

    +

    You can also configure setter dependencies with a similar syntax, but with additional options to specify the property name +by using an Expression as shown below:

    +
    
    public class RuleWithSetters : IEventRule
    {
        public ICondition Condition { get; set; }
        public IAction Action { get; set; }
    
        public void ProcessEvent(SomeEvent @event)
        {
            if (Condition.Matches(@event))
            {
                Action.PerformWork(@event);
            }
        }
    }
    
    public class RuleWithSettersRegistry : Registry
    {
        public RuleWithSettersRegistry()
        {
            For<IEventRule>().Use<RuleWithSetters>()
                .Setter<ICondition>().Is<Condition1>()
    
                // or
                .Setter(x => x.Action).Is(new Action1())
    
                // or if you need to specify the name
                .Setter<IAction>("Action").Is<Action2>()
    
                // or you can configure values *after* the object
                // is constructed with the SetProperty method
                .SetProperty(x => x.Action = new Action2());
        }
    }
    
    
    + +

    Enumerable Dependencies

    +

    TODO(show a sample of using enumerable dependencies)

    +

    Programmatic Configuration outside of the Registry DSL

    +

    In some cases, you may want to skip the Registry DSL and go straight for the raw dependencies structures. Let's say that +we're using an open generic type for our rules engine so that we can respond to multiple event types:

    +
    
    public interface IEventRule<TEvent>
    {
        void ProcessEvent(TEvent @event);
    }
    
    public interface ICondition<TEvent>
    {
        bool Matches(TEvent @event);
    }
    
    public class Condition1<TEvent> : ICondition<TEvent>
    {
        public bool Matches(TEvent @event)
        {
            throw new NotImplementedException();
        }
    }
    
    public interface IAction<TEvent>
    {
        void PerformWork(TEvent @event);
    }
    
    public class Action1<TEvent> : IAction<TEvent>
    {
        public void PerformWork(TEvent @event)
        {
            throw new NotImplementedException();
        }
    }
    
    public class EventRule<TEvent> : IEventRule<TEvent>
    {
        private readonly string _name;
        private readonly ICondition<TEvent> _condition;
        private readonly IAction<TEvent> _action;
    
        public EventRule(string name, ICondition<TEvent> condition, IAction<TEvent> action)
        {
            _name = name;
            _condition = condition;
            _action = action;
        }
    
        public string Name
        {
            get { return _name; }
        }
    
        public void ProcessEvent(TEvent @event)
        {
            if (_condition.Matches(@event))
            {
                _action.PerformWork(@event);
            }
        }
    }
    
    
    +

    As an alternative approach, we could build up ConstructorInstance objects to represent our rules like so:

    +
    
    public class OpenTypesRegistry : Registry
    {
        public OpenTypesRegistry()
        {
            var instance = new ConstructorInstance(typeof(EventRule<>));
    
            // By name
            instance.Dependencies.Add("action", typeof(Action1<>));
    
            // Everything else is syntactical sugur over this:
            instance.Dependencies.Add(new Argument
            {
                Type = typeof(IAction<>), // The dependency type
                Name = "action", // The name of the dependency, either
                // a constructor argument name or
                // the name of a setter property
    
                // Specify the actual dependency
                // This can be either a concrete type, the prebuilt value,
                // or an Instance
                Dependency = typeof(Action1<>)
            });
        }
    }
    
    
    +

    It's frequently useful to explicitly configure all the elements for an enumerable argument (arrays, IEnumerable, or IList). +StructureMap provides this syntax to do just that:

    +
    
    public class BigRule : IEventRule
    {
        private readonly IEnumerable<ICondition> _conditions;
        private readonly IEnumerable<IAction> _actions;
    
        public BigRule(IEnumerable<ICondition> conditions, IEnumerable<IAction> actions)
        {
            _conditions = conditions;
            _actions = actions;
        }
    
        public void ProcessEvent(SomeEvent @event)
        {
            if (_conditions.Any(x => x.Matches(@event)))
            {
                _actions.Each(x => x.PerformWork(@event));
            }
        }
    }
    
    public class BigRuleRegistry : Registry
    {
        public BigRuleRegistry()
        {
            For<IEventRule>().Use<BigRule>()
    
                // Each line in the nested closure adds another
                // ICondition to the enumerable dependency in
                // the order in which they are configured
                .EnumerableOf<ICondition>().Contains(_ =>
                {
                    _.Type<Condition1>();
                    _.Type<Condition2>();
                })
                .EnumerableOf<IAction>().Contains(_ =>
                {
                    _.Type<Action1>();
                    _.Object(new Action2());
                });
        }
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -491,6 +167,29 @@

    Programmatic Configuration outside of the Registry DSL

    + + diff --git a/registration/on-missing-family-policies/index.html b/registration/on-missing-family-policies/index.html index c821361..cd8b161 100644 --- a/registration/on-missing-family-policies/index.html +++ b/registration/on-missing-family-policies/index.html @@ -1,315 +1,155 @@ - + - StructureMap - On Missing Family Policies - - - - - - - - - - + StructureMap - On Missing Family Policies + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    On Missing Family Policies Edit on GitHub

    + +
    + +
    + + +

    New for StructureMap 3.0 is a feature to create missing service registrations at runtime based on pluggable rules using the new IFamilyPolicy +interface:

    +
    
    
    public interface IFamilyPolicy
    {
        PluginFamily Build(Type type);
    
        bool AppliesToHasFamilyChecks { get; }
    }
    
    +

    Internally, if you make a request to IContainer.GetInstance(type) for a type that the active Container does not recognize, StructureMap will next +try to apply all the registered IFamilyPolicy policies to create a PluginFamily object for that plugin type that models the registrations for that plugin type, including the default, additional named instances, interceptors or decorators, and lifecycle rules.

    +

    The simplest built in example is the EnumerableFamilyPolicy shown below that can fill in requests for IList<T>, ICollection<T>, and T[] with a collection of all the known registrations of the type T:

    +
    
    public class EnumerableFamilyPolicy : IFamilyPolicy
    {
        public PluginFamily Build(Type type)
        {
            if (EnumerableInstance.IsEnumerable(type))
            {
                var family = new PluginFamily(type);
                family.SetDefault(new AllPossibleInstance(type));
    
                return family;
            }
    
            return null;
        }
    
        public bool AppliesToHasFamilyChecks
        {
            get
            {
                return false;
            }
            
        }
    }
    
    +

    The result of EnumerableFamilyPolicy in action is shown by the acceptance test below:

    +
    
    [Fact]
    public void collection_types_are_all_possible_by_default()
    {
        // NOTE that we do NOT make any explicit registration of
        // IList<IWidget>, IEnumerable<IWidget>, ICollection<IWidget>, or IWidget[]
        var container = new Container(_ =>
        {
            _.For<IWidget>().Add<AWidget>();
            _.For<IWidget>().Add<BWidget>();
            _.For<IWidget>().Add<CWidget>();
        });
    
        // IList<T>
        container.GetInstance<IList<IWidget>>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    
        // ICollection<T>
        container.GetInstance<ICollection<IWidget>>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    
        // Array of T
        container.GetInstance<IWidget[]>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    }
    
    
    +

    See also the Handling Missing Named Instances for runtime determination of named instances within a known plugin type.

    +

    Built In Policies

    +

    StructureMap and StructureMap.AutoMocking use several IFamilyPolicy rules internally to create default behavior. In all cases, any custom +IFamilyPolicy rule that you explicitly add to a Container will be evaluated before the built in policies.

    +
      +
    1. CloseGenericFamilyPolicy - +uses the registration for an open type as a template to create the registrations for a closed type the first time StructureMap encounters +that closed type. See Generic Types for more information.
    2. +
    3. FuncBuildByNamePolicy - +Used internally to create registrations for Func&lt;string, T&gt; builders.
    4. +
    5. EnumerableFamilyPolicy - +Shown above.
    6. +
    7. AutoMockedContainer - +Used by StructureMap.AutoMocking to create registrations on the fly that just return a mock object for the requested plugin type.
    8. +
    +

    Using a Custom IFamilyPolicy" id="custom">

    +

    FubuMVC 2.0 (still unreleased to the public as of yet, but in production usage) uses a custom family policy in its StructureMap +integration to auto-resolve concrete configuration types like the following type:

    +
    
    public class SomeSettings
    {
        public string ThisDirectory { get; set; }
        public string ThatDirectory { get; set; }
    }
    
    
    +

    Unless the system using this object has explicitly registered SomeSettings, we want StructureMap to resolve this object by +using data from the basic .Net appSettings collection to create a SomeSettings object.

    +

    For the sake of the example, assume that you have a functioning service that implements this interface below:

    +
    
    public interface ISettingsProvider
    {
        T SettingsFor<T>() where T : class, new();
    
        object SettingsFor(Type settingsType);
    }
    
    public class AppSettingsProvider : ISettingsProvider
    {
        public T SettingsFor<T>() where T : class, new()
        {
            return SettingsFor(typeof (T)).As<T>();
        }
    
        public object SettingsFor(Type settingsType)
        {
            // The real one reads key/value data from
            // the appSettings and uses FubuCore's
            // model binding to assign data to a new
            // object of settingsType
            return null;
        }
    }
    
    
    +

    Assuming that ISettingsProvider is registered in your StructureMap Container, you could then craft a custom +IFamilyPolicy class like this:

    +
    
    public class SettingPolicy : IFamilyPolicy
    {
        public PluginFamily Build(Type type)
        {
            if (type.Name.EndsWith("Settings") && type.IsConcreteWithDefaultCtor())
            {
                var family = new PluginFamily(type);
                var instance = buildInstanceForType(type);
                family.SetDefault(instance);
    
                return family;
            }
    
            return null;
        }
    
        public bool AppliesToHasFamilyChecks
        {
            get { return true; }
        }
    
    
        private static Instance buildInstanceForType(Type type)
        {
            var instanceType = typeof (SettingsInstance<>).MakeGenericType(type);
            var instance = Activator.CreateInstance(instanceType).As<Instance>();
            return instance;
        }
    }
    
    // SettingsInstance just uses the registered service for ISettingsProvider to
    // build the real object
    public class SettingsInstance<T> : LambdaInstance<T> where T : class, new()
    {
        public SettingsInstance() : base("Building {0} from application settings".ToFormat(typeof (T).FullName),
            c => c.GetInstance<ISettingsProvider>().SettingsFor<T>())
        {
        }
    }
    
    
    +

    SettingPolicy is able to create a registration on the fly for any concrete type whose name ends in "Settings" and has a default, no arg +constructor.

    +

    To use register the custom SettingPolicy, use one of the Registry.Policies.OnMissingFamily() methods:

    +
    
    public class SettingsRegistry : Registry
    {
        public SettingsRegistry()
        {
            For<ISettingsProvider>().Use<AppSettingsProvider>();
            Policies.OnMissingFamily<SettingPolicy>();
        }
    }
    
    
    +

    You can see the real implementation of the SettingPolicy in action in its integration tests on GitHub.

    + +
    + +
    + + + +
    +
    +
    @@ -323,6 +163,29 @@

    Using a Custom IFamilyPolicy" id="custom">

    + + diff --git a/registration/policies/index.html b/registration/policies/index.html new file mode 100644 index 0000000..8905800 --- /dev/null +++ b/registration/policies/index.html @@ -0,0 +1,229 @@ + + + + + + + + StructureMap - Construction Policies + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Construction Policies Edit on GitHub

    + +
    + +
    + + +

    StructureMap has long supported conventional policies for registration based on type scanning +and 3.0 introduced cleaner mechanisms for interception policies. +The 4.0 release extends StructureMap's support for conventional build policies with a new mechanism for altering +how object instances are built based on user created meta-conventions using the IInstancePolicy shown below:

    +
    
    public interface IInstancePolicy
    {
        void Apply(Type pluginType, Instance instance);
    }
    
    +

    These policies are registered as part of the registry dsl with +the Policies.Add() method:

    +
    
    var container = new Container(_ =>
    {
        _.Policies.Add<MyCustomPolicy>();
        // or
        _.Policies.Add(new MyCustomPolicy());
    });
    
    +

    The IInstancePolicy mechanism probably works differently than other IoC containers in that the policy +is applied to the container's underlying configuration model instead of at runtime. Internally, StructureMap lazily creates +a "build plan" for each configured Instance at the first time +that that Instance is built or resolved. As part of creating that build plan, StructureMap runs +all the registered IInstancePolicy objects against the Instance in question to capture any +potential changes before "baking" the build plan into a .Net Expression that is then compiled into a Func +for actual construction.

    +

    The Instance objects will give you access to the types being created, the configured name of the Instance (if any), +the ability to add interceptors and to modify the lifecycle. If you wish to add inline dependencies to +Instances that are built by calling constructor function and setter properties, you may find it easier +to use the ConfiguredInstancePolicy base class as a convenience:

    +
    
    public abstract class ConfiguredInstancePolicy : IInstancePolicy
    {
        public void Apply(Type pluginType, Instance instance)
        {
            var configured = instance as IConfiguredInstance;
            if (configured != null)
            {
                apply(pluginType, configured);
            }
        }
    
        protected abstract void apply(Type pluginType, IConfiguredInstance instance);
    }
    
    +

    For more information, see:

    + +

    Example 1: Constructor arguments

    +

    So let me say upfront that I don't like this approach, but other folks have asked for this ability +over the years. Say that you have some legacy code where many concrete classes have a constructor argument +called "connectionString" that needs to be the connection string to the application database like these classes:

    +
    
    public class DatabaseUser
    {
        public string ConnectionString { get; set; }
    
        public DatabaseUser(string connectionString)
        {
            ConnectionString = connectionString;
        }
    }
    
    public class ConnectedThing
    {
        public string ConnectionString { get; set; }
    
        public ConnectedThing(string connectionString)
        {
            ConnectionString = connectionString;
        }
    }
    
    
    +

    Instead +of explicitly configuring every single concrete class in StructureMap with that inline constructor argument, +we can make a policy to do that in one place:

    +
    
    public class ConnectionStringPolicy : ConfiguredInstancePolicy
    {
        protected override void apply(Type pluginType, IConfiguredInstance instance)
        {
            var parameter = instance.Constructor.GetParameters().FirstOrDefault(x => x.Name == "connectionString");
            if (parameter != null)
            {
                var connectionString = findConnectionStringFromConfiguration();
                instance.Dependencies.AddForConstructorParameter(parameter, connectionString);
            }
        }
    
        // find the connection string from whatever configuration
        // strategy your application uses
        private string findConnectionStringFromConfiguration()
        {
            return "the connection string";
        }
    }
    
    
    +

    Now, let's use that policy against the types that need "connectionString" and see what happens:

    +
    
    [Fact]
    public void use_the_connection_string_policy()
    {
        var container = new Container(_ =>
        {
            _.Policies.Add<ConnectionStringPolicy>();
        });
    
        container.GetInstance<DatabaseUser>()
            .ConnectionString.ShouldBe("the connection string");
    
        container.GetInstance<ConnectedThing>()
            .ConnectionString.ShouldBe("the connection string");
    }
    
    
    +

    Years ago StructureMap was knocked by an "IoC expert" for not having this functionality. I said at the +time -- and still would -- that I would strongly recommend that you simply don't directly +open database connections in more than one or a very few spots in your code anyway. If I did +need to configure a database connection string in multiple concrete classes, I prefer strong typed configuration.

    +

    Example 2: Connecting to Databases based on Parameter Name

    +

    From another common user request over the years, let's say that your application needs to connect to +multiple databases, but your data access service in both cases is an interface called IDatabase, and +that's all the consumers of any database should ever need to know.

    +

    To make this concrete, let's say that our data access is all behind an interface and concrete class pair named +Database/IDatabase like so:

    +
    
    public interface IDatabase { }
    
    public class Database : IDatabase
    {
        public string ConnectionString { get; set; }
    
        public Database(string connectionString)
        {
            ConnectionString = connectionString;
        }
    
        public override string ToString()
        {
            return string.Format("ConnectionString: {0}", ConnectionString);
        }
    }
    
    
    +

    For a registration policy, let's say that the parameter name of an IDatabase dependency +in a constructor function should match an identifier of one of the registered IDatabase services. +That policy would be:

    +
    
    public class InjectDatabaseByName : ConfiguredInstancePolicy
    {
        protected override void apply(Type pluginType, IConfiguredInstance instance)
        {
            instance.Constructor.GetParameters()
                .Where(x => x.ParameterType == typeof(IDatabase))
                .Each(param =>
                {
                    // Using ReferencedInstance here tells StructureMap
                    // to "use the IDatabase by this name"
                    var db = new ReferencedInstance(param.Name);
                    instance.Dependencies.AddForConstructorParameter(param, db);
                });
        }
    }
    
    
    +

    And because I'm generally pretty boring about picking test data names, let's say that two of +our databases are named "red" and "green" with this container registration below:

    +
    
    var container = new Container(_ =>
    {
        _.For<IDatabase>().Add<Database>().Named("red")
            .Ctor<string>("connectionString").Is("*red*");
    
        _.For<IDatabase>().Add<Database>().Named("green")
            .Ctor<string>("connectionString").Is("*green*");
    
        _.Policies.Add<InjectDatabaseByName>();
    });
    
    +

    For more context, the classes that use IDatabase would need to have constructor functions like +these below:

    +
    
    public class BigService
    {
        public BigService(IDatabase green)
        {
            DB = green;
        }
    
        public IDatabase DB { get; set; }
    }
    
    public class ImportantService
    {
        public ImportantService(IDatabase red)
        {
            DB = red;
        }
    
        public IDatabase DB { get; set; }
    }
    
    public class DoubleDatabaseUser
    {
        public DoubleDatabaseUser(IDatabase red, IDatabase green)
        {
            Red = red;
            Green = green;
        }
    
        // Watch out for potential conflicts between setters
        // and ctor params. The easiest thing is to just make
        // setters private
        public IDatabase Green { get; private set; }
    
        public IDatabase Red { get; private set; }
    }
    
    
    +

    Finally, we can exercise our new policy and see it in action:

    +
    
    // ImportantService should get the "red" database
    container.GetInstance<ImportantService>()
        .DB.As<Database>().ConnectionString.ShouldBe("*red*");
    
    // BigService should get the "green" database
    container.GetInstance<BigService>()
        .DB.As<Database>().ConnectionString.ShouldBe("*green*");
    
    // DoubleDatabaseUser gets both
    var user = container.GetInstance<DoubleDatabaseUser>();
    
    user.Green.As<Database>().ConnectionString.ShouldBe("*green*");
    user.Red.As<Database>().ConnectionString.ShouldBe("*red*");
    
    +

    How I prefer to do this - my strong preference would be to use separate interfaces for the different +databases even if that type is just an empty type marker that implements the same base. +I feel like using separate interfaces makes the code easier to trace and understand than trying +to make StructureMap vary dependencies based on naming conventions or what namespace a concrete type +happens to be in. At least now though, you have the choice of my way or using policies based on +naming conventions.

    +

    Example 3: Make objects singletons based on type name

    +

    Unlike the top two examples, this is taken from a strategy that I used in FubuMVC +for its service registration. In that case, we wanted any concrete type whose name ended with +"Cache" to be a singleton in the container registration. With the new IInstancePolicy feature in StructureMap 4, +we could create a new policy class like so:

    +
    
    public class CacheIsSingleton : IInstancePolicy
    {
        public void Apply(Type pluginType, Instance instance)
        {
            if (instance.ReturnedType.Name.EndsWith("Cache"))
            {
                instance.SetLifecycleTo<SingletonLifecycle>();
            }
        }
    }
    
    
    + +Now, let's say that we have an interface named `IWidgets` and a single implementation called `WidgetCache` that +should track our widgets in the application. Using our new policy, we should see `WidgetCache` being +made a singleton: + +
    
    [Fact]
    public void set_cache_to_singleton()
    {
        var container = new Container(_ =>
        {
            _.Policies.Add<CacheIsSingleton>();
    
            _.For<IWidgets>().Use<WidgetCache>();
        });
    
        // The policy is applied *only* at the time
        // that StructureMap creates a "build plan"
        container.GetInstance<IWidgets>()
            .ShouldBeTheSameAs(container.GetInstance<IWidgets>());
    
        // Now that the policy has executed, we
        // can verify that WidgetCache is a SingletonThing
        container.Model.For<IWidgets>().Default
            .Lifecycle.ShouldBeOfType<SingletonLifecycle>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/registration/registry-dsl/index.html b/registration/registry-dsl/index.html index eb57c15..6290e1c 100644 --- a/registration/registry-dsl/index.html +++ b/registration/registry-dsl/index.html @@ -1,191 +1,162 @@ - + - StructureMap - Registry DSL - - - - - - - - - - + StructureMap - Registry DSL + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Registry DSL Edit on GitHub

    + +
    + +
    + + +

    Creating Registry classes is the recommended way of using the Registry DSL.

    +

    The Registry DSL is mostly a fluent interface with some nested closure +usage. The intent of the Registry DSL is to make the configuration process as +error free as possible by using "compiler safe" expressions and defensive +programming to point out missing data.

    +

    The Registry Class

    +

    On all but the smallest systems, the main unit of configuration will probably be +the Registry class. Typically, you would subclass the Registry class, then +use the fluent interface methods exposed by the Registry class to create Container +configuration. Here's a sample Registry class below used to configure an +instance of an IWidget interface:

    +
    
    public class PurpleRegistry : Registry
    {
        public PurpleRegistry()
        {
            For<IWidget>().Use<AWidget>();
        }
    }
    
    
    +

    Including Registries

    +

    The next question is "how does my new Registry class get used?"

    +

    When you set up a Container, you need to simply direct the +Container to use the configuration in that Registry class:

    +
    
    [Fact]
    public void include_a_registry()
    {
        var registry = new Registry();
        registry.IncludeRegistry<YellowBlueRegistry>();
        registry.IncludeRegistry<RedGreenRegistry>();
        registry.IncludeRegistry<PurpleRegistry>();
        // build a container
        var container = new Container(registry);
        // verify the default implementation and total registered implementations
        container.GetInstance<IWidget>().ShouldBeOfType<AWidget>();
        container.GetAllInstances<IWidget>().Count().ShouldBe(5);
    }
    
    
    +

    Use versus Add

    +

    Registrations in the Registry DSL can be done with either Add() or Use() methods, but they have +a different semantic meaning to StructureMap. Add() means add another Instance to this plugin type +while Use() means this one is the default.

    +

    One of the things that is different about StructureMap is that if it has multiple registrations of any +given plugin type, one of these registrations has to be explicitly marked as the default usage for that plugin type +or StructureMap will blow up in the call to Container.GetInstance(). Other IoC tools will magically use +the first registration or the last registration (and some even allow you to configure that behavior). We chose to +make that determination be explicit.

    +

    As of StructureMap 3.0, the WhatDoIHave() output is part of any exception thrown by StructureMap when +it cannot determine a default registration for a requested type if there is more than one registration for that +type.

    +

    If there are multiple calls to Use() for the same plugin type, the last one wins. For more control over this behavior in +modularity scenarios, see Fallback Services and Replace or Clear Out Previous Registrations.

    +

    For().Use()

    +

    To register the default Instance of a type, the syntax is one of the Registry.For().Use() overloads shown below:

    +
    
    public class SettingDefaults : Registry
    {
        public SettingDefaults()
        {
            // If you know the plugin type and its a closed type
            // you can use this syntax
            For<IWidget>().Use<DefaultWidget>();
    
            // By Lambda
            For<IWidget>().Use(() => new DefaultWidget());
    
            // Pre-existing object
            For<IWidget>().Use(new AWidget());
    
            // This is rare now, but still valid
            For<IWidget>().Add<AWidget>().Named("A");
            For<IWidget>().Add<BWidget>().Named("B");
            For<IWidget>().Use("A"); // makes AWidget the default
    
            // Also rare, but you can supply an Instance object
            // yourself for special needs
            For<IWidget>().UseInstance(new MySpecialInstance());
    
            // If you're registering an open generic type
            // or you just have Type objects, use this syntax
            For(typeof (IService<>)).Use(typeof (Service<>));
    
            // This is occasionally useful for generic types
            For(typeof (IService<>)).Use(new MySpecialInstance());
        }
    }
    
    +

    For().Add()

    +

    To register additional Instances for a plugin type, use one of the overloads of For().Add():

    +
    
    public class AdditionalRegistrations : Registry
    {
        public AdditionalRegistrations()
        {
            // If you know the plugin type and its a closed type
            // you can use this syntax
            For<IWidget>().Add<DefaultWidget>();
    
            // By Lambda
            For<IWidget>().Add(() => new DefaultWidget());
    
            // Pre-existing object
            For<IWidget>().Add(new AWidget());
    
            // Also rare, but you can supply an Instance object
            // yourself for special needs
            For<IWidget>().AddInstance(new MySpecialInstance());
    
            // If you're registering an open generic type
            // or you just have Type objects, use this syntax
            For(typeof(IService<>)).Add(typeof(Service<>));
    
            // This is occasionally useful for generic types
            For(typeof(IService<>)).Add(new MySpecialInstance());
        }
    }
    
    +

    Add Many Registrations with For().AddInstances()

    +

    If you need to add several Instances to a single plugin type, the AddInstances() syntax +shown below may be quicker and easier to use:

    +
    
    
    // registry is a StructureMap Registry object
    registry.For<IService>().AddInstances(x =>
    {
        // Equivalent to For<IService>().Add<ColorService>().....
        x.Type<ColorService>().Named("Red").Ctor<string>("color").Is("Red");
    
        // Equivalent to For<IService>().Add(new ColorService("Yellow"))......
        x.Object(new ColorService("Yellow")).Named("Yellow");
    
        // Equivalent to For<IService>().Use(() => new ColorService("Purple"))....
        x.ConstructedBy(() => new ColorService("Purple")).Named("Purple");
    
        x.Type<ColorService>().Named("Decorated").Ctor<string>("color").Is("Orange");
    });
    
    
    +

    Named Instances

    +

    When you have multiple implementations of an interface, it can often be useful to +name instances. To retrieve a specific implementation:

    +
    
    [Fact]
    public void SimpleCaseWithNamedInstance()
    {
        container = new Container(x => { x.For<IWidget>().Add<AWidget>().Named("MyInstance"); });
        // retrieve an instance by name
        var widget = (AWidget)container.GetInstance<IWidget>("MyInstance");
        widget.ShouldNotBeNull();
    }
    
    
    +

    You can also register named instances with the following shorthand:

    +
    
    [Fact]
    public void A_concrete_type_is_available_by_name_when_it_is_added_by_the_shorthand_mechanism()
    {
        IContainer container = new Container(r => r.For<IAddTypes>().AddInstances(x =>
        {
            x.Type<RedAddTypes>().Named("Red");
            x.Type<GreenAddTypes>().Named("Green");
            x.Type<BlueAddTypes>().Named("Blue");
            x.Type<PurpleAddTypes>();
        }));
        // retrieve the instances by name
        container.GetInstance<IAddTypes>("Red").IsType<RedAddTypes>();
        container.GetInstance<IAddTypes>("Green").IsType<GreenAddTypes>();
        container.GetInstance<IAddTypes>("Blue").IsType<BlueAddTypes>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -199,6 +170,29 @@

    Named Instances

    + + diff --git a/registration/setter-injection-policies/index.html b/registration/setter-injection-policies/index.html deleted file mode 100644 index f695e38..0000000 --- a/registration/setter-injection-policies/index.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - StructureMap - Setter Injection Policies - - - - - - - - - - - - - - - - - - - -Fork me on GitHub - - - -
    - -
    - - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    On Missing Family Policies

    -

    Previous

    Changing Configuration at Runtime

    - - -
    - - -
    -

    Setter Injection Policies

    - -
    - -
    - - -

    TODO(Write some content!)

    - - -
    - -
    - - - -
    -
    -
    - - - - - - - - - - - - - - - - diff --git a/release-notes/index.html b/release-notes/index.html index 88d9ae8..d8d3b68 100644 --- a/release-notes/index.html +++ b/release-notes/index.html @@ -1,188 +1,216 @@ - + - StructureMap - Release Notes - - - - - - - - - - + StructureMap - Release Notes + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Release Notes Edit on GitHub

    + +
    + +
    + + +

    StructureMap is attempting to follow a strict SemVer versioning policy.

    +

    Release Notes 4.3

    +

    See the closed GitHub issues for +a complete list of changes.

    +
      +
    • Converts the codebase to using the new dotnet CLI tools
    • +
    • Targets .Net 4.5, Netstandard 1.3, and Netstandard 1.5
    • +
    • Performance improvement for some IContainer.With() usages
    • +
    +

    Release Notes 4.2

    +
      +
    • Added the "disposal lock" feature to prevent a Container from being erroneously disposed
    • +
    +

    Release Notes 4.1

    +

    4.1 was mostly a bugfix release, but also included some new public API calls for type scanning discovery from *.exe files. +See the closed GitHub issues for details.

    +
      +
    • 4.1.2 - Bug fix for GH-461 singleton scoped registrations to a child container
    • +
    • 4.1.1 - Bug fix for "AlwaysUnique" lifecycle within enumerable, inline dependencies
    • +
    +

    Release Notes 4.0.*

    +

    4.0.1 was strictly a bug fix release.

    +

    Release Notes 4.0

    +

    4.0 is a medium sized release that largely builds on the existing 3.0 architecture with significant improvements to conventional +registration via type scanning and several performance improvements as well as some bug fixes.

    +

    The highlights:

    +
      +
    1. We believe that the documentation is finally comprehensive in regards to StructureMap behavior and features
    2. +
    3. StructureMap 4.0 is cross-compiled to .Net 4.0, .Net 4.0 as/ PCL, and as CoreCLR compliant (using the dotnet build profile).
    4. +
    5. The type scanning model (Registry.Scan()) was completely rebuilt to make the model easier to extend and to +optimize application bootstrapping in systems that heavily rely on StructureMap type scanning. See Auto-Registration and Conventions for more information.
    6. +
    7. New diagnostic method specifically for troubleshooting type scanning problems. See Type Scanning Diagnostics for more information.
    8. +
    9. New concept of a "build time Instance convention" to apply much more powerful policies and conventions against your StructureMap registrations +as a whole. See Construction Policies for more information.
    10. +
    11. Runtime performance improvements
    12. +
    13. Hardened StructureMap for multi-threaded usage
    14. +
    15. Performance improvements specifically targeted at usage from within ASP.Net MVC and its particular manner of using IoC tools.
    16. +
    17. Removed the static ObjectFactory facade over the application Container altogether.
    18. +
    19. Enhanced lifecycle support for compliance with ASP.Net MVC6. Nested containers track and dispose AlwaysUnique objects, the new ContainerScoped +lifecyle, and an optional mode to make the root or child containers track Transient disposable objects. See Object Lifecycles and Nested Containers (Per Request/Transaction) for more information.
    20. +
    21. Registry.For<T>().ClearAll() and Registry.For(Type).ClearAll() methods for removing all previous registrations for a type. See +Replace or Clear Out Previous Registrations for more information.
    22. +
    +

    See also the complete list of changes and issues for StructureMap 4.0.

    +

    3.1.*

    +

    Click on any release version to see the list of closed GitHub issues related to any of the 3.1 releases.

    +
      +
    • 3.1.6 -- Optional strong named nugets, bug fixes
    • +
    • 3.1.5 -- Fixes for open generics convention resolution, child containers and policies, naming conflicts between setters and ctor arguments
    • +
    • 3.1.4 -- performance optimization for resolving objects that are registered directly to a Container
    • +
    • 3.1.3 -- named instances registered to child or nested containers
    • +
    • 3.1.2 -- reduces thread contention issues on Container.Configure() calls at runtime
    • +
    • 3.1.1 -- fixed a potentially significant memory leak issue
    • +
    • 3.1.0 -- new functionality on IContext
    • +
    +

    3.0.* Bug Fix Releases

    +

    Click on any release version to see the list of closed GitHub issues related to a bugfix release.

    + +

    Release Notes 3.0

    +
      +
    • The exception messages provide contextual information about what StructureMap was trying to do when things went wrong.

      +
    • +
    • The nested container implementation is vastly improved, much faster (100X in my testing against a big application), and doesn’t have the massive singleton behavior bug from 2.6.*.

      +
    • +
    • All old [Obsolete] 2.5 registration syntax has been removed, and there’s been a major effort to enforce consistency throughout the registration API’s.

      +
    • +
    • The original StructureMap.dll has been broken up into a couple pieces. The main assembly will be targeting PCL compliance thanks to the diligent efforts of Frank Quednau, and that means that Xml configuration and anything to do with ASP.Net has been devolved into separate assemblies and eventually into different Nuget packages. This means that StructureMap will theoretically support WP8 and other versions of .Net for the very first time. God help me.

      +
    • +
    • The strong naming has been removed. My thought is to distribute separate Nuget packages with unsigned versions for sane folks and signed versions for enterprise-y folks.

      +
    • +
    • Lifecycle (scope) can be set individually on each Instance (stupid limitation left over from the very early days) +Constructor selection can be specified per Instance.

      +
    • +
    • Improved diagnostics, both at runtime and for the container configuration.

      +
    • +
    • Improved runtime performance, especially for deep object graphs with inline dependencies (i.e., behavior chains).

      +
    • +
    • The interception model has been completely redesigned.

      +
    • +
    • The ancient attribute model for StructureMap configuration has been mostly removed.

      +
    • +
    • The “Profile” model has been much improved.

      +
    • +
    • The Xml configuration has been heavily streamlined.

      +
    • +
    • Internally, the old PipelineGraph, InstanceFactory, ProfileManager architecture is all gone. The new PipelineGraph implementations just wrap one or more PluginGraph objects, so there’s vastly less data structure shuffling gone on internally.

      +
    • +
    +

    Related links:

    + + +
    + +
    + + + +
    +
    +
    @@ -196,6 +224,29 @@

    Release Notes 3.0

    + + diff --git a/resolving/get-a-service-by-plugin-type-and-name/index.html b/resolving/get-a-service-by-plugin-type-and-name/index.html index d1e4fde..0647168 100644 --- a/resolving/get-a-service-by-plugin-type-and-name/index.html +++ b/resolving/get-a-service-by-plugin-type-and-name/index.html @@ -1,141 +1,117 @@ - + - StructureMap - Get a Service by Plugin Type and Name - - - - - - - - - - + StructureMap - Get a Service by Plugin Type and Name + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Get a Service by Plugin Type and Name Edit on GitHub

    + +
    + +
    + + +

    You can also request a named configuration for a given PluginType by using the overloads of IContainer.GetInstance() that take in a name like this:

    +
    
    [Fact]
    public void get_a_named_instance()
    {
        var container = new Container(x =>
        {
            x.For<IWidget>().Add<AWidget>().Named("A");
            x.For<IWidget>().Add<BWidget>().Named("B");
            x.For<IWidget>().Add<CWidget>().Named("C");
        });
    
        container.GetInstance<IWidget>("A").ShouldBeOfType<AWidget>();
        container.GetInstance<IWidget>("B").ShouldBeOfType<BWidget>();
        container.GetInstance<IWidget>("C").ShouldBeOfType<CWidget>();
    
        // or
    
        container.GetInstance(typeof(IWidget), "A").ShouldBeOfType<AWidget>();
        container.GetInstance(typeof(IWidget), "B").ShouldBeOfType<BWidget>();
        container.GetInstance(typeof(IWidget), "C").ShouldBeOfType<CWidget>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -149,6 +125,29 @@

    Get a Service by Plugin Type and Name

    + + diff --git a/resolving/get-a-service-by-plugintype/index.html b/resolving/get-a-service-by-plugintype/index.html index 603b929..b64e999 100644 --- a/resolving/get-a-service-by-plugintype/index.html +++ b/resolving/get-a-service-by-plugintype/index.html @@ -1,134 +1,117 @@ - + - StructureMap - Get a Service by PluginType - - - - - - - - - - + StructureMap - Get a Service by PluginType + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Get a Service by PluginType Edit on GitHub

    + +
    + +
    + + +

    Requesting the default configured object of a plugin type is done through the IContainer.GetInstance() method shown below:

    +
    
    [Fact]
    public void get_the_default_instance()
    {
        var container = new Container(x => { x.For<IWidget>().Use<AWidget>(); });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<AWidget>();
    
        // or
    
        container.GetInstance(typeof(IWidget))
            .ShouldBeOfType<AWidget>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -142,6 +125,29 @@

    Get a Service by PluginType

    + + diff --git a/resolving/get-all-services-by-plugin-type/index.html b/resolving/get-all-services-by-plugin-type/index.html index ffe6753..0c9ec0b 100644 --- a/resolving/get-all-services-by-plugin-type/index.html +++ b/resolving/get-all-services-by-plugin-type/index.html @@ -1,145 +1,120 @@ - + - StructureMap - Get all Services by Plugin Type - - - - - - - - - - + StructureMap - Get all Services by Plugin Type + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Get all Services by Plugin Type Edit on GitHub

    + +
    + +
    + + +

    Please see Working with Enumerable Types for a lot more information about what's going on behind the +scenes.

    +

    Once in a while you might want to get an enumerable of all the configured objects for a PluginType. That's done with the GetAllInstances() method shown below:

    +
    
    [Fact]
    public void get_all_instances()
    {
        var container = new Container(x =>
        {
            x.For<IWidget>().Add<AWidget>().Named("A");
            x.For<IWidget>().Add<BWidget>().Named("B");
            x.For<IWidget>().Add<CWidget>().Named("C");
        });
    
        container.GetAllInstances<IWidget>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    
        // or
    
        container.GetAllInstances(typeof(IWidget))
            .OfType<IWidget>() // returns an IEnumerable, so I'm casting here
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    }
    
    
    + + +
    + +
    + + + +
    +
    +
    @@ -153,6 +128,29 @@

    Get all Services by Plugin Type

    + + diff --git a/resolving/index.html b/resolving/index.html index e77cbff..06839df 100644 --- a/resolving/index.html +++ b/resolving/index.html @@ -1,119 +1,117 @@ - + - StructureMap - Resolving Services - - - - - - - - - - + StructureMap - Resolving Services + + + + + + + + + + + - + - + Fork me on GitHub - + - - + + -
    - -
    +
    + +
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    + +
    +
    + - +
    -

    Next

    Get a Service by PluginType

    -

    Previous

    Registration

    + +
    +

    Resolving Services Edit on GitHub

    - -
    - - -
    -

    Resolving Services

    - -
    +
    -
    - -

    This will be the easy part of interacting with StructureMap. During application execution, you will need to resolve the services you previously registered in the container. When you ask StructureMap to resolve a service, StructureMap either creates a new object instance or finds the previously built object for the correct Object Lifecycles.

    -

    While in many systems you will probably only resolve the default service of a type or a named instance of a service, there are far more ways to resolve services exposed by StructureMap. The IContainer interface acts as a Service Locator to build and resolve configured services on demand.

    -

    - +
    + +

    This will be the easy part of interacting with StructureMap. During application execution, you will need to resolve the services you previously registered in the container. When you ask StructureMap to resolve a service, StructureMap either creates a new object instance or finds the previously built object for the correct Object Lifecycles.

    +

    While in many systems you will probably only resolve the default service of a type or a named instance of a service, there are far more ways to resolve services exposed by StructureMap. The IContainer interface acts as a Service Locator to build and resolve configured services on demand.

    + -
    +
    -
    +
    - -
    -
    -
    +
    +
    + @@ -127,6 +125,29 @@

    Resolving Services

    + + diff --git a/resolving/passing-arguments-at-runtime/index.html b/resolving/passing-arguments-at-runtime/index.html index dabf469..da263b5 100644 --- a/resolving/passing-arguments-at-runtime/index.html +++ b/resolving/passing-arguments-at-runtime/index.html @@ -1,238 +1,144 @@ - + - StructureMap - Passing Arguments at Runtime - - - - - - - - - - + StructureMap - Passing Arguments at Runtime + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Passing Arguments at Runtime Edit on GitHub

    + +
    + +
    + + +

    Most of the time you will be using StructureMap to build objects based on pre-canned configuration established upfront, but StructureMap +also has the capability to supply dependencies by type or named parameters (if you know the name of constructor arguments or setter property names) to the Container at runtime using the IContainer.With() methods.

    +

    Why would you use this? Here are a few examples from my own usage over the years:

    +
      +
    1. In adhoc code, retrieve some service but override a connectionString constructor argument to connect to a different database
    2. +
    3. If you were to use StructureMap as a configuration intermediary, it becomes common to use this mechanism to swap out configuration on the fly
    4. +
    5. Inject an Entity object into a service (uncommon now, but I did this on several systems years ago)
    6. +
    7. Inject something contextual that can only be built at runtime like an ASP.Net HttpContext into a pre-configured object graph
    8. +
    +

    Now, for some samples. Let's say that we have some classes like so:

    +
    
    public class ColorWidget : IWidget
    {
        public string Color { get; set; }
    
        public ColorWidget(string color)
        {
            Color = color;
        }
    }
    
    public class GuyWithWidgetAndService
    {
        public IWidget Widget { get; set; }
        public IService Service { get; set; }
    
        public GuyWithWidgetAndService(IWidget widget, IService service)
        {
            Widget = widget;
            Service = service;
        }
    }
    
    
    +

    and unless stated otherwise in a sample, a Container configured like so:

    +
    
    var container = new Container(x =>
    {
        x.For<IWidget>().Use<BWidget>();
        x.For<IService>().Use<AService>();
    });
    
    +

    Passing Named Arguments

    +

    The original usage of explicit arguments was to replace primitive arguments to constructor functions like this sample:

    +
    
    [Fact]
    public void supply_named_arguments()
    {
        var container = new Container(x => { x.For<IWidget>().Use<ColorWidget>().Ctor<string>().Is("Red"); });
    
        container.GetInstance<IWidget>()
            .ShouldBeOfType<ColorWidget>()
            .Color.ShouldBe("Red");
    
        container.With("color").EqualTo("Blue")
            .GetInstance<IWidget>()
            .ShouldBeOfType<ColorWidget>()
            .Color.ShouldBe("Blue");
    }
    
    
    +

    The canonical usage is overriding file paths, database connection string, or urls.

    +

    Passing Arguments with a Fluent Interface

    +

    You can invoke the explicit argument passing as a fluent interface starting with +IContainer.With() like the following sample:

    +
    
    var widget = new BWidget();
    var service = new BService();
    
    var guyWithWidgetAndService = container
        .With<IWidget>(widget)
        .With<IService>(service)
        .GetInstance<GuyWithWidgetAndService>();
    
    guyWithWidgetAndService
        .Widget.ShouldBeTheSameAs(widget);
    
    guyWithWidgetAndService
        .Service.ShouldBeTheSameAs(service);
    
    +

    Using a Nested Closure

    +

    If you dislike fluent interfaces or want to pass in a lot of dependencies, +the nested closure syntax might be more usable:

    +
    
    var widget = new BWidget();
    var service = new BService();
    
    var guyWithWidgetAndService = container
        .With(x =>
        {
            x.With<IWidget>(widget);
            x.With<IService>(service);
        })
        .GetInstance<GuyWithWidgetAndService>();
    
    guyWithWidgetAndService
        .Widget.ShouldBeTheSameAs(widget);
    
    guyWithWidgetAndService
        .Service.ShouldBeTheSameAs(service);
    
    +

    Using the ExplicitArguments object

    +

    Finally, you can also pass an object of type ExplicitArguments directly to an overload +of the IContainer.GetInstance() method:

    +
    
    var widget = new BWidget();
    var service = new BService();
    
    var args = new ExplicitArguments();
    args.Set<IWidget>(widget);
    args.Set<IService>(service);
    
    var guyWithWidgetAndService = container
        .GetInstance<GuyWithWidgetAndService>(args);
    
    guyWithWidgetAndService
        .Widget.ShouldBeTheSameAs(widget);
    
    guyWithWidgetAndService
        .Service.ShouldBeTheSameAs(service);
    
    + +
    + +
    + + + +
    +
    +
    @@ -246,6 +152,29 @@

    Using the ExplicitArguments object

    + + diff --git a/resolving/requesting-a-concrete-type/index.html b/resolving/requesting-a-concrete-type/index.html index 32d22dc..31cf124 100644 --- a/resolving/requesting-a-concrete-type/index.html +++ b/resolving/requesting-a-concrete-type/index.html @@ -1,174 +1,129 @@ - + - StructureMap - Auto Resolving Concrete Types - - - - - - - - - - + StructureMap - Auto Resolving Concrete Types + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Auto Resolving Concrete Types Edit on GitHub

    + +
    + +
    + + +

    StructureMap allows you to resolve instances of concrete classes without configuring that concrete type with a few provisos:

    +
      +
    • The concrete type must have at least one public constructor
    • +
    • StructureMap can build all the arguments in the constructor, either because StructureMap has explicit configuration for that dependency or can auto resolve the type
    • +
    • The constructor does not contain any primitive arguments like strings, numbers, or dates because StructureMap assumes those elements are configuration items and not auto resolvable.
    • +
    +

    Let's say we have the following object model, which represents the weather condition for a certain location.

    +
    
    public class Weather
    {
        public Location Location { get; set; }
        public Atmosphere Atmosphere { get; set; }
        public Wind Wind { get; set; }
        public Condition Condition { get; set; }
    
        public Weather(Location location, Atmosphere atmosphere, Wind wind, Condition condition)
        {
            Location = location;
            Atmosphere = atmosphere;
            Wind = wind;
            Condition = condition;
        }
    }
    
    public class Location
    {
        //some properties
    }
    
    public class Atmosphere
    {
        //some properties
    }
    
    public class Wind
    {
        //some properties        
    }
    
    public class Condition
    {
        //some properties        
    }
    
    
    +

    Before we can resolve the concrete Weather type, we need an instance of an Container object. As mentioned earlier, these objects defines a generic GetInstance method which can build us an instance of the Weather type.

    +

    You can create a container yourself or use the statically accessed container.

    +
    
    var container = new Container();
    var weather1 = container.GetInstance<Weather>();
    
    var weather2 = container.GetInstance<Weather>();
    weather2 = container.GetInstance<Weather>(); //short version for above.
    
    +

    The reason why we don't need to supply any configuration is because StructureMap supports a concept called Auto Wiring. It's basically a smart way of building instances of types by looking to the constructors of the requested and all the needed underlaying types. During this inspection StructureMap also uses any provided configuration to help building the requested service or dependency.

    +

    In our example, where there isn't any configuration available, StructureMap looks at the constructor of the requested Weather type. It sees that it depends on four concrete types which all have a default constructor. StructureMap is therefore able to create an instance for all of them and inject them into the Weather constructor. After that the Weather instance is returned to the caller.

    +

    Most of the time you will be mapping abstractions to concrete types, but as you have seen StructureMap supports other use cases as well.

    + +
    + +
    + + + +
    +
    +
    @@ -182,6 +137,29 @@

    Auto Resolving Concrete Types

    + + diff --git a/resolving/try-geting-an-optional-service-by-plugin-type-and-name/index.html b/resolving/try-geting-an-optional-service-by-plugin-type-and-name/index.html index 56b0409..06a982a 100644 --- a/resolving/try-geting-an-optional-service-by-plugin-type-and-name/index.html +++ b/resolving/try-geting-an-optional-service-by-plugin-type-and-name/index.html @@ -1,118 +1,117 @@ - + - StructureMap - Try Geting an Optional Service by Plugin Type and Name - - - - - - - - - - + StructureMap - Try Geting an Optional Service by Plugin Type and Name + + + + + + + + + + + - + - + Fork me on GitHub - + - - + + -
    - -
    +
    + +
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    + +
    + -

    Next

    Passing Arguments at Runtime

    -

    Previous

    Try Getting an Optional Service by Plugin Type

    + +
    +

    Try Geting an Optional Service by Plugin Type and Name Edit on GitHub

    - -
    - - -
    -

    Try Geting an Optional Service by Plugin Type and Name

    - -
    +
    -
    - - -

    TODO(Write some content!)

    - +
    + + +

    Just use the IContainer.TryGetInstance<T>(name) or IContainer.TryGetInstance(Type pluginType, string name) method as shown below:

    +
    
    [Fact]
    public void TryGetInstanceViaNameAndGeneric_ReturnsInstance_WhenTypeFound()
    {
        addColorInstance("Red");
        addColorInstance("Orange");
        addColorInstance("Blue");
    
        // "Orange" exists, so an object should be returned
        var instance = _container.TryGetInstance<Rule>("Orange");
        instance.ShouldBeOfType(typeof(ColorRule));
    }
    
    
    -
    +
    -
    +
    - -
    -
    -
    +
    +
    + @@ -126,6 +125,29 @@

    Try Geting an Optional Service by Plugin Type and Name

    + + diff --git a/resolving/try-getting-an-optional-service-by-plugin-type/index.html b/resolving/try-getting-an-optional-service-by-plugin-type/index.html index c9691e9..8f5e80d 100644 --- a/resolving/try-getting-an-optional-service-by-plugin-type/index.html +++ b/resolving/try-getting-an-optional-service-by-plugin-type/index.html @@ -1,235 +1,140 @@ - + - StructureMap - Try Getting an Optional Service by Plugin Type - - - - - - - - - - + StructureMap - Try Getting an Optional Service by Plugin Type + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Try Getting an Optional Service by Plugin Type Edit on GitHub

    + +
    + +
    + + + +

    In normal usage, if you ask StructureMap for a service and StructureMap doesn't recognize the requested type, the requested name, or know what the default should be for that type, StructureMap will fail fast by throwing an exception rather than returning a null. Sometimes though, you may want to +retrieve an optional service from StructureMap that may or may not be registered in the Container. If that particular registration doesn't exist, you +just want a null value. StructureMap provides first class support for optional dependencies through the usage of the IContainer.TryGetInstance() methods.

    +

    Say you have a simple interface IFoo that may or may not be registered in the Container:

    +
    
    public interface IFoo
    {
    }
    
    public class Foo : IFoo
    {
    }
    
    
    +

    In your own code you might request the IFoo service like the code below, knowing that you'll +take responsibility yourself for building the IFoo service if StructureMap doesn't have a registration +for IFoo:

    +
    
    public class MyFoo : IFoo
    {
    }
    
    [Fact]
    public void real_usage()
    {
        var container = new Container();
    
        // if the container doesn't know about it,
        // I'll build it myself
        var foo = container.TryGetInstance<IFoo>()
                  ?? new MyFoo();
    }
    
    
    +

    Just to make this perfectly clear, if StructureMap has a default registration for IFoo, you get this behavior:

    +
    
    [Fact]
    public void i_have_got_that()
    {
        var container = new Container(_ => _.For<IFoo>().Use<Foo>());
    
        container.TryGetInstance<IFoo>()
            .ShouldNotBeNull();
    
        // -- or --
    
        container.TryGetInstance(typeof(IFoo))
            .ShouldNotBeNull();
    }
    
    
    +

    If StructureMap knows nothing about IFoo, you get a null:

    +
    
    [Fact]
    public void i_do_not_have_that()
    {
        var container = new Container();
    
        container.TryGetInstance<IFoo>()
            .ShouldBeNull();
    
        // -- or --
    
        container.TryGetInstance(typeof(IFoo))
            .ShouldBeNull();
    }
    
    
    +

    Concrete Types

    +

    Since it's not a perfect world, there are some gotchas you need to be aware of. +While StructureMap will happily auto-resolve concrete types that aren't registered, +that does not apply to the TryGetInstance mechanism:

    +
    
    public class ConcreteThing
    {
    }
    
    [Fact]
    public void no_auto_resolution_of_concrete_types()
    {
        var container = new Container();
    
        container.TryGetInstance<ConcreteThing>()
            .ShouldBeNull();
    
        // now register ConcreteThing and do it again
        container.Configure(_ => { _.For<ConcreteThing>().Use<ConcreteThing>(); });
    
        container.TryGetInstance<ConcreteThing>()
            .ShouldNotBeNull();
    }
    
    
    +

    Optional Generic Types

    +

    If you are using open generic types, the TryGetInstance() mechanism can close the open generic registration +to satisfy the optional dependency like this sample:

    +
    
    public interface IThing<T>
    {
    }
    
    public class Thing<T> : IThing<T>
    {
    }
    
    [Fact]
    public void can_try_get_open_type_resolution()
    {
        var container = new Container(_ => { _.For(typeof(IThing<>)).Use(typeof(Thing<>)); });
    
        container.TryGetInstance<IThing<string>>()
            .ShouldBeOfType<Thing<string>>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -243,6 +148,29 @@

    Optional Generic Types

    + + diff --git a/roadmap/index.html b/roadmap/index.html index ab7d72d..5e1dc60 100644 --- a/roadmap/index.html +++ b/roadmap/index.html @@ -1,129 +1,125 @@ - + - StructureMap - Roadmap - - - - - - - - - - + StructureMap - Roadmap + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Roadmap Edit on GitHub

    + +
    + +
    + + +

    StructureMap 3.0 released in early 2014 marked a huge change in the StructureMap internals and public API's. The 4.0 release was +a much smaller release that primarily improved type scanning, diagnostics, and performance. The only breaking changes from 3 to 4 were in custom type scanning conventions, the removal of ObjectFactory, and +the elimination of some obscure configuration API's.

    +

    Please log any suspected bugs or feature requests on StructureMap's GitHub page.

    +

    Ongoing and upcoming work

    +
      +
    1. StructureMap.DynamicInterception
    2. +
    3. StructureMap.AutoFactory
    4. +
    5. Auto Mocking updates and modernization
    6. +
    + +
    + +
    + + + +
    +
    +
    @@ -137,6 +133,29 @@

    Future Plans

    + + diff --git a/setter-injection/index.html b/setter-injection/index.html new file mode 100644 index 0000000..14257ec --- /dev/null +++ b/setter-injection/index.html @@ -0,0 +1,189 @@ + + + + + + + + StructureMap - Setter Injection + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Setter Injection Edit on GitHub

    + +
    + +
    + + + +

    StructureMap can inject dependencies into public setter properties as part of its construction process using the Setter Injection form of Dependency Injection. The StructureMap team strongly recommends using constructor injection wherever possible instead of setter injection. That being said, +there are few cases where setter injection is probably easier (inheritance hierarchies), not to mention legacy or third party tools that +simply cannot support constructor injection cough ASP.Net cough.

    +

    See this discussion from Martin Fowler on Constructor vs Setter Injection.

    +

    If you are having any trouble with setter injection in your StructureMap usage, make sure you're familiar with using Build Plans +to help in troubleshooting

    +

    Explicit Setter Injection with [SetterProperty] Attributes

    +

    The simplest conceptual way to force StructureMap into making public setters mandatory service dependencies by decorating setter properties with the [SetterProperty] attribute like this example:

    +
    
    public class Repository
    {
        private IDataProvider _provider;
    
        // Adding the SetterProperty to a setter directs
        // StructureMap to use this property when
        // constructing a Repository instance
        [SetterProperty]
        public IDataProvider Provider
        {
            set { _provider = value; }
        }
    
        [SetterProperty]
        public bool ShouldCache { get; set; }
    }
    
    +

    Without the [SetterProperty] attributes decorating the setters, StructureMap would ignore the Provider and ShouldCache properties when it builds up a Repository object. With the attributes, StructureMap will try to build and attach values for the two properties as part of object construction.

    +

    If you were to look at StructureMap's "build plan" for the Repository class, you would see something like this:

    +
    +PluginType: StructureMap.Testing.DocumentationExamples.Repository
    +Lifecycle: Transient
    +new Repository()
    +    Set IDataProvider Provider = **Default**
    +    Set Boolean ShouldCache = Value: False
    +
    +

    If you intensely dislike runaway attribute usage, that's okay because there are other ways to enable setter injection in StructureMap.

    +

    Inline Setter Configuration

    +

    Any setter property not configured with [SetterProperty] or the setter policies in the next section can still be filled by StructureMap if an inline dependency is configured matching that setter property as shown in the example below:

    +
    
    public class RuleWithSetters : IEventRule
    {
        public ICondition Condition { get; set; }
        public IAction Action { get; set; }
    
        public void ProcessEvent(SomeEvent @event)
        {
            if (Condition.Matches(@event))
            {
                Action.PerformWork(@event);
            }
        }
    }
    
    public class RuleWithSettersRegistry : Registry
    {
        public RuleWithSettersRegistry()
        {
            For<IEventRule>().Use<RuleWithSetters>()
                .Setter<ICondition>().Is<Condition1>()
    
                // or
                .Setter(x => x.Action).Is(new Action1())
    
                // or if you need to specify the name
                .Setter<IAction>("Action").Is<Action2>()
    
                // or you can configure values *after* the object
                // is constructed with the SetProperty method
                .SetProperty(x => x.Action = new Action2());
        }
    }
    
    
    +

    See also:

    + +

    Setter Injection Policies

    +

    Lastly, you can give StructureMap some criteria for determining which setters should be mandatory dependencies with the Registry.Policies.SetAllProperties() method during Container setup as shown in this example below:

    +
    
    public class ClassWithNamedProperties
    {
        public int Age { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public IGateway Gateway { get; set; }
        public IService Service { get; set; }
    }
    
    [Fact]
    public void specify_setter_policy_and_construct_an_object()
    {
        var theService = new ColorService("red");
    
        var container = new Container(x =>
        {
            x.For<IService>().Use(theService);
            x.For<IGateway>().Use<DefaultGateway>();
    
            x.ForConcreteType<ClassWithNamedProperties>().Configure.Setter<int>().Is(5);
    
            x.Policies.SetAllProperties(
                policy => policy.WithAnyTypeFromNamespace("StructureMap.Testing.Widget3"));
        });
    
        var description = container.Model.For<ClassWithNamedProperties>().Default.DescribeBuildPlan();
        Debug.WriteLine(description);
    
        var target = container.GetInstance<ClassWithNamedProperties>();
        target.Service.ShouldBeTheSameAs(theService);
        target.Gateway.ShouldBeOfType<DefaultGateway>();
    }
    
    
    +

    All calls to Registry.Policies.SetAllProperties() are additive, meaning you can use as many criteria as possible for setter injection.

    +

    Filling Setter's of an Object

    +

    You can run into situations where you'll want StructureMap to fill the setter dependencies of an object that is built outside of your own code and cannot be built by StructureMap itself. Action filter attributes from ASP.Net MVC are an obvious example.

    +

    You're still in luck because StructureMap has the BuildUp(object) method for just this scenario as shown in this example from the unit tests:

    +
    
    public class BuildUpTarget1
    {
        public IGateway Gateway { get; set; }
        public IService Service { get; set; }
    }
    
    [Fact]
    public void create_a_setter_rule_and_see_it_applied_in_BuildUp()
    {
        var theGateway = new DefaultGateway();
        var container = new Container(x =>
        {
            x.For<IGateway>().Use(theGateway);
            x.Policies.SetAllProperties(y => y.OfType<IGateway>());
        });
    
        var target = new BuildUpTarget1();
        container.BuildUp(target);
    
        target.Gateway.ShouldBeTheSameAs(theGateway);
        target.Service.ShouldBeNull();
    }
    
    
    +

    The normal rules for what setters should be filled as described above apply to BuildUp().

    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/software-design-concepts/index.html b/software-design-concepts/index.html index 825eccf..2d127d7 100644 --- a/software-design-concepts/index.html +++ b/software-design-concepts/index.html @@ -1,134 +1,162 @@ - + - StructureMap - Software Design Concepts - - - - - - - - - - + StructureMap - Software Design Concepts + + + + + + + + + + + - + - + Fork me on GitHub - + + + + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Software Design Concepts Edit on GitHub

    + +
    + +
    + + +

    Inversion of Control

    +

    Years ago I consulted for a company that had developed a successful software engine for pricing and analyzing potential energy trades. The next step for them was to adapt their pricing engine so that it could be embedded in other software packages or even a simple spreadsheet so that analysts could quickly try out "what if" scenarios before making any kind of deal. The immediate problem this firm had was that their pricing engine was architected such that the pricing engine business logic directly invoked their proprietary database schema and configuration files. The strategic pricing engine logic was effectively useless without all the rest of their system, so forget embedding the logic into spreadsheet logic.

    +

    With the benefit of hindsight, if we were to build an energy trading pricing engine from scratch, we would probably opt to use the software design concept of Inversion of Control such that the actual pricing logic code would be handed all the pricing metadata it needed to perform its work instead of making the pricing logic reach out to get it. In its most general usage, Inversion of Control simply means that a component is given some sort of dependent data or service or configuration instead of that component having to "know" how to fetch or find that resource.

    +

    An IoC container like StructureMap uses the Inversion of Control concept to simplify your internal services by freeing them from having to know how to find, build, or clean up their dependencies.

    +

    Dependency Injection

    +

    Dependency Injection is nothing more than pushing dependencies of an object into constructor functions or setter properties instead of that object doing everything for itself. If you are strictly using Dependency Injection to fill the dependencies of your classes, your code should have no coupling to StructureMap itself.

    +
    
    public interface IDatabase { }
    
    public class DatabaseUser
    {
        // Using Constructor Injection
        public DatabaseUser(IDatabase database)
        {
        }
    }
    
    public class OtherDatabaseUser
    {
        // Setter Injection
        public IDatabase Database { get; set; }
    }
    
    
    +

    Service Locator

    +

    StructureMap also fills the role of a service locator. In this usage, your code would directly access StructureMap's Container class to build or resolve services upon demand like this sample:

    +
    
    public class ThirdDatabaseUser
    {
        private IDatabase _database;
    
        public ThirdDatabaseUser(IContainer container)
        {
            // This is service location
            _database = container.GetInstance<IDatabase>();
        }
    }
    
    
    +

    Since IoC tools like StructureMap have come onto the software scene, many developers have very badly overused the service locator pattern and many other developers have become very vocal in their distaste for service location. The StructureMap team simply recommends that you favor Dependency Injection wherever possible, but that some service location in your system where you may need more advanced building options or lazy resolution of services is probably just fine.

    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Registration

    -

    Previous

    Features

    - - -
    - - -
    -

    Software Design Concepts

    - -
    - -
    - - -

    TODO(adapt old blog posts here)

    -

    Dependency Injection

    -

    Inversion of Control

    -

    Service Locator

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + +
    + + +
    + + +
    +

    Auto Wiring Edit on GitHub

    + +
    + +
    + + +

    The best way to use an IoC container is to allow "Auto Wiring" to do most of the work for you. IoC Containers like StructureMap are an infrastructure concern, and as such, should be isolated from as much of your code as possible. Before examining Auto Wiring in depth, let's look at a common anti pattern of IoC usage:

    +
    
    // This is the wrong way to use an IoC container.  Do NOT invoke the container from
    // the constructor function.  This tightly couples the ShippingScreenPresenter to
    // the IoC container in a harmful way.  This class cannot be used in either
    // production or testing without a valid IoC configuration.  Plus, you're writing more
    // code
    public ShippingScreenPresenter(IContainer container)
    {
        // It's even worse if you use a static facade to retrieve
        // a service locator!
        _service = container.GetInstance<IShippingService>();
        _repository = container.GetInstance<IRepository>();
    }
    
    +

    Instead of binding ShippingScreenPresenter so tightly to StructureMap and having to explicitly fetch its dependencies, let's switch +it to using StructureMap a little more idiomatically and just exposing a constructor function with the necessary dependencies +as arguments:

    +
    
    // This is the way to write a Constructor Function with an IoC tool
    // Let the IoC container "inject" services from outside, and keep
    // ShippingScreenPresenter ignorant of the IoC infrastructure
    public ShippingScreenPresenter(IShippingService service, IRepository repository)
    {
        _service = service;
        _repository = repository;
    }
    
    +

    As long as a StructureMap Container knows how to resolve the IRepository and +IShippingService interfaces, StructureMap can build ShippingScreenPresenter by using "auto-wiring." All this means is that +instead of forcing you to explicitly configure all the dependencies for ShippingScreenPresenter, StructureMap can infer from +the public constructor function and public property setters +what dependencies ShippingScreenPresenter needs and uses the defaults of both to build it out.

    +

    Looking at the build plan for ShippingScreenPresenter:

    +
    
    public void ShowBuildPlan()
    {
        var container = new Container(_ =>
        {
            _.For<IShippingService>().Use<InternalShippingService>();
            _.For<IRepository>().Use<SimpleRepository>();
        });
    
        // Just proving that we can build ShippingScreenPresenter;)
        container.GetInstance<ShippingScreenPresenter>().ShouldNotBeNull();
    
        var buildPlan = container.Model.For<ShippingScreenPresenter>().Default.DescribeBuildPlan(1);
    
        Debug.WriteLine(buildPlan);
    }
    
    +

    give us:

    +
    +PluginType: StructureMap.Testing.DocumentationExamples.ShippingScreenPresenter
    +Lifecycle: Transient
    +new ShippingScreenPresenter(IShippingService, IRepository)
    +  ┣ IShippingService = **Default**
    +  ┃                     | PluginType: StructureMap.Testing.DocumentationExamples.IShippingService
    +  ┃                     | Lifecycle: Transient
    +  ┃                     | new InternalShippingService()
    +  ┃                    
    +  ┗ IRepository = **Default**
    +               | PluginType: StructureMap.Testing.DocumentationExamples.IRepository
    +               | Lifecycle: Transient
    +               | new SimpleRepository()
    +              
    +
    +

    See Working with Primitive Types for more information on how StructureMap deals with primitive types like numbers, strings, enums, and dates in auto-wiring.

    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Working with the IContext at Build Time

    -

    Previous

    StructureMap Assumptions

    - - -
    - - -
    -

    Auto Wiring

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Registering a Single Instance Against Multiple PluginTypes Edit on GitHub

    + +
    + +
    + + +

    It's not uncommon to want a single instance registration in StructureMap to be mapped to multiple +plugin type interfaces, especially if you have a class that implements multiple role interfaces +to support different consumers.

    +

    As a simplified example, let's say that we have a class named StatefulCache that will govern some kind +of application wide state. Some consumers will only need to read or query data, so we'll create an IReader +interface for that role. Other consumers will only make updates to the StatefulCache, so we'll also have +an IWriter interface as shown below:

    +
    
    public interface IWriter { }
    
    public interface IReader { }
    
    public class StatefulCache : IReader, IWriter
    {
    }
    
    
    +

    What we need from StructureMap is a way to make all requests to either IReader and IWriter +resolve to the same singleton object instance of StatefulCache.

    +

    StructureMap provides the Forward<TFrom, TTo>() mechanism for exactly this purpose:

    +
    
    [Fact]
    public void stateful_cache_serves_multiple_interfaces()
    {
        var container = new Container(_ =>
        {
            // Let's make StatefulCache a SingletonThing in the container
            _.ForConcreteType<StatefulCache>().Configure.Singleton();
    
            _.Forward<StatefulCache, IReader>();
            _.Forward<StatefulCache, IWriter>();
        });
    
        container.GetInstance<IReader>().ShouldBeOfType<StatefulCache>();
        container.GetInstance<IWriter>().ShouldBeOfType<StatefulCache>();
    }
    
    
    +

    And because the syntax has consistently been confusing to users (including me even though I wrote it), +here's how to effect the same registration with lambda registrations:

    +
    
    [Fact]
    public void equivalent()
    {
        var container = new Container(_ =>
        {
            // Let's make StatefulCache a SingletonThing in the container
            _.ForConcreteType<StatefulCache>().Configure.Singleton();
    
            _.For<IReader>().Use(c => c.GetInstance<StatefulCache>());
            _.For<IWriter>().Use(c => c.GetInstance<StatefulCache>());
        });
    
        container.GetInstance<IReader>().ShouldBeOfType<StatefulCache>();
        container.GetInstance<IWriter>().ShouldBeOfType<StatefulCache>();
    }
    
    
    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Profiles and Child Containers

    -

    Previous

    Working with the IContext at Build Time

    - - -
    - - -
    -

    Forwarding Requests for a Type to Another Type

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Handling Missing Named Instances Edit on GitHub

    + +
    + +
    + + +

    Let's say that something asks StructureMap to resolve a named instance of a type that StructureMap does not know about. What if instead +of throwing the exception for an unknown named service, StructureMap could be taught to create a new registration for that type for the name +requested? That's the exact purpose of the Missing Named Instance feature in StructureMap.

    + +

    Using the contrived example from the StructureMap tests for this feature, let's say that you have a simple interface and object implementation like this:

    +
    
    public interface Rule
    {
    }
    
    public class ColorRule : Rule
    {
        public string Color { get; set; }
    
        public ColorRule(string color)
        {
            Color = color;
        }
    }
    
    
    +

    If a user asks the container for a named Rule by a name and that rule doesn't exist, we'll just build +a ColorRule where the Color property should be the name of the Instance requested. That registration +and the usage is shown below:

    +
    
    [Fact]
    public void configure_and_use_missing_instance()
    {
        var container = new Container(x =>
        {
            x.For<Rule>().MissingNamedInstanceIs
                .ConstructedBy(context => new ColorRule(context.RequestedName));
        });
    
        container.GetInstance<Rule>("red")
            .ShouldBeOfType<ColorRule>().Color.ShouldBe("red");
    
        container.GetInstance<Rule>("green")
            .ShouldBeOfType<ColorRule>().Color.ShouldBe("green");
    
        container.GetInstance<Rule>("blue")
            .ShouldBeOfType<ColorRule>().Color.ShouldBe("blue");
    }
    
    
    +

    The missing named instance rules are evaluated last, meaning that the container will still resolve +explicitly registered instances:

    +
    
    [Fact]
    public void does_not_override_explicit_registrations()
    {
        var container = new Container(x =>
        {
            x.For<Rule>().Add(new ColorRule("DarkRed")).Named("red");
    
            x.For<Rule>().MissingNamedInstanceIs
                .ConstructedBy(context => new ColorRule(context.RequestedName));
        });
    
        container.GetInstance<Rule>("red")
            .ShouldBeOfType<ColorRule>()
            .Color.ShouldBe("DarkRed");
    }
    
    
    +

    You also have the ability to explicitly supply an Instance to be evaluated in the missing named instance +resolution:

    +
    
    [Fact]
    public void configure_and_use_missing_instance_by_generic_registration()
    {
        var instance = new LambdaInstance<ColorRule>(c => new ColorRule(c.RequestedName));
    
        var container = new Container(x =>
        {
            x.For(typeof(Rule))
                .MissingNamedInstanceIs(instance);
        });
    
        container.GetInstance<Rule>("red").ShouldBeOfType<ColorRule>().Color.ShouldBe("red");
        container.GetInstance<Rule>("green").ShouldBeOfType<ColorRule>().Color.ShouldBe("green");
        container.GetInstance<Rule>("blue").ShouldBeOfType<ColorRule>().Color.ShouldBe("blue");
    }
    
    
    +

    Multi-Tenancy

    +

    To the best of my recollection, the feature described in this section was designed for a multi-tenancy situation where +we needed to allow the business rules to vary by client, but most clients would still be using the default rules. In our +implemenation, we would make a service location call to the container for the rules by the client id and use the +object returned to calculate the business rules (it was an invoice processing service).

    +

    If our rules logic class structure looked like:

    +
    
    public interface Rule
    {
    }
    
    public class DefaultRule : Rule
    {
    }
    
    public class Client1Rule : Rule
    {
    }
    
    public class Client2Rule : Rule
    {
    }
    
    
    +

    then we could allow client specific rules while still allowing the container to fall through to the default rules +for clients that don't need customized rules:

    +
    
    [Fact]
    public void use_customer_overrides()
    {
        var container = new Container(_ =>
        {
            _.For<Rule>().MissingNamedInstanceIs.Type<DefaultRule>();
    
            _.For<Rule>().Add<Client1Rule>().Named("client1");
            _.For<Rule>().Add<Client2Rule>().Named("client2");
        });
    
        // Client1 & Client2 have explicit registrations
        container.GetInstance<Rule>("client1").ShouldBeOfType<Client1Rule>();
        container.GetInstance<Rule>("client2").ShouldBeOfType<Client2Rule>();
    
        // Client3 has no explicit registration, so falls through to
        // DefaultRule
        container.GetInstance<Rule>("client3").ShouldBeOfType<DefaultRule>();
    }
    
    
    +

    In a more complex usage, maybe you need to pull client specific information from a database or configuration files +to construct the rules object. The code below is a partial sample of how you might use the missing named instance +feature to do data lookups inside of StructureMap:

    +
    
    public interface IClientRulesRepsitory
    {
        ClientRulesData Find(string clientName);
    }
    
    public class ClientRulesData
    {
    }
    
    public class DataUsingRule : Rule
    {
        private readonly ClientRulesData _data;
    
        public DataUsingRule(ClientRulesData data)
        {
            _data = data;
        }
    }
    
    [Fact]
    public void register_by_looking_up_data()
    {
        var container = new Container(_ =>
        {
            _.For<Rule>().MissingNamedInstanceIs.ConstructedBy(
                "Building client rules by looking up client data", c =>
                {
                    var data = c.GetInstance<IClientRulesRepsitory>()
                        .Find(c.RequestedName);
    
                    return new DataUsingRule(data);
                });
        });
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -298,6 +153,29 @@

    Multi-Tenancy

    + + diff --git a/the-container/index.html b/the-container/index.html index 37e54bd..3f456db 100644 --- a/the-container/index.html +++ b/the-container/index.html @@ -1,118 +1,118 @@ - + - StructureMap - The Container - - - - - - - - - - + StructureMap - The Container + + + + + + + + + + + - + - + Fork me on GitHub - + -
    - +
    + -
    - -
    +
    + +
    - - +
    @@ -126,6 +126,29 @@

    The Container

    + + diff --git a/the-container/lambdas/index.html b/the-container/lambdas/index.html new file mode 100644 index 0000000..8cb764b --- /dev/null +++ b/the-container/lambdas/index.html @@ -0,0 +1,168 @@ + + + + + + + + StructureMap - Building Objects with Lambdas + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Building Objects with Lambdas Edit on GitHub

    + +
    + +
    + +

    Instead of allowing StructureMap to build objects directly, you can give a StructureMap Container a Lambda function that can be called to create an object at resolution time.

    +

    Using NHibernate's ISession as an example +of an object that typically has to be built by using an ISessionFactory object:

    +
    
    public interface ISession { }
    
    public interface ISessionFactory
    {
        ISession Build();
    }
    
    +

    If we want to allow StructureMap to control the ISession lifecycle and creation, we have to register a Lambda function as the +means of creating ISession as shown in this example below:

    +
    
    public class SessionFactoryRegistry : Registry
    {
        // Let's not worry about how ISessionFactory is built
        // in this example
        public SessionFactoryRegistry(ISessionFactory factory)
        {
            For<ISessionFactory>().Use(factory);
    
            // Build ISession with a lambda:
            For<ISession>().Use("Build ISession from ISessionFactory", c =>
            {
                // To resolve ISession, I first pull out
                // ISessionFactory from the IContext and use that
                // to build a new ISession. 
                return c.GetInstance<ISessionFactory>().Build();
            });
        }
    }
    
    +

    Lambda registrations can be done with any of the following four signatures:

    +
      +
    1. (Expression<Func<IContext, T>> builder) -- a simple, one line Lambda to build T using IContext
    2. +
    3. (Expression<Func<T>> func) -- a simple, one line Lambda to build T
    4. +
    5. (string description, Func<IContext, T> builder) -- use IContext in your builder Lambda with a user-supplied description for diagnostics
    6. +
    7. (string description, Func<T> builder) -- Supply a complex Func<T> with a user-supplied description for diagnostics
    8. +
    +

    Be very wary of the difference between legal Expression's and more complicated Lambda's that will need to be Func's. It likely doesn't matter to +you the user, but it unfortunately does to StructureMap and .Net itself. If you need to use a more complex Func, you will have +to supply a diagnostic description.

    +

    See Working with the IContext at Build Time for more information.

    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/the-container/lazy-resolution/index.html b/the-container/lazy-resolution/index.html new file mode 100644 index 0000000..9c782de --- /dev/null +++ b/the-container/lazy-resolution/index.html @@ -0,0 +1,177 @@ + + + + + + + + StructureMap - Lazy Resolution + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Lazy Resolution Edit on GitHub

    + +
    + +
    + +

    StructureMap has some built in functionality for "lazy" resolved dependencies, so that instead of your +application service taking a direct dependency on IExpensiveToBuildService that might not be necessary, +you could instead have StructureMap fulfil a dependency on Lazy<IExpensiveToBuildService> or Func<IExpensiveToBuildService> +that could be used to retrieve that expensive service only when it is needed from whatever Container originally created +the parent object.

    +

    Do note that the Lazy<T> and Func<T> approaches respect the lifecycle of the underlying registration rather than +automatically building a unique object instance.

    +

    Also note that Lazy<T> or Func<T> is your best (only) viable approach if you wish to have StructureMap inject bi-directional +relationships.

    +

    Lazy<T>

    +

    Assuming that StructureMap either has an existing configuration for T or can +derive a way to build T, you can just declare a dependency on Lazy<T> like this sample:

    +
    
    public class WidgetLazyUser
    {
        private readonly Lazy<IWidget> _widget;
    
        public WidgetLazyUser(Lazy<IWidget> widget)
        {
            _widget = widget;
        }
    
        public IWidget Widget
        {
            get { return _widget.Value; }
        }
    }
    
    [Fact]
    public void lazy_resolution_in_action()
    {
        var container = new Container(_ =>
        {
            _.For<IWidget>().Use<AWidget>();
        });
    
        container.GetInstance<WidgetLazyUser>()
            .Widget.ShouldBeOfType<AWidget>();
    }
    
    
    +

    Func<T>

    +

    Likewise, you can also declare a dependency on Func<T> with very similar mechanics:

    +
    
    [Fact]
    public void build_a_func_that_returns_a_singleton()
    {
        var container = new Container(x =>
        {
            x.ForSingletonOf<IWidget>().Use<ColorWidget>().Ctor<string>("color").Is("green");
        });
    
        var func = container.GetInstance<Func<IWidget>>();
        var w1 = func();
        var w2 = func();
        var w3 = func();
    
        w1.ShouldBeOfType<ColorWidget>().Color.ShouldBe("green");
    
        w1.ShouldBeTheSameAs(w2);
        w1.ShouldBeTheSameAs(w3);
        w2.ShouldBeTheSameAs(w3);
    }
    
    
    +

    This functionality predates the introduction of the Lazy type to .Net

    +

    Func<string, T>

    +

    Finally, you can also declare a dependency on Func<string, T> that will allow you to lazily +resolve a dependency of T by name:

    +
    
    [Fact]
    public void build_a_func_by_string()
    {
        var container = new Container(x =>
        {
            x.For<IWidget>().Add<ColorWidget>().Ctor<string>("color").Is("green").Named("green");
            x.For<IWidget>().Add<ColorWidget>().Ctor<string>("color").Is("blue").Named("blue");
            x.For<IWidget>().Add<ColorWidget>().Ctor<string>("color").Is("red").Named("red");
        });
    
        var func = container.GetInstance<Func<string, IWidget>>();
        func("green").ShouldBeOfType<ColorWidget>().Color.ShouldBe("green");
    }
    
    
    +

    Bi-relational Dependency Workaround

    +

    StructureMap does not directly support bi-directional dependency relationships -- but will happily tell you in an exception when +you accidentally manage to create one without cratering your AppDomain with a StackOverflowException.

    +

    Either Func<T> or Lazy<T> can be used as a workaround for purposeful bi-directional dependencies between types. The +following is an example of using this strategy:

    +
    
    
    [Singleton]
    public class Thing1
    {
        private readonly Lazy<Thing2> _thing2;
    
        public Thing1(Lazy<Thing2> thing2)
        {
            _thing2 = thing2;
        }
    
        public Thing2 Thing2
        {
            get { return _thing2.Value; }
        }
    }
    
    [Singleton]
    public class Thing2
    {
        public Thing1 Thing1 { get; set; }
    
        public Thing2(Thing1 thing1)
        {
            Thing1 = thing1;
        }
    }
    
    [Fact]
    public void use_lazy_as_workaround_for_bi_directional_dependency()
    {
        var container = new Container();
        var thing1 = container.GetInstance<Thing1>();
        var thing2 = container.GetInstance<Thing2>();
    
        thing1.Thing2.ShouldBeSameAs(thing2);
        thing2.Thing1.ShouldBeSameAs(thing1);
    }
    
    
    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/the-container/nested-containers/index.html b/the-container/nested-containers/index.html index de7f98f..82059b5 100644 --- a/the-container/nested-containers/index.html +++ b/the-container/nested-containers/index.html @@ -1,424 +1,183 @@ - + - StructureMap - Nested Containers (Per Request/Transaction) - - - - - - - - - - + StructureMap - Nested Containers (Per Request/Transaction) + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Nested Containers (Per Request/Transaction) Edit on GitHub

    + +
    + +
    + + + +

    Nested Container's are a powerful feature in StructureMap for service resolution and clean object disposal in the +context of short lived operations. Nested Container's were introduced in version 2.6, but greatly improved in both performance (100X reduction in the time to create a nested container in a large application) and ahem lifecycle +mechanics as a major goal of the 3.0 release.

    +

    History

    +

    The original use case and impetus for building this feature was a simplistic message handling system that dequeued +messages from a Sql Server table (please forget for a second the wisdom of using Sql Server as a queueing system), deserialized +the contents into a .Net object, then created the proper handler object for that message type and executed that handler -- all within +a single transaction. What we wanted at the time was a way to track and clean up all IDisposable objects created during the lifespan of each +transaction. We also wanted a new type of object lifecycle where objects like the NHibernate ISession would be shared by every object +created during the lifetime of the nested container -- even if the ISession was resolved lazily after the intial +resolution of the message handler. The result was what is now the nested container feature +of StructureMap.

    +

    Why Nested Containers over HttpContext or ThreadLocal Scoping?

    +

    Why not just use HttpContext based lifecycles like we've always done in the past? Because HttpContext is not supported by any +type of OWIN web host and will not be a part of ASP.Net vNext. Using a Nested Container per HTTP request is a better, lighterweight way +to scope services to an HTTP request without coupling your code to what will soon be legacy ASP.Net runtime code.

    +

    Who uses it?

    +

    At the time of this document, Nested Container's per HTTP request are supported by frameworks like FubuMVC, +ASP.Net MVC through the StructureMap.MVC5 nuget package, and Web API with the StructureMap.WebApi2 nuget. Several service bus frameworks also use a StructureMap nested container per message invocation including FubuTransportation, +MassTransit, and NServiceBus.

    +

    Creation

    +

    Creating a nested container is as simple as calling the IContainer.GetNestedContainer() method as shown below:

    +
    
    public interface IWorker
    {
        void DoWork();
    }
    
    public class Worker : IWorker, IDisposable
    {
        public void DoWork()
        {
            // do stuff!
        }
    
        public void Dispose()
        {
            // clean up
        }
    }
    
    [Fact]
    public void creating_a_nested_container()
    {
        // From an IContainer object
        var container = new Container(_ => { _.For<IWorker>().Use<Worker>(); });
    
        using (var nested = container.GetNestedContainer())
        {
            // This object is disposed when the nested container
            // is disposed
            var worker = nested.GetInstance<IWorker>();
            worker.DoWork();
        }
    }
    
    
    +

    Lifecycle Rules

    +

    While StructureMap supports several object instance lifecycles out of the box, in idiomatic usage of StructureMap the only common lifecyles are:

    +
      +
    1. Transient - The default lifecycle. A new object is created for a configured Instance on each request to the container
    2. +
    3. Singleton - One instance is constructed and used over the entire Container lifetime
    4. +
    +

    In the context of a Nested Container however, the Transient scoping now applies to the Nested Container itself:

    +
    
    [Fact]
    public void nested_container_behavior_of_transients()
    {
        // "Transient" is the default lifecycle
        // in StructureMap
        var container = new Container(_ => { _.For<IColor>().Use<Green>(); });
    
        // In a normal Container, a "transient" lifecycle
        // Instance will be built up once in every request
        // to the Container
        container.GetInstance<IColor>()
            .ShouldNotBeTheSameAs(container.GetInstance<IColor>());
    
        // From a nested container, the "transient" lifecycle
        // is tracked to the nested container
        using (var nested = container.GetNestedContainer())
        {
            nested.GetInstance<IColor>()
                .ShouldBeTheSameAs(nested.GetInstance<IColor>());
    
            // One more time
            nested.GetInstance<IColor>()
                .ShouldBeTheSameAs(nested.GetInstance<IColor>());
        }
    }
    
    
    +

    Instances scoped to anything but Transient or AlwaysUnique are resolved as normal, but through the parent container:

    +
    
    [Fact]
    public void nested_container_usage_of_singletons()
    {
        var container = new Container(_ => { _.ForSingletonOf<IColorCache>().Use<ColorCache>(); });
    
        var singleton = container.GetInstance<IColorCache>();
    
        // SingletonThing's are resolved from the parent container
        using (var nested = container.GetNestedContainer())
        {
            nested.GetInstance<IColorCache>()
                .ShouldBeTheSameAs(singleton);
        }
    }
    
    
    +

    See Object Lifecycles for more information on supported object lifecycles.

    +

    Overriding Services from the Parent

    +

    A nested container is a new Container object that still retains access to the parent container that created it so that it can +efficiently share registrations, policies, and cached build plans. You can, however, register services into the nested container that override the parent container.

    + +

    The FubuMVC web framework uses a nested container per HTTP request. During an HTTP request, FubuMVC injects services +for the current HTTP request and response to a nested container before creating the actual services that will handle the request. The +FubuMVC mechanics are conceptually similar to this code sample:

    +
    
    [Fact]
    public void overriding_services_in_a_nested_container()
    {
        var container = new Container(_ =>
        {
            _.For<IHttpRequest>().Use<StandInHttpRequest>();
            _.For<IHttpResponse>().Use<StandInHttpResponse>();
        });
    
        var request = new HttpRequest();
        var response = new HttpResponse();
    
        using (var nested = container.GetNestedContainer())
        {
            // Override the HTTP request and response for this
            // nested container
            nested.Configure(_ =>
            {
                _.For<IHttpRequest>().Use(request);
                _.For<IHttpResponse>().Use(response);
            });
    
            var handler = nested.GetInstance<HttpRequestHandler>();
            handler.Request.ShouldBeTheSameAs(request);
            handler.Response.ShouldBeTheSameAs(response);
        }
    
        // Outside the nested container, we still have the original
        // registrations
        container.GetInstance<IHttpRequest>()
            .ShouldBeOfType<StandInHttpRequest>();
    
        container.GetInstance<IHttpResponse>()
            .ShouldBeOfType<StandInHttpResponse>();
    }
    
    
    + +

    When handling requests for new services, a nested container first checks its own configuration if it has its own explicit registration for the request. If the nested container does have an explicit registration, it uses that registration. Otherwise, a nested container will attempt to build +an object using the registered configuration of its parent container.

    + +

    Lazy Resolution

    +

    Nested container object lifecycles equally apply to objects resolved lazily with +either Lazy<T>, Func<T>, or Func<string, T> as shown below:

    +
    
    public class Foo
    {
    }
    
    public class FooHolder
    {
        public IContainer Container { get; set; }
        public Func<Foo> Func { get; set; }
        public Lazy<Foo> Lazy { get; set; }
    
        public FooHolder(IContainer container, Func<Foo> func, Lazy<Foo> lazy)
        {
            Container = container;
            Func = func;
            Lazy = lazy;
        }
    }
    
    [Fact]
    public void service_location_and_container_resolution_inside_nested_containers()
    {
        var container = new Container();
    
        using (var nested = container.GetNestedContainer())
        {
            var holder = nested.GetInstance<FooHolder>();
    
            // The injected IContainer is the nested container
            holder.Container.ShouldBeTheSameAs(nested);
    
            // Func<T> and Lazy<T> values will be built by
            // the nested container w/ the nested container
            // scoping
            var nestedFoo = nested.GetInstance<Foo>();
    
            holder.Func().ShouldBeTheSameAs(nestedFoo);
            holder.Lazy.Value.ShouldBeTheSameAs(nestedFoo);
        }
    }
    
    
    + +

    Profiles

    +

    You can created nested containers from profile containers as shown in the sample below:

    +
    
    [Fact]
    public void nested_container_from_profile_container()
    {
        var container = new Container(x =>
        {
            x.For<IColor>().Use<Red>();
    
            x.Profile("Blue", _ => _.For<IColor>().Use<Blue>());
            x.Profile("Green", _ => _.For<IColor>().Use<Green>());
        });
    
        using (var nested = container.GetProfile("Blue").GetNestedContainer())
        {
            nested.GetInstance<IColor>().ShouldBeOfType<Blue>();
        }
    
        using (var nested = container.GetNestedContainer("Green"))
        {
            nested.GetInstance<IColor>().ShouldBeOfType<Green>();
        }
    }
    
    
    +

    See Profiles and Child Containers for more information about using profiles.

    +

    Disposing Services

    +

    As stated above, disposing a nested container will also dispose all objects created with the default Transient lifecycle by the +nested container that implement the IDisposable interface. That behavior is demonstrated +below:

    +
    
    [Fact]
    public void nested_container_disposal()
    {
        var container = new Container(_ =>
        {
            // A SingletonThing scoped service
            _.ForSingletonOf<IColorCache>().Use<ColorCache>();
    
            // A transient scoped service
            _.For<IColor>().Use<Green>();
    
            // An AlwaysUnique scoped service
            _.For<Purple>().AlwaysUnique();
        });
    
        ColorCache singleton = null;
        Green nestedGreen = null;
        Blue nestedBlue = null;
        Purple nestedPurple = null;
    
        using (var nested = container.GetNestedContainer())
        {
            // SingletonThing's are really built by the parent
            singleton = nested.GetInstance<IColorCache>()
                .ShouldBeOfType<ColorCache>();
    
            nestedGreen = nested.GetInstance<IColor>()
                .ShouldBeOfType<Green>();
    
            nestedBlue = nested.GetInstance<Blue>();
    
            nestedPurple = nested.GetInstance<Purple>();
        }
    
        // Transients created by the Nested Container
        // are disposed
        nestedGreen.WasDisposed.ShouldBeTrue();
        nestedBlue.WasDisposed.ShouldBeTrue();
    
        // Unique's created by the Nested Container
        // are disposed
        nestedPurple.WasDisposed.ShouldBeTrue();
    
        // NOT disposed because it's owned by
        // the parent container
        singleton.WasDisposed.ShouldBeFalse();
    }
    
    
    +

    For the sake of clarity, the classes used in the sample above are:

    +
    
    public interface IColor
    {
    }
    
    public class Red : IColor
    {
    }
    
    public class Purple : Blue { }
    
    public class Blue : IColor, IDisposable
    {
        public bool WasDisposed;
    
        public void Dispose()
        {
            WasDisposed = true;
        }
    }
    
    public class Green : IColor, IDisposable
    {
        public bool WasDisposed;
    
        public void Dispose()
        {
            WasDisposed = true;
        }
    }
    
    public interface IColorCache
    {
    }
    
    public class ColorCache : IColorCache, IDisposable
    {
        public bool WasDisposed;
    
        public void Dispose()
        {
            WasDisposed = true;
        }
    }
    
    
    + +
    + +
    + + + +
    +
    +
    @@ -432,6 +191,29 @@

    Disposing Services

    + + diff --git a/the-container/primitives/index.html b/the-container/primitives/index.html new file mode 100644 index 0000000..52aa666 --- /dev/null +++ b/the-container/primitives/index.html @@ -0,0 +1,172 @@ + + + + + + + + StructureMap - Working with Primitive Types + + + + + + + + + + + + + + + + + + + + +Fork me on GitHub + + + +
    + +
    + + +
    +
    + + + + + +
    +

    Working with Primitive Types Edit on GitHub

    + +
    + +
    + +

    StructureMap treats simple types like strings, numbers of any kind, enumerations, and dates as primitive +types that are completely exempt from auto wiring -- meaning that any +constructor or setter dependencies on these types must be supplied as inline dependencies.

    +

    To make this concrete, if you ask StructureMap to build a concrete type that has dependencies on simple types without +like this example, StructureMap will throw an exception telling you that it cannot build the instance:

    +
    
    public class GuyWithNoDefaultName
    {
        // StructureMap will not use any kind of auto-wiring
        // on name
        public GuyWithNoDefaultName(string name)
        {
        }
    }
    
    [Fact]
    public void cannot_build_simple_arguments()
    {
        var container = new Container();
    
        Exception<StructureMapBuildPlanException>.ShouldBeThrownBy(() =>
        {
            container.GetInstance<GuyWithNoDefaultName>();
        });
    }
    
    
    +

    Part of the exception message thrown in the unit test shown above is the erroneous build plan +showing you that the name parameter has to be defined:

    +
    +	new GuyWithNoDefaultName(String name)
    +	  ┗ String name = Required primitive dependency is not explicitly defined
    +
    +

    We can build GuyWithNoDefaultName by supplying a value for name as I did in the following +sample:

    +
    
    [Fact]
    public void can_build_with_explicit_argument()
    {
        var container = new Container(_ =>
        {
            _.ForConcreteType<GuyWithNoDefaultName>()
                .Configure.Ctor<string>("name").Is("Steve Winwood");
        });
    
        container.GetInstance<GuyWithNoDefaultName>()
            .ShouldNotBeNull();
    }
    
    
    +

    See Construction Policies for an example of using a constructor policy to set a dependency +on a "connectionString" argument in a conventional way.

    +

    Default Values

    +

    As a new feature in the 4.0 release, StructureMap can finally take advantage of default parameter arguments to +derive the values for a primitive argument (or setter value) while still allowing you to explicitly define +that parameter or setter value:

    +
    
    // I was listening to Jim Croce's "I've got a Name" song
    // when I wrote this feature;)
    public class GuyWithName
    {
        public GuyWithName(string name = "Jim Croce")
        {
            Name = name;
        }
    
        public string Name { get; set; }
    }
    
    [Fact]
    public void uses_the_default_value_if_one_exists()
    {
        var container = new Container();
    
        // Should happily build with the default
        // value of 'name'
        container.GetInstance<GuyWithName>()
            .Name.ShouldBe("Jim Croce");
    }
    
    [Fact]
    public void uses_the_default_value_if_one_exists_2()
    {
        var container = new Container(_ =>
        {
            _.ForConcreteType<GuyWithName>();
        });
    
        // Should happily build with the default
        // value of 'name'
        container.GetInstance<GuyWithName>()
            .Name.ShouldBe("Jim Croce");
    }
    
    [Fact]
    public void use_explicit_dependency_if_one_exists()
    {
        var container = new Container(_ =>
        {
            _.ForConcreteType<GuyWithName>()
                .Configure.Ctor<string>("name").Is("Eric Clapton");
        });
    
        container.GetInstance<GuyWithName>()
            .Name.ShouldBe("Eric Clapton");
    }
    
    
    + +
    + +
    + + + +
    +
    +
    + + + + + + + + + + + + + + + + + + diff --git a/the-container/profiles-and-child-containers/index.html b/the-container/profiles-and-child-containers/index.html index 202869d..2889383 100644 --- a/the-container/profiles-and-child-containers/index.html +++ b/the-container/profiles-and-child-containers/index.html @@ -1,131 +1,194 @@ - + - StructureMap - Profiles and Child Containers - - - - - - - - - - + StructureMap - Profiles and Child Containers + + + + + + + + + + + - + - + Fork me on GitHub - + + +
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Profiles and Child Containers Edit on GitHub

    + +
    + +
    + + + +

    The single best source for information about the particulars of child container behavior is to look through the acceptance tests for child containers and +profiles. +from the code in GitHub.

    +

    Child Containers

    +

    The easiest way to explain a child container is to just show it in action:

    +
    
    [Fact]
    public void show_a_child_container_in_action()
    {
        var parent = new Container(_ =>
        {
            _.For<IWidget>().Use<AWidget>();
            _.For<IService>().Use<AService>();
        });
    
        // Create a child container and override the
        // IService registration
        var child = parent.CreateChildContainer();
        child.Configure(_ =>
        {
            _.For<IService>().Use<ChildSpecialService>();
        });
    
        // The child container has a specific registration
        // for IService, so use that one
        child.GetInstance<IService>()
            .ShouldBeOfType<ChildSpecialService>();
    
        // The child container does not have any
        // override of IWidget, so it uses its parent's
        // configuration to resolve IWidget
        child.GetInstance<IWidget>()
            .ShouldBeOfType<AWidget>();
    }
    
    
    +

    Child Containers are a mechanism to make a completely new Container that can override some of the parent Container's registrations but still +fall back to the parent Container to fulfill any request that is not explicitly configured to the child container. The behavior of a child container +in how it resolves services and allows you to override the parent container is very similar to a nested container, but the crucial difference is in how the two concepts handle lifecycles and calling IDisposable.Dispose().

    +

    A couple salient facts about child containers that should (knock on wood) dispel the confusion about when and why to use them versus a nested container:

    +
      +
    1. Child Containers do not change how the default transient lifecycle behaves.
    2. +
    3. Child Containers (and Profiles) were intended to be used to establish different service resolutions for different subsystems of the running system or +to isolate registration overrides for specific types of users or customers (multi-tenancy).
    4. +
    +

    Profiles

    +

    Profiles were completely redesigned as part of the big 3.0 release.

    +

    Profiles are just named child containers that may be configured upfront through Registry configurations. +Profiles are one of the oldest features that date back to the very beginning of StructureMap. Originally profiles were conceived of as +a way to vary StructureMap registrations by development environment as the code moved from running locally on a developer's box to testing +servers to production. While that usage is still valid, it is probably more common to use profiles to define overrides for how StructureMap +should resolve services in different modes of the application (connected vs offline) or different types of system users.

    +
    
    [Fact]
    public void Add_default_instance_with_concrete_type()
    {
        IContainer container = new Container(registry =>
        {
            registry.Profile("something", p =>
            {
                p.For<IWidget>().Use<AWidget>();
                p.For<Rule>().Use<DefaultRule>();
            });
        });
    
        var profile = container.GetProfile("something");
    
        profile.GetInstance<IWidget>().ShouldBeOfType<AWidget>();
        profile.GetInstance<Rule>().ShouldBeOfType<DefaultRule>();
    }
    
    
    +

    Child Containers and Singletons

    +

    If you register a new Instance directly to a child container, that registration is really scoped as a +singleton within the usage of that particular child container:

    +
    
    [Fact]
    public void singletons_to_child_container_are_isolated()
    {
        var parentContainer = new Container(_ =>
        {
            _.For<IDependency>().Use<Dependency>();
        });
    
        var child1 = parentContainer.CreateChildContainer();
        child1.Configure(x =>
        {
            x.ForSingletonOf<IRoot>().Use<Root>();
        });
    
        var child2 = parentContainer.CreateChildContainer();
        child2.Configure(x =>
        {
            x.ForSingletonOf<IRoot>().Use<Root>();
        });
    
        // IRoot is a "singleton" within child1 usage
        child1.GetInstance<IRoot>().ShouldBeSameAs(child1.GetInstance<IRoot>());
    
        // IRoot is a "singleton" within child2 usage
        child2.GetInstance<IRoot>().ShouldBeSameAs(child2.GetInstance<IRoot>());
    
        // but, child1 and child2 both have a different IRoot
        child1.GetInstance<IRoot>()
            .ShouldNotBeTheSameAs(child2.GetInstance<IRoot>());
    }
    
    
    +

    Creating a Nested Container from a Child Container

    +

    It is perfectly valid to create a nested container from a child container for short-lived requests or transactions:

    +
    
    [Fact]
    public void nested_container_from_child()
    {
        var parent = new Container(_ =>
        {
            _.For<IWidget>().Use<AWidget>();
            _.For<IService>().Use<AService>();
        });
    
        // Create a child container and override the
        // IService registration
        var child = parent.CreateChildContainer();
        child.Configure(_ =>
        {
            _.For<IService>().Use<ChildSpecialService>();
        });
    
        using (var nested = child.GetNestedContainer())
        {
            nested.GetInstance<IService>()
                .ShouldBeOfType<ChildSpecialService>();
        }
    }
    
    
    +

    Example: Child Containers in Automated Testing

    +

    My shop has been somewhat successful in writing automated integration tests in a whitebox testing style +where we happily "swap out" a handful of external services with a stubbed service that we can happily control +to either setup system state or measure the interaction of our system with the stub (outgoing emails etc) -- with the canonical +example being a web service that our biggest application has to call for authentication purposes that is frequently unavailable during +our development efforts and not quite reliable even when it is available:.

    +

    That's great, and the stubs certainly help the testing efforts be more productive. Until the stateful stubs we inject in one test end up bleeding into +another test as de facto shared state and making those tests fail in ways that were very difficult to diagnose. To combat this problem of test isolation, +we've introduced the idea of using a clean child container per integration test so that the test harness tools can happily +swap in stubs without impacting other tests in the test suite.

    +

    In action, that usage looks something like this:

    +
    
    public class TheRealService : IService { }
    
    public class StubbedService : IService { }
    
    [Fact]
    public void in_testing()
    {
        var container = new Container(_ =>
        {
            _.For<IService>().Use<TheRealService>();
        });
    
        // Create a new child container for only this test
        var testContainer = container.CreateChildContainer();
    
        // Override a service with a stub that's easier to control
        var stub = new StubbedService();
        testContainer.Inject<IService>(stub);
    
        // Now, continue with the test resolving application
        // services through the new child container....
    }
    
    
    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - - - - -
    -

    Profiles and Child Containers

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Working with Enumerable Types Edit on GitHub

    + +
    + +
    + + +

    While you can certainly use any IEnumerable type as a plugin type with your own explicit configuration, +StructureMap has some built in support for these specific enumerable types:

    +
      +
    1. IEnumerable<T>
    2. +
    3. IList<T>
    4. +
    5. List<T>
    6. +
    7. ICollection<T>
    8. +
    9. T[]
    10. +
    +

    Specifically, if you request one of these types either directly with GetInstance<IList<IWidget>>() or as a declared +dependency in a constructor or setter (new WidgetUser(IList<IWidgets> widgets) for example) and you have no +specific registration for the enumerable types, StructureMap has a built in policy to return all the registered instances +of IWidget in the exact order that the registrations were made to StructureMap.

    +

    Note, if there are not any registrations for whatever T is, you'll get an empty enumeration.

    +

    Here's an acceptance test from the StructureMap codebase that demonstrates this:

    +
    
    [Fact]
    public void collection_types_are_all_possible_by_default()
    {
        // NOTE that we do NOT make any explicit registration of
        // IList<IWidget>, IEnumerable<IWidget>, ICollection<IWidget>, or IWidget[]
        var container = new Container(_ =>
        {
            _.For<IWidget>().Add<AWidget>();
            _.For<IWidget>().Add<BWidget>();
            _.For<IWidget>().Add<CWidget>();
        });
    
        // IList<T>
        container.GetInstance<IList<IWidget>>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    
        // ICollection<T>
        container.GetInstance<ICollection<IWidget>>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    
        // Array of T
        container.GetInstance<IWidget[]>()
            .Select(x => x.GetType())
            .ShouldHaveTheSameElementsAs(typeof(AWidget), typeof(BWidget), typeof(CWidget));
    }
    
    
    +

    And another showing how you can override this behavior with explicit configuration:

    +
    
    [Fact]
    public void override_enumeration_behavior()
    {
        var container = new Container(_ =>
        {
            _.For<IWidget>().Add<AWidget>();
            _.For<IWidget>().Add<BWidget>();
            _.For<IWidget>().Add<CWidget>();
    
            // Explicit registration should have precedence over the default
            // behavior
            _.For<IWidget[]>().Use(new IWidget[] { new DefaultWidget() });
        });
    
        container.GetInstance<IWidget[]>()
            .Single().ShouldBeOfType<DefaultWidget>();
    }
    
    
    +

    Sample Usage: Validation Rules

    +

    One of the ways that I have used the built in IEnumerable handling is for extensible validation rules. Say that we are +building a system to process IWidget objects. As part of processing a widget, we first need to validate that widget with a +series of rules that we might model with the IWidgetValidator interface shown below and used within the main +WidgetProcessor class:

    +
    
    public interface IWidgetValidator
    {
        IEnumerable<string> Validate(IWidget widget);
    }
    
    public class WidgetProcessor
    {
        private readonly IEnumerable<IWidgetValidator> _validators;
    
        public WidgetProcessor(IEnumerable<IWidgetValidator> validators)
        {
            _validators = validators;
        }
    
        public void Process(IWidget widget)
        {
            var validationMessages = _validators.SelectMany(x => x.Validate(widget))
                .ToArray();
    
            if (validationMessages.Any())
            {
                // don't process the widget
            }
        }
    }
    
    
    +

    We could simply configure all of the IWidgetValidator rules in one place with an explicit registration of IEnumerable<IWidgetValidator>, +but what if we need to have an extensibility to add more validation rules later? What if we want to add these additional rules in addon packages? Or we +just don't want to continuously break into the centralized Registry class every single time we add a new validation rule?

    +

    By relying on StructureMap's IEnumerable behavior, we're able to split our IWidgetValidatior registration across multiple Registry classes and that's not infrequently useful to do.

    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Handling Missing Named Instances

    -

    Previous

    Working with Generic Types

    - - -
    - - -
    -

    Working with Enumerable Types

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -
    + + +
    + +
    + + +
    +
    + + + + + +
    +

    Working with the IContext at Build Time Edit on GitHub

    + +
    + +
    + + +

    The IContext usage shown in this topic is certainly not going away in future versions of StructureMap, but if at all possible, the StructureMap team +strongly recommends using Construction Policies to accomplish customized object building instead of relying +on conditional logic using IContext at runtime.

    +

    The IContext interface is what StructureMap uses to expose the current state of the internal "build session" for +the current object creation operation for usage in user-supplied lambda builders or +interceptors. IContext allows you to:

    +
      +
    1. Retrieve other services from the current Container to use in a Lambda
    2. +
    3. "BuildUp" objects with setter dependencies
    4. +
    5. Retrieve all the objects created inside the current build session that could be cast to a certain interface or base class
    6. +
    7. If an object is being built as a dependency to another object, see the parent type
    8. +
    9. See the root type of the top level object that StructureMap is building in this request
    10. +
    +

    The entire IContext interface is shown below:

    +
    
    public interface IContext
    {
        string RequestedName { get; }
    
        void BuildUp(object target);
    
        T GetInstance<T>();
    
        T GetInstance<T>(string name);
    
        object GetInstance(Type pluginType);
    
        object GetInstance(Type pluginType, string instanceKey);
    
        T TryGetInstance<T>() where T : class;
    
        T TryGetInstance<T>(string name) where T : class;
    
        object TryGetInstance(Type pluginType);
    
        object TryGetInstance(Type pluginType, string instanceKey);
    
        IEnumerable<T> All<T>() where T : class;
    
    
        IEnumerable<T> GetAllInstances<T>();
    
        IEnumerable<object> GetAllInstances(Type pluginType);
    
        Type ParentType { get; }
    
        Type RootType { get; }
    }
    
    +

    Example 1: Contextual Logging

    +

    All of the sample code in this example is in Github.

    +

    One of the canonical examples of using IContext is the integration of logging frameworks like NLog or Log4net +that allow you to create logging policies by concrete type. With these tools, you generally have a static class (boo!) +where you ask for the proper logging service for a type of object like this one:

    +
    
    public static class LoggerFactory
    {
        public static Logger LoggerFor(Type type)
        {
            return new Logger(type);
        }
    }
    
    
    +

    Now, say you would want to have the proper Logger injected into every object that StructureMap creates that depends on Logger matching +the concrete type of the object being created. That registration is shown below in a unit test from StructureMap's codebase:

    +
    
    [Fact]
    public void can_happily_use_the_parent_type()
    {
        var container = new Container(x =>
        {
            // AlwaysUnique() is important so that every object created will get
            // their own Logger instead of sharing whichever one is created first
            x.For<Logger>().Use(c => LoggerFactory.LoggerFor(c.ParentType)).AlwaysUnique();
        });
    
        var top = container.GetInstance<LoggedClass1>();
        top.Logger.ParentType.ShouldBe(typeof(LoggedClass1));
        top.Child.Logger.ParentType.ShouldBe(typeof(LoggedClass2));
        top.Child.Child.Logger.ParentType.ShouldBe(typeof(LoggedClass3));
    }
    
    
    +

    Just for fun, here's the equivalent with the new construction policies from 4.0:

    +
    
    public class LoggerConvention : ConfiguredInstancePolicy
    {
        protected override void apply(Type pluginType, IConfiguredInstance instance)
        {
            instance.Constructor
                .GetParameters()
                .Where(param => param.ParameterType == typeof(Logger))
                .Each(param => instance.Dependencies.Add(LoggerFactory.LoggerFor(instance.PluggedType)));
        }
    }
    
    [Fact]
    public void use_logger_convention()
    {
        var container = new Container(_ =>
        {
            _.Policies.Add<LoggerConvention>();
        });
    
        var top = container.GetInstance<LoggedClass1>();
        top.Logger.ParentType.ShouldBe(typeof(LoggedClass1));
        top.Child.Logger.ParentType.ShouldBe(typeof(LoggedClass2));
        top.Child.Child.Logger.ParentType.ShouldBe(typeof(LoggedClass3));
    }
    
    
    +

    The LoggerConvention way of accomplishing the logging integration is technically more code and possibly harder to understand, +but it's significantly more efficient at runtime because the decision about which Logger to use is only done once upfront. +The conventional approach should also be more evident in StructureMap diagnostics.

    +

    Example 2: NHibernate Integration

    +

    It's been several years since I used NHibernate, so I might not have the technical details exactly right here:)

    +

    If you're developing a system with NHibernate managed by StructureMap, you will frequently need to inject +NHibernate's ISession service into your concrete classes. There's a little catch though, to create an ISession object +you have to use NHibernate's ISessionFactory service:

    +
    
    public interface ISession { }
    
    public interface ISessionFactory
    {
        ISession Build();
    }
    
    +

    Sidestepping the issue of how to build an ISessionFactory, here's a possible way to enable a StructureMap +Container to build and resolve dependencies of ISession with a lambda builder:

    +
    
    public class SessionFactoryRegistry : Registry
    {
        // Let's not worry about how ISessionFactory is built
        // in this example
        public SessionFactoryRegistry(ISessionFactory factory)
        {
            For<ISessionFactory>().Use(factory);
    
            // Build ISession with a lambda:
            For<ISession>().Use("Build ISession from ISessionFactory", c =>
            {
                // To resolve ISession, I first pull out
                // ISessionFactory from the IContext and use that
                // to build a new ISession. 
                return c.GetInstance<ISessionFactory>().Build();
            });
        }
    }
    
    + +
    + +
    + + + +
    +
    +
    -
    - -
    - -
    -
    - - -
    -

    StructureMap 3.1.6

    -
    - - - -

    Next

    Forwarding Requests for a Type to Another Type

    -

    Previous

    Auto Wiring

    - - -
    - - -
    -

    Working with the IContext at Build Time

    - -
    - -
    - - -

    TODO(Write some content!)

    - + -
    -
    + + + -