我正在使用带有StructureMap的mvc.net来扫描和注册所有存储库和服务。现在我想通过Singleton注册和缓存。我该怎么办?
IContainer container = new Container(x => {
// Register Repositories and Services
x.Scan(y => {
y.AssemblyContainingType<SomeRepository>();
y.AssemblyContainingType<SomeService>();
y.IncludeNamespaceContainingType<SomeRepository>();
y.IncludeNamespaceContainingType<SomeService>();
});
// Register Controllers
x.Scan(y => {
y.TheCallingAssembly();
y.AddAllTypesOf<IController>().NameBy(type => type.Name.Replace("Controller", ""));
});
});
答案 0 :(得分:19)
使用2.6中的新API,不推荐使用ITypeScanner。这应该作为惯例来实现。一个简单的例子是你想要注册一个约定,所有类型的特定接口都是单例:
Scan(a =>
{
a.AssemblyContainingType<IMyPluginType>();
a.With(new SingletonConvention<IMyPluginType>());
a.AddAllTypesOf<IMyPluginType>();
});
然后:
internal class SingletonConvention<TPluginFamily> : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (!type.IsConcrete() || !type.CanBeCreated() || !type.AllInterfaces().Contains(typeof(TPluginFamily))) return;
registry.For(typeof(TPluginFamily)).Singleton().Use(type);
}
}
答案 1 :(得分:2)
您需要实施类似于Jeremy Miller在http://codebetter.com/blogs/jeremy.miller/archive/2009/01/20/create-your-own-auto-registration-convention-with-structuremap.aspx概述的ITypeScanner
因此,对于您的控制器,我会将Scan调用更改为:
x.Scan(y => {
y.TheCallingAssembly();
y.With<MyNewTypeScanner>();
});
然后我会在其他地方定义一个看起来像这样的类:
public class MyNewTypeScanner: ITypeScanner
{
//This method is responsible for determining if a type should be registered
// and then passing it to RegisterType() if so
public void Process(Type type, PluginGraph graph)
{
//At this point you would probably just test to see if type is IController
//but you can get more sophisticated without too much headache.
this.RegisterType(graph, type);
}
private void RegisterType(PluginGraph graph, Type implementingType)
{
//The argument passed to FindFamily must be the type/class that will be requested out of SM
var family = graph.FindFamily(implementingType);
family.AddType(implementingType);
family.SetScopeTo(InstanceScope.Singleton);
}
}
这应该适合你。
答案 2 :(得分:0)
扩展@Eric Hauser的答案,创建一个更容易使用的解决方案
public abstract class TypedRegistrationConvention<TPluginFamily>
: IRegistrationConvention
{
public virtual void Process(Type type, Registry registry)
{
if (!type.IsConcrete()
|| !type.CanBeCreated()
|| !type.AllInterfaces().Contains(typeof (TPluginFamily)))
return;
ApplyConvention(type, registry);
}
public abstract void ApplyConvention(Type type, Registry registry);
}
使用这个已建立的基类,您可以实现约定,而不必使用类型检查代码。
public class SingletonConvention<TPluginFamily>
: TypedRegistrationConvention<TPluginFamily>
{
public override void ApplyConvention(Type type, Registry registry)
{
registry.For(typeof (TPluginFamily)).Singleton().Use(type);
}
}
最后更简单的课程。