0
votes

I am trying to use StructureMap to register some types that implement a generic interface and are instantiated via a factory.

My code:

    public interface IManagerBase<T, TKey> : IDisposable
    {
        // Get Methods
        T GetById(TKey Id);
    }

    public partial interface IServerHostManager : IManagerBase<ServerHost, int>
    {
        // ServerHost Specific Get Methods
    }    

    partial class ServerHostManager : ManagerBase<ServerHost, int>, IServerHostManager
    {
        // Implementation
    }

    public class ManagerFactory : IManagerFactory
    {
        public IServerHostManager GetServerHostManager()
        {
            return new ServerHostManager();
        }
    }

This works fine:

 For<IServerHostManager>().HybridHttpOrThreadLocalScoped()
.Use(new ManagerFactory().GetServerHostManager());

My factory is called and a new instance of IServerHostManager is returned.

Is there any way I can scan for all generic types and have them instantiated via my factory?

This does not work due to ServerHostManager being an internal class:

        Scan(x =>
        {
            x.AssemblyContainingType(typeof(IManagerBase<,>));
            x.AddAllTypesOf(typeof(IManagerBase<,>));
            x.ConnectImplementationsToTypesClosing(typeof(IManagerBase<,>))
                .OnAddedPluginTypes(t => t.HybridHttpOrThreadLocalScoped());
        });

What scan command can I use to tell SM to call my factory?

Thank you,

Rick

Followup added on 5/4:

Sorry for the delay in following up.

I’ve got a bunch of manager objects (> 75) that CodeSmith’s nHibernate template has created. They are normally accessed via a factory object. Instead, I’d like to scan for them have them all registered automatically.

This is how I register the objects now:

For<IActivityLogManager>().HybridHttpOrThreadLocalScoped() 
.Use(new ManagerFactory().GetActivityLogManager()); 

For<IAspnetUserManager>().HybridHttpOrThreadLocalScoped() 
.Use(new ManagerFactory().GetAspnetUserManager()); 

Here are the objects

public interface IManagerBase<T, TKey> : IDisposable
{
    // Get Methods 
    T GetById(TKey Id);
}

public partial interface IActivityLogManager : IManagerBase<BusinessObjects.ActivityLog, int>
{
    // Get Methods
    IList<ActivityLog> GetByActivityTypeId(System.Int32 activityType);
}

public partial class ActivityLogManager : ManagerBase<BusinessObjects.ActivityLog, int>, IActivityLogManager
{
    public IList<ActivityLog> GetByActivityTypeId(System.Int32 activityType)
    {
        // Code to fetch objects
    }    
}

public partial interface IAspnetUserManager : IManagerBase<BusinessObjects.AspnetUser, System.Guid>
{
    // Get Methods
    IList<ActivityLog> GetByActivityTypeId(System.Int32 activityType);
}

public partial class AspnetUserManager : ManagerBase<BusinessObjects.AspnetUser, System.Guid>, IAspnetUserManager
{
    public IList<AspnetUser> GetAll()
    {
        // Code to fetch objects
    }    
}

My Scan code:

Scan(x => 
    { 
        x.AssemblyContainingType(typeof(IManagerBase<,>)); 
        x.AddAllTypesOf(typeof(IManagerBase<,>)); 
        x.ConnectImplementationsToTypesClosing(typeof(IManagerBase<,>)) 
            .OnAddedPluginTypes(t => t.HybridHttpOrThreadLocalScoped());     
    });

The Scan code above does not find any objects in the assembly.

I hope this clarifies my scenario.

Thank you,

Rick

1
It isn't clear what other types you want instantiated. It appears you only gave one example. Can you include an example of how you would register multiple generics manually, and then maybe we can help you build a convention scanner to do it automatically. - Joshua Flanagan
I added to the above post. Thank you. - rboarman

1 Answers

1
votes

This issue can be solved by making the assembly a friend:

[assembly: InternalsVisibleTo("AssemblyB")]

http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx