@@ -22,99 +22,103 @@ namespace ServiceStack.WebHost.Endpoints
2222 /// </summary>
2323 public class EndpointHost
2424 {
25- private static readonly EndpointHostInstance _instance = new EndpointHostInstance ( ) ;
26-
27- internal static EndpointHostInstance Instance { get { return _instance ; } }
28-
29- private static Dictionary < string , EndpointHostInstance > _namedHosts = new Dictionary < string , EndpointHostInstance > ( ) ;
30- private readonly static object _syncRoot = new object ( ) ;
25+ private static readonly EndpointHostInstance _singletonInstance = new EndpointHostInstance ( ) ;
3126
3227 /// <summary>
33- /// Gets a <see cref="EndpointHostInstance"/> by name, and creates a new host if one doesn't exist by that name .
28+ /// Do not expose .
3429 /// </summary>
35- /// <param name="name">The name of the endpoint to create.</param>
36- /// <returns>Returns the instance.</returns>
37- /// <remarks>This method is thread safe.</remarks>
38- internal static EndpointHostInstance GetNamedHost ( string name )
30+ internal static EndpointHostInstance SingletonInstance
3931 {
40- if ( string . IsNullOrEmpty ( name ) ) throw new ArgumentException ( "Agument must not be not or empty" , "name" ) ;
41-
42- EndpointHostInstance host ;
43- if ( _namedHosts . TryGetValue ( name , out host ) )
44- {
45- return host ;
46- }
32+ get { return _singletonInstance ; }
33+ }
4734
48- lock ( _syncRoot )
35+ /// <summary>
36+ /// Use this instance for all access to this class.
37+ /// </summary>
38+ internal static EndpointHostInstance Instance
39+ {
40+ get
4941 {
50- if ( _namedHosts . TryGetValue ( name , out host ) ) //double checked locking works fine in .Net
51- {
52- return host ;
53- }
54- var namedHosts = new Dictionary < string , EndpointHostInstance > ( _namedHosts ) ;
55- namedHosts . Add ( name , host = new EndpointHostInstance ( true ) ) ;
56- //publish last
57- _namedHosts = namedHosts ;
58- return host ;
59- }
42+ var ts = _threadSpecificInstance ;
43+ if ( ts != null ) return ts ;
44+ else return _singletonInstance ;
45+ }
6046 }
6147
62- internal static void RemoveNamedHost ( string name )
48+ [ ThreadStatic ]
49+ private static EndpointHostInstance _threadSpecificInstance ;
50+
51+ internal static IDisposable SetThreadSpecificHost ( EndpointHostInstance useInstance )
6352 {
64- if ( string . IsNullOrEmpty ( name ) ) return ;
53+ _threadSpecificInstance = useInstance ;
54+ return new ThreadCleanup ( ) ;
55+ }
6556
66- lock ( _syncRoot )
57+ private class ThreadCleanup : IDisposable
58+ {
59+ public void Dispose ( )
6760 {
68- var namedHosts = new Dictionary < string , EndpointHostInstance > ( _namedHosts ) ;
69- namedHosts . Remove ( name ) ;
70- _namedHosts = namedHosts ;
61+ EndpointHost . _threadSpecificInstance = null ;
7162 }
7263 }
7364
74- public static ServiceOperations ServiceOperations { get { return _instance . ServiceOperations ; } }
75- public static ServiceOperations AllServiceOperations { get { return _instance . AllServiceOperations ; } }
65+ private readonly static object _syncRoot = new object ( ) ;
66+
67+ /// <summary>
68+ /// Creates a new <see cref="EndpointHostInstance"/> to run as a seperate instance.
69+ /// </summary>
70+ /// <param name="name">The name of the endpoint to create.</param>
71+ /// <returns>Returns the instance.</returns>
72+ /// <remarks>This method is thread safe.</remarks>
73+ internal static EndpointHostInstance Create ( IAppHost appHost )
74+ {
75+ return EndpointHostInstance . CreateInstance ( appHost ) ;
76+ }
77+
78+ public static ServiceOperations ServiceOperations { get { return Instance . ServiceOperations ; } }
79+ public static ServiceOperations AllServiceOperations { get { return Instance . AllServiceOperations ; } }
7680
77- public static IAppHost AppHost { get { return _instance . AppHost ; } internal set { _instance . AppHost = value ; } }
81+ public static IAppHost AppHost { get { return Instance != null ? Instance . AppHost : null ; } internal set { Instance . AppHost = value ; } }
7882
79- public static IContentTypeFilter ContentTypeFilter { get { return _instance . ContentTypeFilter ; } set { _instance . ContentTypeFilter = value ; } }
83+ public static IContentTypeFilter ContentTypeFilter { get { return Instance . ContentTypeFilter ; } set { Instance . ContentTypeFilter = value ; } }
8084
81- public static List < Action < IHttpRequest , IHttpResponse > > RawRequestFilters { get { return _instance . RawRequestFilters ; } }
85+ public static List < Action < IHttpRequest , IHttpResponse > > RawRequestFilters { get { return Instance . RawRequestFilters ; } }
8286
83- public static List < Action < IHttpRequest , IHttpResponse , object > > RequestFilters { get { return _instance . RequestFilters ; } }
87+ public static List < Action < IHttpRequest , IHttpResponse , object > > RequestFilters { get { return Instance . RequestFilters ; } }
8488
85- public static List < Action < IHttpRequest , IHttpResponse , object > > ResponseFilters { get { return _instance . ResponseFilters ; } }
89+ public static List < Action < IHttpRequest , IHttpResponse , object > > ResponseFilters { get { return Instance . ResponseFilters ; } }
8690
87- public static List < IViewEngine > ViewEngines { get { return _instance . ViewEngines ; } set { _instance . ViewEngines = value ; } }
91+ public static List < IViewEngine > ViewEngines { get { return Instance . ViewEngines ; } set { Instance . ViewEngines = value ; } }
8892
89- public static HandleUncaughtExceptionDelegate ExceptionHandler { get { return _instance . ExceptionHandler ; } set { _instance . ExceptionHandler = value ; } }
93+ public static HandleUncaughtExceptionDelegate ExceptionHandler { get { return Instance . ExceptionHandler ; } set { Instance . ExceptionHandler = value ; } }
9094
91- public static HandleServiceExceptionDelegate ServiceExceptionHandler { get { return _instance . ServiceExceptionHandler ; } set { _instance . ServiceExceptionHandler = value ; } }
95+ public static HandleServiceExceptionDelegate ServiceExceptionHandler { get { return Instance . ServiceExceptionHandler ; } set { Instance . ServiceExceptionHandler = value ; } }
9296
93- public static List < HttpHandlerResolverDelegate > CatchAllHandlers { get { return _instance . CatchAllHandlers ; } set { _instance . CatchAllHandlers = value ; } }
97+ public static List < HttpHandlerResolverDelegate > CatchAllHandlers { get { return Instance . CatchAllHandlers ; } set { Instance . CatchAllHandlers = value ; } }
9498
95- public static List < IPlugin > Plugins { get { return _instance . Plugins ; } set { _instance . Plugins = value ; } }
99+ public static List < IPlugin > Plugins { get { return Instance . Plugins ; } set { Instance . Plugins = value ; } }
96100
97- public static IVirtualPathProvider VirtualPathProvider { get { return _instance . VirtualPathProvider ; } set { _instance . VirtualPathProvider = value ; } }
101+ public static IVirtualPathProvider VirtualPathProvider { get { return Instance . VirtualPathProvider ; } set { Instance . VirtualPathProvider = value ; } }
98102
99- public static DateTime StartedAt { get { return _instance . StartedAt ; } set { _instance . StartedAt = value ; } }
103+ public static DateTime StartedAt { get { return Instance . StartedAt ; } set { Instance . StartedAt = value ; } }
100104
101- public static DateTime ReadyAt { get { return _instance . ReadyAt ; } set { _instance . ReadyAt = value ; } }
105+ public static DateTime ReadyAt { get { return Instance . ReadyAt ; } set { Instance . ReadyAt = value ; } }
102106
103107 // Pre user config
104108 public static void ConfigureHost ( IAppHost appHost , string serviceName , ServiceManager serviceManager )
105109 {
106- _instance . ConfigureHost ( appHost , serviceName , serviceManager ) ;
110+ Instance . ConfigureHost ( appHost , serviceName , serviceManager ) ;
107111 }
108112
109113 //After configure called
110114 public static void AfterInit ( )
111115 {
112- _instance . AfterInit ( ) ;
116+ Instance . AfterInit ( ) ;
113117 }
114118
115119 public static T TryResolve < T > ( )
116120 {
117- return _instance . TryResolve < T > ( ) ;
121+ return Instance . TryResolve < T > ( ) ;
118122 }
119123
120124 /// <summary>
@@ -123,21 +127,21 @@ public static T TryResolve<T>()
123127 public static Container Container
124128 {
125129 get {
126- return _instance . Container ;
130+ return Instance . Container ;
127131 }
128132 }
129133
130134 public static void AddPlugin ( params IPlugin [ ] plugins )
131135 {
132- _instance . AddPlugin ( plugins ) ;
136+ Instance . AddPlugin ( plugins ) ;
133137 }
134138
135139 public static ServiceManager ServiceManager
136140 {
137- get { return _instance . ServiceManager ; }
141+ get { return Instance . ServiceManager ; }
138142 set
139143 {
140- _instance . ServiceManager = value ;
144+ Instance . ServiceManager = value ;
141145 }
142146 }
143147
@@ -155,11 +159,11 @@ public static EndpointHostConfig Config
155159 {
156160 get
157161 {
158- return _instance . Config ;
162+ return Instance . Config ;
159163 }
160164 set
161165 {
162- _instance . Config = value ;
166+ Instance . Config = value ;
163167 }
164168 }
165169
@@ -170,7 +174,7 @@ public static EndpointHostConfig Config
170174 /// <returns></returns>
171175 public static bool ApplyPreRequestFilters ( IHttpRequest httpReq , IHttpResponse httpRes )
172176 {
173- return _instance . ApplyPreRequestFilters ( httpReq , httpRes ) ;
177+ return Instance . ApplyPreRequestFilters ( httpReq , httpRes ) ;
174178 }
175179
176180 /// <summary>
@@ -180,7 +184,7 @@ public static bool ApplyPreRequestFilters(IHttpRequest httpReq, IHttpResponse ht
180184 /// <returns></returns>
181185 public static bool ApplyRequestFilters ( IHttpRequest httpReq , IHttpResponse httpRes , object requestDto )
182186 {
183- return _instance . ApplyRequestFilters ( httpReq , httpRes , requestDto ) ;
187+ return Instance . ApplyRequestFilters ( httpReq , httpRes , requestDto ) ;
184188 }
185189
186190 /// <summary>
@@ -190,30 +194,30 @@ public static bool ApplyRequestFilters(IHttpRequest httpReq, IHttpResponse httpR
190194 /// <returns></returns>
191195 public static bool ApplyResponseFilters ( IHttpRequest httpReq , IHttpResponse httpRes , object response )
192196 {
193- return _instance . ApplyResponseFilters ( httpReq , httpRes , response ) ;
197+ return Instance . ApplyResponseFilters ( httpReq , httpRes , response ) ;
194198 }
195199
196200 public static void SetOperationTypes ( ServiceOperations operationTypes , ServiceOperations allOperationTypes )
197201 {
198- _instance . SetOperationTypes ( operationTypes , allOperationTypes ) ;
202+ Instance . SetOperationTypes ( operationTypes , allOperationTypes ) ;
199203 }
200204
201205 internal static object ExecuteService ( object request , EndpointAttributes endpointAttributes , IHttpRequest httpReq , IHttpResponse httpRes )
202206 {
203- return _instance . ExecuteService ( request , endpointAttributes , httpReq , httpRes ) ;
207+ return Instance . ExecuteService ( request , endpointAttributes , httpReq , httpRes ) ;
204208 }
205209
206210 public static IServiceRunner < TRequest > CreateServiceRunner < TRequest > ( ActionContext actionContext )
207211 {
208- return _instance . CreateServiceRunner < TRequest > ( actionContext ) ;
212+ return Instance . CreateServiceRunner < TRequest > ( actionContext ) ;
209213 }
210214
211215 /// <summary>
212216 /// Call to signal the completion of a ServiceStack-handled Request
213217 /// </summary>
214218 internal static void CompleteRequest ( )
215219 {
216- _instance . CompleteRequest ( ) ;
220+ Instance . CompleteRequest ( ) ;
217221 }
218222 }
219223}
0 commit comments