Dependency injection 如何注册为singleton或transient所有类型使用StructureMap实现一个接口

Dependency injection 如何注册为singleton或transient所有类型使用StructureMap实现一个接口,dependency-injection,inversion-of-control,ioc-container,structuremap,structuremap3,Dependency Injection,Inversion Of Control,Ioc Container,Structuremap,Structuremap3,我有两个接口,说明服务必须是单例的还是瞬态的: public interface ITransient {} public interface ISingleton {} 我在其他接口和类中实现此接口: public interface ISession : ISingleton { int? UserId {get;set;} } public class Session : ISession { public int? UserId {get;set;} } 然后,我将

我有两个接口,说明服务必须是单例的还是瞬态的:

public interface ITransient {}
public interface ISingleton {}
我在其他接口和类中实现此接口:

public interface ISession : ISingleton
{
    int? UserId {get;set;}
}

public class Session : ISession
{
    public int? UserId {get;set;}
}
然后,我将会话注入到其他服务中:

public interface IBookService : ITransient
{
    ...
}

public class BookService : IBookService
{
    public BookService(ISession session) { ... }
    ...
}
如何配置StructureMap,使实现ISingleton的所有类型的实例请求都必须使用Singleton lifecycle创建

我试过:

Container.Configure(conf => {
    conf.For<ITransient>().Transient();
    conf.For<ISingleton>().Singleton();
}
有人能帮我吗

更新

我建立了一个惯例:

public class BasicConvention : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (!type.IsAbstract && typeof(ISingleton).IsAssignableFrom(type))
        {
            registry.For(type, new SingletonLifecycle());
        }
        if (!type.IsAbstract && typeof(ITransient).IsAssignableFrom(type))
        {
            registry.For(type, new TransientLifecycle());
        }
    }
}
public class BasicConvention : ConfigurableRegistrationConvention
{
    public override void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete()) return;

        var pluginType = FindPluginType(type);
        if (pluginType != null && type.HasConstructors())
        {
            var ci = registry.For(pluginType).Use(type);
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is TransientLifecycleAttribute) != null)
                ci.Transient();
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is SingletonLifecycleAttribute) != null)
                ci.Singleton();             
            ConfigureFamily(registry.For(pluginType));
        }
    }

    public virtual Type FindPluginType(Type concreteType)
    {
        var interfaceName = "I" + concreteType.Name;
        return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
    }
}
这似乎是可行的,但它将每个类注册为插件类型,在本例中:

Session=>Session[Singleton] BookService=>BookService[Transient]

但是如果我将会话作为ISession注入。。。找不到实例,因为ISession未注册。。。但我可以使用默认对流。。。然后工作,但检索实例作为瞬态

呼叫我所拥有的,我可以看到:

===============================================================================================================================================================================================================================================================================
PluginType                  Namespace                          Lifecycle     Description                                                                                                                                               Name                                    
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
....
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession                     Paf.Application.Session            Transient     Paf.Application.Session ('Paf.Application.Session, Paf.Modules.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')                        Paf.Application.Session,... (Default)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.....
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Session                     Paf.Application                    Singleton     Paf.Application.Session                                                                                                                                (Default)                               
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
...
===============================================================================================================================================================================================================================================================================

我可以解决这个问题吗?

好的,我已经转到StructureMap源代码,了解如何处理默认争用

我发现DefaultConventionScanner类:

public class DefaultConventionScanner : ConfigurableRegistrationConvention
{
    public override void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete()) return;

        var pluginType = FindPluginType(type);
        if (pluginType != null && type.HasConstructors())
        {
            registry.AddType(pluginType, type);
            ConfigureFamily(registry.For(pluginType));
        }
    }

    public virtual Type FindPluginType(Type concreteType)
    {
        var interfaceName = "I" + concreteType.Name;
        return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
    }
}
我可以推断我可以更改插件类型registry.AddTypepluginType,键入代码行并编写它:

            if(typeof(ISingleton).IsAssignableFrom(type))
                registry.For(pluginType).Use(type).Singleton();
            else if (typeof(ITransient).IsAssignableFrom(type))
                registry.For(pluginType).Use(type).Transient();
            else
            {
                registry.AddType(pluginType, type);
            }
            ConfigureFamily(registry.For(pluginType));
因此,如果插件类型接口类型为ISingleton或ITransient I registry,则将新插件类型注册为Singleton或Transient,否则将插件类型注册为allwais

我试着了解工作!!是啊

只有一个考虑因素,我不知道这两者之间是否存在差异:

            registry.AddType(pluginType, type);
以及: registry.ForpluginType.Usetype

我比较了之前和之后的结果,我只能看到一个不同

旧结果:

===============================================================================================================================================================================================================================================================================
PluginType                  Namespace                          Lifecycle     Description                                                                                                                                               Name                                    
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession                    Paf.Application.Session            Transient     Paf.Application.Session ('Paf.Application.Session, Paf.Modules.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')                              Paf.Application.Session,... (Default)
===============================================================================================================================================================================================================================================================================
新结果:

===============================================================================================================================================================================================================================================================================
PluginType                  Namespace                          Lifecycle     Description                                                                                                                                               Name                                    
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession                    Paf.Application.Session            Singleton     Paf.Application.Session                                                                                                                                (Default)                               
===============================================================================================================================================================================================================================================================================
新的结果是可以的,是单态的,区别只是在描述上,我认为没有什么重要的想法

使现代化 根据我问题的评论,我决定不使用ITransient和ISingleton接口。我决定在实现类中使用属性

我创建了两个属性:

[AttributeUsage(AttributeTargets.Class)]
public class SingletonLifecycleAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class TransientLifecycleAttribute : Attribute
{
}
我把它分配到我的课堂上:

public interface ISession   {       int? UserId {get;set;}  }

[SingletonLifecycle]
public class Session : ISession {       public int? UserId {get;set;}   }   

public interface IBookService { ... }

[TransientLifecycle]
public class BookService : IBookService { public BookService(ISession session) { ... }  }
然后我修改了我的惯例:

public class BasicConvention : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (!type.IsAbstract && typeof(ISingleton).IsAssignableFrom(type))
        {
            registry.For(type, new SingletonLifecycle());
        }
        if (!type.IsAbstract && typeof(ITransient).IsAssignableFrom(type))
        {
            registry.For(type, new TransientLifecycle());
        }
    }
}
public class BasicConvention : ConfigurableRegistrationConvention
{
    public override void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete()) return;

        var pluginType = FindPluginType(type);
        if (pluginType != null && type.HasConstructors())
        {
            var ci = registry.For(pluginType).Use(type);
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is TransientLifecycleAttribute) != null)
                ci.Transient();
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is SingletonLifecycleAttribute) != null)
                ci.Singleton();             
            ConfigureFamily(registry.For(pluginType));
        }
    }

    public virtual Type FindPluginType(Type concreteType)
    {
        var interfaceName = "I" + concreteType.Name;
        return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
    }
}
我认为现在一切都很好,更好了;
谢谢史蒂夫

你现在是一个生活方式的抽象,但我认为这是错误的方法,因为是实现决定了它的生活方式,而不是抽象。换句话说:你的行为违反了。真的,真的。。。那么Session是应该实现ISingleton而不是ISession的实现吗?是的,或者你用一个属性来标记它,在这种情况下,我觉得这个属性更自然。顺便问一下,为什么BookService依赖于会话而不是ISession。这是一个错误吗?我认为这是一个意外。好的,我认为使用属性是一个好方法。谢谢是的,应该是会话,我要编辑我的问题。
public class BasicConvention : ConfigurableRegistrationConvention
{
    public override void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete()) return;

        var pluginType = FindPluginType(type);
        if (pluginType != null && type.HasConstructors())
        {
            var ci = registry.For(pluginType).Use(type);
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is TransientLifecycleAttribute) != null)
                ci.Transient();
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is SingletonLifecycleAttribute) != null)
                ci.Singleton();             
            ConfigureFamily(registry.For(pluginType));
        }
    }

    public virtual Type FindPluginType(Type concreteType)
    {
        var interfaceName = "I" + concreteType.Name;
        return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
    }
}