#region License
/*
* Copyright 2002-2005 the original author or authors.
*
* 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
#region Imports
using System;
using AopAlliance.Aop;
using Spring.Collections;
#endregion
namespace Spring.Aop.Support{
/// <summary>
/// Simple <seealso cref="Spring.Aop.IIntroductionAdvisor"/> implementation that
/// by default applies to any class.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class DefaultIntroductionAdvisor : IIntroductionAdvisor, ITypeFilter
{
private readonly IAdvice _introduction;
private readonly ISet _interfaces = new HybridSet();
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultIntroductionAdvisor"/> class using
/// the supplied <paramref name="introduction"/>
/// </summary>
/// <remarks>
/// <p>
/// This constructor adds all interfaces implemented by the supplied
/// <paramref name="introduction"/> (except the
/// <see cref="AopAlliance.Aop.IAdvice"/> interface) to the list of
/// interfaces to introduce.
/// </p>
/// </remarks>
/// <param name="introduction">The introduction to use.</param>
public DefaultIntroductionAdvisor(IAdvice introduction)
: this(introduction, introduction.GetType().GetInterfaces())
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultIntroductionAdvisor"/> class using
/// the supplied <paramref name="introduction"/>
/// </summary>
/// <param name="introduction">The introduction to use.</param>
/// <param name="intf">
/// The interface to introduce.
/// </param>
public DefaultIntroductionAdvisor(IAdvice introduction, Type intf)
: this(introduction, new Type[] {intf})
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultIntroductionAdvisor"/> class using
/// the supplied <paramref name="introduction"/>
/// </summary>
/// <param name="introduction">The introduction to use.</param>
/// <param name="interfaces">
/// The interfaces to introduce.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="introduction"/> is <see langword="null"/>.
/// </exception>
public DefaultIntroductionAdvisor(IAdvice introduction, Type[] interfaces)
{
if (introduction == null)
{
throw new ArgumentNullException("introduction", "Introduction cannot be null");
}
_introduction = introduction;
foreach (Type intf in interfaces)
{
if (intf != typeof (IAdvice))
{
AddInterface(intf);
}
}
}
/// <summary>
/// Returns the filter determining which target classes this
/// introduction should apply to.
/// </summary>
/// <value>
/// The filter determining which target classes this introduction
/// should apply to.
/// </value>
public virtual ITypeFilter TypeFilter
{
get { return this; }
}
/// <summary>
/// Gets the interfaces introduced by this
/// <see cref="Spring.Aop.IAdvisor"/>.
/// </summary>
/// <value>
/// The interfaces introduced by this
/// <see cref="Spring.Aop.IAdvisor"/>.
/// </value>
public virtual Type[] Interfaces
{
get
{
Type[] interfaces = new Type[_interfaces.Count];
_interfaces.CopyTo(interfaces, 0);
return interfaces;
}
}
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// Default for an introduction is per-instance interception.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
public virtual bool IsPerInstance
{
get { return true; }
}
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
public virtual IAdvice Advice
{
get { return this._introduction; }
}
/// <summary>
/// Adds the supplied <paramref name="intf"/> to the list of
/// introduced interfaces.
/// </summary>
/// <param name="intf">The interface to add.</param>
/// <exception cref="System.ArgumentException">
/// If any of the <see cref="Interfaces"/> are not interface <see cref="System.Type"/>.
/// </exception>
public virtual void AddInterface(Type intf)
{
if(intf != null)
{
BailIfNotAnInterfaceType(intf);
_interfaces.Add(intf);
}
}
/// <summary>
/// Should the pointcut apply to the supplied
/// <see cref="System.Type"/>?
/// </summary>
/// <remarks>
/// <p>
/// This, the default, implementation always returns <see langword="true"/>.
/// </p>
/// </remarks>
/// <param name="type">
/// The candidate <see cref="System.Type"/>.
/// </param>
/// <returns>
/// <see langword="true"/> if the advice should apply to the supplied
/// <paramref name="type"/>
/// </returns>
public virtual bool Matches(Type type)
{
return true;
}
/// <summary>
/// Can the advised interfaces be implemented by the introduction
/// advice?
/// </summary>
/// <remarks>
/// <p>
/// Invoked <b>before</b> adding an
/// <seealso cref="Spring.Aop.IIntroductionAdvisor"/>.
/// </p>
/// </remarks>
/// <exception cref="System.ArgumentException">
/// If the advised interfaces cannot be implemented by the introduction
/// advice.
/// </exception>
/// <seealso cref="Spring.Aop.IIntroductionAdvisor.Interfaces"/>
/// <exception cref="System.ArgumentException">
/// If any of the <see cref="Interfaces"/> are not interface <see cref="System.Type"/>.
/// </exception>
public virtual void ValidateInterfaces()
{
foreach (Type intf in _interfaces)
{
BailIfNotAnInterfaceType(intf);
if (! intf.IsAssignableFrom(_introduction.GetType()))
{
throw new ArgumentException("Introduction [" + _introduction.GetType().FullName + "] " +
"does not implement interface '" + intf.FullName + "' specified in introduction advice.");
}
}
}
private static void BailIfNotAnInterfaceType(Type intf)
{
if (intf != null && !intf.IsInterface)
{
throw new ArgumentException("Type [" + intf.FullName + "] is not an interface; cannot be used in an introduction.");
}
}
/// <summary>
/// 2 IntroductionAdvisors are considered equal if
/// a) they are of the same type
/// b) their introduction advices are equal
/// c) they introduce the same interfaces
/// </summary>
public bool Equals(DefaultIntroductionAdvisor other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
if (other.GetType() != this.GetType())
return false;
return Equals(other._introduction, _introduction) && Equals(other._interfaces, _interfaces);
}
/// <summary>
/// 2 IntroductionAdvisors are considered equal if
/// a) they are of the same type
/// b) their introduction advices are equal
/// c) they introduce the same interfaces
/// </summary>
public override bool Equals(object obj)
{
return Equals(obj as DefaultIntroductionAdvisor);
}
/// <summary>
/// 2 IntroductionAdvisors are considered equal if
/// a) they are of the same type
/// b) their introduction advices are equal
/// c) they introduce the same interfaces
/// </summary>
public override int GetHashCode()
{
unchecked
{
return ((_introduction != null ? _introduction.GetHashCode() : 0)*397) ^ (_interfaces != null ? _interfaces.GetHashCode() : 0);
}
}
}
}
|