You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<divclass="alert alert-info" role="alert">You need to install <ahref="https://www.nuget.org/packages/StructureMap.Autofactory">StructureMap.Autofactory</a> package to use the functionality described below.</div>
93
93
<p>When you need to implement <ahref="http://en.wikipedia.org/wiki/Abstract_factory_pattern">Abstract Factory</a>, StructureMap offers a way to do it for you. Let's say you have</p>
94
-
<pre><codeclass="language-csharp">
public interface IDummyService
{
 string Name { get; }
}

</code></pre>
94
+
<pre><codeclass="language-csharp">
public interface IDummyService
{
 string Name { get; }
}

</code></pre>
95
95
with implementation
96
-
<pre><codeclass="language-csharp">
public class DummyService : IDummyService
{
 public string Name { get; set; }
}

</code></pre>
96
+
<pre><codeclass="language-csharp">
public class DummyService : IDummyService
{
 public string Name { get; set; }
}

</code></pre>
97
97
<p>Now you declare an interface for your factory:</p>
<p>Any other method that has the return type (i.e. doesn't return <code>void</code>), is treated as a factory method. In addition, if the method name starts with <code>GetNamed</code>, the first method argument is used as the name for the named instance. All the rest arguments are passed as <ahref="/registration/inline-dependencies">explicit arguments</a> to the implementation constructor.</p>
114
114
<p>It is much easier to see it on an example:</p>
115
-
<pre><codeclass="language-csharp">
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>();
}

</code></pre>
115
+
<pre><codeclass="language-csharp">
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>();
}

</code></pre>
116
116
<h2id="custom-convention">Custom convention</h2>
117
117
<p>If the default convention doesn't work for you, you can create and use your custom convention. All you need is to implement <code>IAutoFactoryConventionProvider</code> and use the corresponding <code>CreateFactory</code> overload. <code>IAutoFactoryConventionProvider</code> has a single method to implement:</p>
<p><code>IAutoFactoryMethodDefinition</code> is defined as follows:</p>
121
-
<pre><codeclass="language-csharp">
/// <summary>
/// Describes how AutoFactory should treat the specific method declared in an abstract factory interface.
/// </summary>
public interface IAutoFactoryMethodDefinition
{
 /// <summary>
 /// The method type. See <see cref="AutoFactoryMethodType"/> for possible values.
 /// </summary>
 AutoFactoryMethodType MethodType { get; }

 /// <summary>
 /// The instance type to create.
 /// </summary>
 Type InstanceType { get; }

 /// <summary>
 /// The instance name if available.
 /// </summary>
 string InstanceName { get; }

 /// <summary>
 /// Explicit arguments if available.
 /// </summary>
 ExplicitArguments ExplicitArguments { get; }
}

</code></pre>
121
+
<pre><codeclass="language-csharp">
/// <summary>
/// Describes how AutoFactory should treat the specific method declared in an abstract factory interface.
/// </summary>
public interface IAutoFactoryMethodDefinition
{
 /// <summary>
 /// The method type. See <see cref="AutoFactoryMethodType"/> for possible values.
 /// </summary>
 AutoFactoryMethodType MethodType { get; }

 /// <summary>
 /// The instance type to create.
 /// </summary>
 Type InstanceType { get; }

 /// <summary>
 /// The instance name if available.
 /// </summary>
 string InstanceName { get; }

 /// <summary>
 /// Explicit arguments if available.
 /// </summary>
 ExplicitArguments ExplicitArguments { get; }
}

</code></pre>
<li>Description of any Lambda or <code>Func<T></code> that is used to construct the Instance object</li>
102
102
</ol>
103
103
<p>To retrieve the build plan for a configured Instance, use the queryable <code>Container.Model</code> to find the configured Instance and call <code>DescribeBuildPlan(int maxDepth)</code> to get the textual report as shown in this sample below:</p>
<p>The result of the code above is this textual representation of how StructureMap will build and/or resolve the default of the <code>IDevice</code> plugin type:</p>
<p>See <ahref="/diagnostics/using-the-container-model">Using the Container Model</a> for more information on using <code>Container.Model</code>.</p>
121
121
<p>You can find many more examples of finding the build plan description from <code>Container.Model</code> from the <ahref="https://github.com/structuremap/structuremap/blob/master/src/StructureMap.Testing/Diagnostics/BuildPlanVisualizationSmokeTester.cs">unit tests in the StructureMap codebase</a>.</p>
<p>The deployments still frequently failed, but we were able to spot <strong>and diagnose</strong> 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.</p>
100
100
<p>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 <code>[ValidationMethod]</code> attribute as shown below:</p>
101
-
<pre><codeclass="language-csharp">
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
 }
}
</code></pre>
101
+
<pre><codeclass="language-csharp">
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
 }
}
</code></pre>
102
102
<p>Used in conjunction with <ahref="/diagnostics/validating-container-configuration">StructureMap's ability to validate a container</a>, you can use this technique to quickly support environment tests embedded into your system code.</p>
0 commit comments