// ----------------------------------------------------------------------- // // // 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; } } } }