tags:

views:

49

answers:

2

This is the equivalent of what I'm trying to create with StructureMap:

new ChangePasswordWithNotificationAndLoggingService(
new ChangePasswordService(
      new ActiveDirectoryRepository(new ActiveDirectoryCredentials()),
      new TokenRepository("")),
new EmailNotificationService(new PasswordChangedNotification(new UserAccount())),
new LoggingService());

This is what I have right now:

ForRequestedType<IChangePasswordService>()
  .TheDefault.Is.ConstructedBy(() => 
     new ChangePasswordService(DependencyRegistrar.Resolve<IActiveDirectoryRepository>(),
                               DependencyRegistrar.Resolve<ITokenRepository>()))
  .EnrichWith<IChangePasswordService>(x => 
     new ChangePasswordWithNotificationAndLoggingService(x,
                   DependencyRegistrar.Resolve<INotificationService>(),
                   DependencyRegistrar.Resolve<ILoggingService>()));

I need to pass the UserAccount to the INotificationService...can't figure it out.

I've tried this: DependencyRegistrar.With(new UserAccount { Username = "test" });

No luck...UserAccount always turns out null. I don't have to do it all with StructureMap, I'm open to any suggestions.

This is what I currently have working:

public static IChangePasswordService ChangePasswordService(UserAccount userAccount)
{
    return new ChangePasswordWithNotificationService(
        new ChangePasswordService(ActiveDirectoryRepository(), TokenRepository()),
        new EmailNotificationService(new PasswordChangedNotification(userAccount)));
}
A: 

Have you tried just using AutoWiring? These are all concrete classes with simple construction so StructureMap can figure out what you need.

For<IChangePasswordService>().Use<ChangePasswordService>();

Looking at your construction I think that this simple configuration might just work.

Edit Regarding the comments.

You should use the With(T instance) method to have the container construct your IChangePasswordService using the given userAccount.

var userAccount = new UserAccount("derans"); 
var changePasswordService = container.With(userAccount).GetInstance<IChangePasswordService>();
KevM
I don't think it'll work because I need to be able to pass in the UserAccount object to the PasswordChangedNotification. It's not clear the way I showed the end-result at the top, but the new UserAccount() needs to be passed in to create the IChangePasswordService.Right now I have it working, but not using StructureMap for everything...I'll edit the top to reflect what I actually am using currently to get the job done.
derans
At retrieval time (not registration time), you can do:Container.With(new UserAccount{Username = "test"}).GetInstance<IChangePasswordService>();
Joshua Flanagan
I've tried that one too, but with the current configuration of the IChangePasswordService in the registry, it doesn't work. UserAccount is always the default instance of UserAccount.
derans
A: 

Why not encapsulate the creation of the change password service into a factory - the factory is then an implemented as StructureMap factory that use a UserAccount passed in and the 'ObjectFactory' to create instances of the IIChangePasswordService as required?

I have demo'ed it below:

namespace SMTest
{
class Program
{
    static void Main(string[] args)
    {
        // bootstrapper...
        ObjectFactory.Configure(x => x.AddRegistry(new TestRegistry()));

        // create factory for use later (IoC manages this)...
        var changePasswordServiceFactory = ObjectFactory.GetInstance<IChangePasswordServiceFactory>();

        var daveAccount = new UserAccount("Dave Cox");
        var steveAccount = new UserAccount("Steve Jones");

        var passwordService1 = changePasswordServiceFactory.CreateForUserAccount(daveAccount);
        var passwordService2 = changePasswordServiceFactory.CreateForUserAccount(steveAccount);


    }
}

public class TestRegistry : Registry
{
    public TestRegistry()
    {
        Scan(x =>
                 {
                     x.TheCallingAssembly();
                     x.AssemblyContainingType(typeof(IChangePasswordService));
                     x.AssemblyContainingType(typeof(IActiveDirectoryRepository));
                     x.AssemblyContainingType(typeof(IActiveDirectoryCredentials));
                     x.AssemblyContainingType(typeof(ITokenRepository));
                     x.AssemblyContainingType(typeof(INotification));
                     x.AssemblyContainingType(typeof(INotificationService));
                     x.AssemblyContainingType(typeof(ILoggingService));

                     ForRequestedType<ILoggingService>().TheDefault.Is.OfConcreteType<MyLogger>();

                     ForRequestedType<IActiveDirectoryRepository>().TheDefault.Is.OfConcreteType<MyAdRepository>();
                     ForRequestedType<IActiveDirectoryCredentials>().TheDefault.Is.OfConcreteType<MyAdCredentials>();

                     ForRequestedType<ITokenRepository>().TheDefault.Is.OfConcreteType<MyTokenRepository>();

                     ForRequestedType<IChangePasswordService>().TheDefault.Is.OfConcreteType<ChangePasswordService>();
                     ForRequestedType<IChangePasswordServiceFactory>().CacheBy(InstanceScope.Singleton).TheDefault.Is.OfConcreteType<StructureMapChangePasswordServiceFactory>();

                     ForRequestedType<INotification>().TheDefault.Is.OfConcreteType<MyPasswordChangedNotification>();
                     ForRequestedType<INotificationService>().TheDefault.Is.OfConcreteType<MyEmailNotificationService>();
                 });
    }
}

public interface ILoggingService
{
}

public class MyLogger : ILoggingService
{
}

public class UserAccount
{
    public string Name { get; private set; }

    public UserAccount(string name)
    {
        Name = name;
    }
}

public interface INotification
{
}

public class MyPasswordChangedNotification : INotification
{
    private readonly UserAccount _account;
    private readonly ILoggingService _logger;

    public MyPasswordChangedNotification(UserAccount account, ILoggingService logger)
    {
        _account = account;
        _logger = logger;
    }
}

public interface INotificationService
{
}

public class MyEmailNotificationService : INotificationService
{
    private readonly INotification _notification;
    private readonly ILoggingService _logger;

    public MyEmailNotificationService(INotification notification, ILoggingService logger)
    {
        _notification = notification;
        _logger = logger;
    }
}

public interface ITokenRepository
{
}

public class MyTokenRepository : ITokenRepository
{
}

public interface IActiveDirectoryRepository
{
}

public interface IActiveDirectoryCredentials
{
}

public class MyAdCredentials : IActiveDirectoryCredentials
{
}

public class MyAdRepository : IActiveDirectoryRepository
{
    private readonly IActiveDirectoryCredentials _credentials;

    public MyAdRepository(IActiveDirectoryCredentials credentials)
    {
        _credentials = credentials;
    }
}

public interface IChangePasswordService
{
}

public class ChangePasswordService : IChangePasswordService
{
    private readonly IActiveDirectoryRepository _adRepository;
    private readonly ITokenRepository _tokenRepository;
    private readonly INotificationService _notificationService;

    public ChangePasswordService(IActiveDirectoryRepository adRepository, ITokenRepository tokenRepository, INotificationService notificationService)
    {
        _adRepository = adRepository;
        _tokenRepository = tokenRepository;
        _notificationService = notificationService;
    }
}

public interface IChangePasswordServiceFactory
{
    IChangePasswordService CreateForUserAccount(UserAccount account);
}

public class StructureMapChangePasswordServiceFactory : IChangePasswordServiceFactory
{
    public IChangePasswordService CreateForUserAccount(UserAccount account)
    {
        return ObjectFactory.With(account).GetInstance < IChangePasswordService>();
    }
}
}
AWC
I feel like this is definitely on the right track, but it is missing the decorated ChangePasswordService. I think I might be able to figure it out from this code though. I'll give it a whirl. Thanks!
derans