Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Rookian/2601765 to your computer and use it in GitHub Desktop.
Save Rookian/2601765 to your computer and use it in GitHub Desktop.
Ctor With Runtime Values And Service Dependencies
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" };
}
}
@Rookian
Copy link
Author

Rookian commented May 6, 2012

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.

    [Test]
    public void Can_resolve_components()
    {
        container.Configure(cfg =>
        {
            cfg.For<IDummyService>().Use<Dummy1>();
            cfg.For<IDummyService>().Use<Dummy2>();
            cfg.For<IEnumerable<IDummyService>>().Use(container.GetAllInstances<IDummyService>());
            cfg.For<IDummyFactory>().CreateFactory();
        });

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

        var components = factory.CreateDummyServices().ToList();

        components.ShouldNotBeNull();
        components.Count().ShouldBeTheSameAs(2);
    }

Are some of you guys will continue to develope this feature for StructureMap?

@Rookian
Copy link
Author

Rookian commented May 7, 2012

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