Added the ability to change the invocation target in the DefaultProxyFactory.
[castle.git] / Facilities / Wcf / Castle.Facilities.WcfIntegration / Client / WcfClientResolver.cs
blobf469741050098c70f2e642207f1fd07e72db692c
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Facilities.WcfIntegration
17 using System;
18 using System.Collections.Generic;
19 using System.Threading;
20 using Castle.Core;
21 using Castle.MicroKernel;
22 using Castle.Facilities.WcfIntegration.Internal;
24 public class WcfClientResolver : ISubDependencyResolver
26 private readonly ICollection<WcfClientModel> clientModels;
27 private readonly Dictionary<Type, CreateChannel> channelCreators;
28 private readonly ReaderWriterLock locker;
30 public WcfClientResolver(WcfClientModel[] clientModels)
32 this.clientModels = clientModels;
33 channelCreators = new Dictionary<Type, CreateChannel>();
34 locker = new ReaderWriterLock();
37 public bool CanResolve(CreationContext context, ISubDependencyResolver parentResolver,
38 ComponentModel model, DependencyModel dependency)
40 return ResolveClientModel(dependency.TargetType, model, context) != null;
43 public object Resolve(CreationContext context, ISubDependencyResolver parentResolver,
44 ComponentModel model, DependencyModel dependency)
46 WcfClientModel clientModel =
47 ResolveClientModel(dependency.TargetType, model, context);
49 if (clientModel != null)
51 return GetChannelBuilder(clientModel)();
54 throw new InvalidOperationException(string.Format(
55 "Could not find a client supporting contract {0}", dependency.TargetType));
58 private WcfClientModel ResolveClientModel(Type contract, ComponentModel model, CreationContext context)
60 WcfClientModel clientModel;
61 Predicate<WcfClientModel> contractMatch = delegate(WcfClientModel candidate)
63 return contract == candidate.Contract;
66 // First, try the contexrt overrides.
67 if (context != null && context.HasAdditionalParameters)
69 if (WcfUtils.FindDependency<WcfClientModel>(
70 context.AdditionalParameters, contractMatch,
71 out clientModel))
73 return clientModel;
77 // Then try the component overrides.
78 if (model != null)
80 if (WcfUtils.FindDependency<WcfClientModel>(
81 model.CustomDependencies, contractMatch,
82 out clientModel))
84 return clientModel;
88 // Finally, try the client models.
89 if (WcfUtils.FindDependency<WcfClientModel>(
90 clientModels, contractMatch, out clientModel))
92 return clientModel;
95 return null;
98 private CreateChannel GetChannelBuilder(WcfClientModel clientModel)
100 CreateChannel channelCreator;
102 locker.AcquireReaderLock(Timeout.Infinite);
106 if (channelCreators.TryGetValue(clientModel.Contract, out channelCreator))
108 return channelCreator;
111 locker.UpgradeToWriterLock(Timeout.Infinite);
113 if (channelCreators.TryGetValue(clientModel.Contract, out channelCreator))
115 return channelCreator;
118 channelCreator = new ChannelBuilder().GetChannelCreator(clientModel.Endpoint);
119 channelCreators[clientModel.Contract] = channelCreator;
120 return channelCreator;
122 finally
124 locker.ReleaseLock();