// -----------------------------------------------------------------------
//
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 Lucene.Net.Util
{
using System;
using System.Diagnostics.CodeAnalysis;
using Support;
///
/// A contract for factories that create instances of
/// that are map to interfaces that extend
///
///
///
/// The factory is abstract so the behavior of how interfaces that derive from
/// are mapped to concrete types that implement that
/// interface. The factory also can change how the concrete types are created.
///
///
/// You could easily create your own factory that replaces the default
/// behavior with Dependency Injection.
///
///
///
public abstract class AttributeFactory
{
///
/// Returns the default implementation for , an instance of
/// .
///
///
///
/// The default factory uses a name convention to retrieve and create instances
/// of . The convention is based on the name of
/// the interface types that are subclasses of .
///
///
/// The Java version appends "Impl" to each interface name. The .NET version
/// removes the "I" from the interface name by using type.Name.Substring(0).
///
///
[SuppressMessage("Microsoft.Security",
"CA2104:DoNotDeclareReadOnlyMutableReferenceTypes",
Justification = "Outside classes can not affect the DefaultAttributeFactory")]
public static readonly AttributeFactory DefaultFactory = new DefaultAttributeFactory();
///
/// Creates the instance based on the parameter
/// that must derive from both and .
///
/// The type of interface
/// An instance of .
[SuppressMessage("Microsoft.Design",
"CA1004:GenericMethodsShouldProvideTypeParameter",
Justification = "This is similar to Activator.Create.")]
public abstract AttributeBase CreateAttributeInstance() where T : IAttribute;
///
/// Creates the instance based on the interface
/// that derives from .
///
/// The type.
///
/// An instance of .
///
public abstract AttributeBase CreateAttributeInstance(Type type);
///
/// The default attribute factory implementation.
///
private sealed class DefaultAttributeFactory : AttributeFactory
{
private static readonly WeakDictionary map =
new WeakDictionary();
public override AttributeBase CreateAttributeInstance()
{
return CreateAttributeInstance(typeof(T));
}
public override AttributeBase CreateAttributeInstance(Type type)
{
var implementationType = FetchClassForInterface(type);
return (AttributeBase)Activator.CreateInstance(implementationType);
}
private static Type FetchClassForInterface(Type type)
{
Type value;
lock (map)
{
if (!map.TryGetValue(type, out value))
{
var interfaceName = type.Name;
var typeName = interfaceName.Substring(1);
try
{
value = Type.GetType("{0}.{1}".Inject(type.Namespace, typeName));
}
catch (TypeLoadException ex)
{
throw new ArgumentException(
"The implementation type '{0}' could not be found for attribute " +
"interface '{1}'".Inject(typeName, type.FullName),
ex);
}
map.Add(type, value);
}
}
return value;
}
}
}
}