castle windsor学习----- Lifestyles
1.Singleton 单例
2.Transient 瞬态
3.PerWebRequest 每一次web请求
当请求开始时组件会被创建,请求结束时释放
1)PerWebRequestLifestyleModule
<httpModules> <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor"/> </httpModules>
IIS7配置
<configuration> <system.webServer> <modules> <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor" /> </modules> </system.webServer> </configuration>
4.Scoped 作用域
Container.Register(Component.For<MyScopedComponent>().LifestyleScoped());
using Castle.MicroKernel.Lifestyle; using (Container.BeginScope()) //extension method { var one = Container.Resolve<MyScopedComponent>(); var two = Container.Resolve<MyScopedComponent>(); Assert.AreSame(one, two); } // releases the instance
用户自定义作用域
Container.Register(Component.For<MyScopedComponent>().LifestyleScoped<MyCustomScopeAccessor>());
需要实现如下接口
public interface IScopeAccessor : IDisposable { ILifetimeScope GetScope(CreationContext context); }
例子:
如果你建立一个B2B应用程序,每个客户公司有自己的一个生命周期,你可以定义如下
public class PerClientCompanyScopeAccessor : IScopeAccessor { private static readonly ConcurrentDictionary<Guid, ILifetimeScope> collection = new ConcurrentDictionary<Guid, ILifetimeScope>(); public ILifetimeScope GetScope(Castle.MicroKernel.Context.CreationContext context) { var companyID = ClientHelper.GetCurrentClientCompanyId(); return collection.GetOrAdd(companyID, id => new ThreadSafeDefaultLifetimeScope()); } public void Dispose() { foreach (var scope in collection) { scope.Value.Dispose(); } collection.Clear(); } }
public class ThreadSafeDefaultLifetimeScope : ILifetimeScope { private static readonly Action<Burden> emptyOnAfterCreated = delegate { }; private readonly object @lock = new object(); private readonly Action<Burden> onAfterCreated; private IScopeCache scopeCache; public ThreadSafeDefaultLifetimeScope(IScopeCache scopeCache = null, Action<Burden> onAfterCreated = null) { this.scopeCache = scopeCache ?? new ScopeCache(); this.onAfterCreated = onAfterCreated ?? emptyOnAfterCreated; } public void Dispose() { lock (@lock) { if (scopeCache == null) { return; } var disposableCache = scopeCache as IDisposable; if (disposableCache != null) { disposableCache.Dispose(); } scopeCache = null; } } public Burden GetCachedInstance(ComponentModel model, ScopedInstanceActivationCallback createInstance) { lock (@lock) { var burden = scopeCache[model]; if (burden == null) { scopeCache[model] = burden = createInstance(onAfterCreated); } return burden; } } }
Bound
Somewhere in the graph we have two view models, one depending on the other, and both of them depend on some other service, say a repository. You might want to bind the repository to the subgraph. In other words you might want the entire subgraph of the outermost view model (WelcomeScreenViewModel
) to share the same instance of the repository, and to have the repository released when the view model itself is released.
This is what bound lifestyle is for.
Container.Register(Component.For<Repository>().LifestyleBoundTo<ViewModelBase>());