#region Apache Notice
/*****************************************************************************
* $Revision: 374175 $
* $LastChangedDate: 2006-02-19 12:37:22 +0100 (Sun, 19 Feb 2006) $
* $LastChangedBy: gbayon $
*
* iBATIS.NET Data Mapper
* Copyright (C) 2006/2005 - The Apache Software Foundation
*
*
* 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.
*
********************************************************************************/
#endregion
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using IBatisNet.Common.Logging;
namespace IBatisNet.Common.Utilities.Objects{
/// <summary>
/// A <see cref="IObjectFactory"/> implementation that can create objects via DynamicMethod.
/// </summary>
public sealed class DelegateObjectFactory : IObjectFactory
{
private IDictionary _cachedfactories = new HybridDictionary();
private object _padlock = new object();
private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
#region IObjectFactory members
/// <summary>
/// Create a new <see cref="IFactory"/> instance for a given type
/// </summary>
/// <param name="typeToCreate">The type instance to build</param>
/// <param name="types">The types of the constructor arguments</param>
/// <returns>Returns a new see <see cref="IFactory"/> instance.</returns>
[MethodImpl(MethodImplOptions.Synchronized)]
public IFactory CreateFactory(Type typeToCreate, Type[] types)
{
string key = GenerateKey(typeToCreate, types);
IFactory factory = _cachedfactories[key] as IFactory;
if (factory == null)
{
lock (_padlock)
{
factory = _cachedfactories[key] as IFactory;
if (factory == null) // double-check
{
if (typeToCreate.IsAbstract)
{
if (_logger.IsInfoEnabled)
{
_logger.Info("Create a stub IFactory for abstract type " + typeToCreate.Name);
}
factory = new AbstractFactory(typeToCreate);
}
else
{
factory = new DelegateFactory(typeToCreate, types);
}
_cachedfactories[key] = factory;
}
}
}
return factory;
}
/// <summary>
/// Generates the key for a cache entry.
/// </summary>
/// <param name="typeToCreate">The type instance to build.</param>
/// <param name="arguments">The types of the constructor arguments</param>
/// <returns>The key for a cache entry.</returns>
private string GenerateKey(Type typeToCreate, object[] arguments)
{
StringBuilder cacheKey = new StringBuilder();
cacheKey.Append(typeToCreate.ToString());
cacheKey.Append(".");
if ((arguments != null) && (arguments.Length != 0))
{
for (int i=0; i<arguments.Length; i++)
{
cacheKey.Append(".").Append(arguments[i]);
}
}
return cacheKey.ToString();
}
#endregion
}
}
|