Created
May 5, 2012 11:42
-
-
Save Rookian/2601765 to your computer and use it in GitHub Desktop.
Ctor With Runtime Values And Service Dependencies
This file contains 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
class Program | |
{ | |
static void Main() | |
{ | |
ObjectFactory.Initialize(x => | |
{ | |
x.For<IExecuter>().Use<Executer>(); | |
x.For<IService>().Use<Service>(); | |
x.For<Func<Data, IExecuter>>().Use(data => ObjectFactory.With(data.GetType(), data).GetInstance<IExecuter>()); | |
}); | |
var consumer = ObjectFactory.GetInstance<FormularWindow>(); | |
consumer.InvokeExecuter(); | |
Console.ReadLine(); | |
} | |
} | |
public class Executer : IExecuter | |
{ | |
readonly Data _data; | |
readonly IService _service; | |
public Executer(Data data, IService service) | |
{ | |
_data = data; | |
_service = service; | |
} | |
public void Execute() | |
{ | |
Console.WriteLine("I consume the data object with id {0}", _data.Id); | |
_service.DoAnything(); | |
} | |
} | |
public class Service : IService | |
{ | |
public void DoAnything() | |
{ | |
Console.WriteLine("I do anything else"); | |
} | |
} | |
public class FormularWindow | |
{ | |
readonly Func<Data, IExecuter> _createExecuter; | |
// Mixing service dependencies and run time values in ctor | |
public FormularWindow(Func<Data, IExecuter> createExecuter) | |
{ | |
_createExecuter = createExecuter; | |
} | |
public void InvokeExecuter() | |
{ | |
var selectedData = GetSelectedData(); | |
var executer = _createExecuter(selectedData); | |
executer.Execute(); | |
} | |
private static Data GetSelectedData() | |
{ | |
return new Data { Id = 4, Description = "Test" }; | |
} | |
} | |
public class Data | |
{ | |
public int Id { get; set; } | |
public string Description { get; set; } | |
} | |
public interface IExecuter | |
{ | |
void Execute(); | |
} | |
public interface IService | |
{ | |
void DoAnything(); | |
} | |
############################################################################################################# | |
For me it seems there is no way of using an interface for the factory instead of a Func. And if you use the | |
factory you still end using Func in the factory. | |
############################################################################################################# | |
class Program | |
{ | |
static void Main() | |
{ | |
var container = new Container(); | |
container.Configure(x=> | |
{ | |
x.For<IService>().Use<Service>(); | |
x.For<IExecuterFactory>().Use<ExecuterFactory>(); | |
x.For<IExecuter>().Use<Executer>(); | |
x.For<Func<Data, IExecuter>>().Use(data => container.With(data.GetType(), data).GetInstance<IExecuter>()); | |
}); | |
var consumer = container.GetInstance<FormularWindow>(); | |
consumer.InvokeExecuter(); | |
Console.ReadLine(); | |
} | |
} | |
internal class ExecuterFactory : IExecuterFactory | |
{ | |
private readonly Func<Data, IExecuter> _createExecuter; | |
public ExecuterFactory(Func<Data, IExecuter> createExecuter) | |
{ | |
_createExecuter = createExecuter; | |
} | |
public IExecuter Create(Data data) | |
{ | |
return _createExecuter(data); | |
} | |
} | |
public interface IExecuterFactory | |
{ | |
IExecuter Create(Data data); | |
} | |
public class FormularWindow | |
{ | |
private readonly IExecuterFactory _executerFactory; | |
// Mixing service dependencies and run time values in ctor | |
public FormularWindow(IExecuterFactory executerFactory) | |
{ | |
_executerFactory = executerFactory; | |
} | |
public void InvokeExecuter() | |
{ | |
var selectedData = GetSelectedData(); | |
var executer = _executerFactory.Create(selectedData); | |
executer.Execute(); | |
} | |
private static Data GetSelectedData() | |
{ | |
return new Data { Id = 4, Description = "Test" }; | |
} | |
} |
I added the "list resolving" feature for AutoFactory with unit tests.
[Test]
public void Can_resolve_components()
{
container.Configure(cfg =>
{
cfg.For<IDummyService>().Use<Dummy1>();
cfg.For<IDummyService>().Use<Dummy2>();
cfg.For<IDummyFactory>().CreateFactory();
});
var factory = container.GetInstance<IDummyFactory>();
var components = factory.CreateDummyServices().ToList();
components.ShouldNotBeNull();
components.Contains(new Dummy1()).ShouldBeTrue();
components.Contains(new Dummy2()).ShouldBeTrue();
components.Count().ShouldEqual(2);
}
[Test]
public void Can_resolve_components_with_type()
{
container.Configure(cfg =>
{
cfg.Scan(s =>
{
s.AssemblyContainingType<MessageHandler2>();
s.ConnectImplementationsToTypesClosing(typeof (IHandler<>));
});
cfg.For<IDummyFactory>().CreateFactory();
});
var factory = container.GetInstance<IDummyFactory>();
var commandHandlerType = typeof (IHandler<Message>);
var components = factory.CreateHandlers(commandHandlerType).ToList();
components.ShouldNotBeNull();
components.Contains(new MessageHandler()).ShouldBeTrue();
components.Contains(new MessageHandler2()).ShouldBeTrue();
components.Count().ShouldEqual(2);
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
My problem is that if you pass the container into other classes you do not see the real dependency. You only see that you depend on IContainer instead of IExecutor. Furthermore unit tests are coupled to StructureMap. Thats just my opinion.
I tried the CreateFactory method, but it seems not fully implemented. For now it is not possible to get a list of dependencies.
Are some of you guys will continue to develope this feature for StructureMap?