// Copyright 2004-2008 Castle Project - http://www.castleproject.org/
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Castle.MicroKernel.SubSystems.Naming
{
using System;
using System.Collections;
using System.Runtime.CompilerServices;
///
/// When requesting a component by service, KeySearchNamingSubSystem first
/// determines if more than one component has been registered for that service.
/// If not, Default resolution occurs. If so, all of the registered keys for
/// that service are processed through the provided Predicate to determine which
/// key to use for service resolution. If no Predicate matches, the default
/// resolution occurs.
///
[Serializable]
public class KeySearchNamingSubSystem : DefaultNamingSubSystem
{
protected readonly IDictionary service2Keys;
protected readonly Predicate keyPredicate;
///
/// Initializes a new instance of the class.
///
public KeySearchNamingSubSystem() : this(delegate { return true; })
{
}
///
/// Initializes a new instance of the class.
///
/// The key predicate.
public KeySearchNamingSubSystem(Predicate keyPredicate)
{
if (keyPredicate == null) throw new ArgumentNullException("keyPredicate");
service2Keys = Hashtable.Synchronized(new Hashtable());
this.keyPredicate = keyPredicate;
}
///
/// Registers the given handler with the give key.
///
/// The key.
/// The handler.
[MethodImpl(MethodImplOptions.Synchronized)]
public override void Register(string key, IHandler handler)
{
base.Register(key, handler);
Type service = handler.ComponentModel.Service;
IList keys;
if (!service2Keys.Contains(service))
{
if (!service2Keys.Contains(service))
{
keys = ArrayList.Synchronized(new ArrayList());
keys.Add(key);
service2Keys[service] = keys;
}
}
else
{
keys = (IList) service2Keys[service];
if (!keys.Contains(key))
{
if (!keys.Contains(key))
{
keys.Add(key);
}
}
}
}
///
/// Unregisters the handler associated with the given key
///
/// The key.
[MethodImpl(MethodImplOptions.Synchronized)]
public override void UnRegister(string key)
{
IHandler handler = key2Handler[key] as IHandler;
base.UnRegister(key);
if (handler != null)
{
IList keys = service2Keys[handler.ComponentModel.Service] as IList;
if (keys != null)
{
keys.Remove(key);
}
}
}
///
/// Unregisters the handler associated with the given service
///
/// The service.
[MethodImpl(MethodImplOptions.Synchronized)]
public override void UnRegister(Type service)
{
base.UnRegister(service);
service2Keys.Remove(service);
}
///
/// Executes the Predicate against all keys for the registered service to
/// determine which component to return.
///
/// The service.
///
[MethodImpl(MethodImplOptions.Synchronized)]
public override IHandler GetHandler(Type service)
{
IList keys = service2Keys[service] as IList;
if (keys == null) return null;
if (keys.Count == 1) return base.GetHandler(service);
for(int i = 0; i < keys.Count; i++)
{
string key = (string) keys[i];
if (keyPredicate(key))
{
return GetHandler(key);
}
}
return base.GetHandler(service);
}
}
}