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);
}
}