Created
January 9, 2014 15:39
-
-
Save brandonmartinez/8336110 to your computer and use it in GitHub Desktop.
A sample structure map configuration. Requires the StructureMap nuget package (obviously). Can paste into a console app to run and test the demo.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using StructureMap; | |
using StructureMap.Configuration.DSL; | |
namespace StructureMapExample | |
{ | |
/// <summary> | |
/// A registry; I configure these one per "area" of my application. If it's a | |
/// small application, you may have only one registry. This is still the preferred | |
/// approach, apposed to configuring directly in the container | |
/// </summary> | |
internal class SampleRegistryOne : Registry | |
{ | |
#region Constructors | |
public SampleRegistryOne() | |
{ | |
// Setup a default instance (this auto-adds the instance); this is basically for autowiring, but is | |
// the most common syntax when you're doing the repository pattern in my experience | |
For<IRepository>().Use<SampleRepository>().Ctor<string>().Is("Repository One - The Default"); | |
// Add additional instances | |
For<IRepository>().Add<SampleRepository>().Ctor<string>().Is("Repository Two"); | |
For<IRepository>().Add<SampleRepository>().Ctor<string>().Is("Repository Three"); | |
// Sometimes you run into issues where it just can't best-guess the ctor properly, | |
// in those cases, specify the param name | |
For<IRepository>().Add<SampleRepository>().Ctor<string>("name").Is("Repository Four"); | |
// Create a named instance | |
For<IRepository>().Add<SampleRepository>().Ctor<string>("name").Is("Repository Five").Named("SpecialInstance"); | |
// Setup our service. Notice that we don't have to specify constructor arguments | |
// or anything here. This is because a.) we have one constructor, b.) the constructor | |
// has no primitive arguments, and c.) all of the dependencies for it have | |
// been previously wired up | |
For<IService>().Use<SampleService>(); | |
// Add another instance, but this time we have multiple constructor parameters _and_ a primitive. | |
// We'll have to manually wire | |
For<IService>() | |
.Add<SampleMultiConstructorService>() | |
.Ctor<IRepository>() | |
.Is(ctx => ctx.GetInstance<IRepository>("SpecialInstance")) | |
.Ctor<string>("someValue") | |
.Is("Value"); | |
} | |
#endregion | |
} | |
internal static class MyProjectContainer | |
{ | |
#region Properties | |
public static IContainer Container { get; set; } | |
#endregion | |
#region Constructors | |
static MyProjectContainer() | |
{ | |
Container = new Container(); | |
} | |
#endregion | |
} | |
internal interface IRepository | |
{ | |
#region Properties | |
string Name { get; } | |
#endregion | |
} | |
internal class SampleRepository : IRepository | |
{ | |
#region Constructors | |
public SampleRepository(string name) | |
{ | |
Name = name; | |
} | |
#endregion | |
#region IRepository Members | |
public string Name { get; private set; } | |
#endregion | |
} | |
internal interface IService | |
{ | |
#region Properties | |
string RepositoryNames { get; } | |
#endregion | |
} | |
internal class SampleService : IService | |
{ | |
#region Fields | |
protected readonly IEnumerable<IRepository> Repositories; | |
#endregion | |
#region Constructors | |
public SampleService(IEnumerable<IRepository> repositories) | |
{ | |
Repositories = repositories; | |
} | |
#endregion | |
#region IService Members | |
public string RepositoryNames | |
{ | |
get | |
{ | |
return "Repositories: " + string.Join(", ", Repositories.Select(x => x.Name)); | |
} | |
} | |
#endregion | |
} | |
internal class SampleMultiConstructorService : SampleService | |
{ | |
public string SomeValue { get; set; } | |
#region Constructors | |
public SampleMultiConstructorService(IRepository repository, string someValue) : this(new[] | |
{ | |
repository | |
}) | |
{ | |
SomeValue = someValue; | |
} | |
public SampleMultiConstructorService(IEnumerable<IRepository> repositories) : base(repositories) { } | |
#endregion | |
} | |
internal class Program | |
{ | |
#region Static Methods | |
private static void Main(string[] args) | |
{ | |
var container = configureContainer(); | |
#if DEBUG | |
container.AssertConfigurationIsValid(); | |
//Console.WriteLine(container.WhatDoIHave()); | |
#endif | |
Console.WriteLine("Get all configured instances of IService"); | |
var services = container.GetAllInstances<IService>(); | |
foreach(var service in services) | |
{ | |
Console.WriteLine("Service Configured. " + service.RepositoryNames); | |
if(service is SampleMultiConstructorService) | |
{ | |
Console.WriteLine("An additional value is present: " + (service as SampleMultiConstructorService).SomeValue); | |
} | |
} | |
Console.WriteLine("Grabbing something out of the container."); | |
// If you were putting together your own factory, this would be a good way to grab what | |
// was requested of your factory. I'd recommend still assembling your own factory, then | |
// you don't have a hard depedency on StructureMap and could swap out your IoC container | |
// if you choose to | |
var instance = container.GetInstance<IService>(); | |
Console.WriteLine("Instance Type: " + instance.GetType().Name + ". Repositories: " + instance.RepositoryNames); | |
Console.ReadKey(); | |
} | |
private static IContainer configureContainer() | |
{ | |
var container = MyProjectContainer.Container; | |
container.Configure((c) => | |
{ | |
// Add registries here | |
// ORDER MATTERS | |
c.AddRegistry<SampleRegistryOne>(); | |
}); | |
return container; | |
} | |
#endregion | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment