#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 System.Reflection;
#endregion
namespace Spring.Util{
/// <summary>
/// Discovers the attributes of a <see cref="System.Delegate"/>
/// <see cref="System.Type"/> and provides access to the
/// <see cref="System.Delegate"/> <see cref="System.Type"/>s metadata.
/// </summary>
/// <author>Rick Evans</author>
public sealed class DelegateInfo
{
#region Constants
/// <summary>
/// The method name associated with a delegate invocation.
/// </summary>
private const string InvocationMethod = "Invoke";
#endregion
#region Constructor (s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Util.DelegateInfo"/> class.
/// </summary>
/// <param name="eventMeta">
/// The event used to extract the delegate <see cref="System.Type"/>
/// from.
/// </param>
/// <exception cref="System.NullReferenceException">
/// if the supplied <paramref name="eventMeta"/> is
/// <see langword="null"/>.
/// </exception>
public DelegateInfo(EventInfo eventMeta) : this(eventMeta.EventHandlerType)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Util.DelegateInfo"/> class.
/// </summary>
/// <param name="type">
/// The delegate <see cref="System.Type"/>.
/// </param>
/// <exception cref="System.ArgumentException">
/// If the supplied <see cref="System.Type"/> is not a subclass of the
/// <see cref="System.Delegate"/> class, or is <see langword="null"/>.
/// </exception>
public DelegateInfo(Type type)
{
DelegateType = type;
}
#endregion
#region Properties
/// <summary>
/// The <see cref="System.Type"/> of the delegate.
/// </summary>
private Type DelegateType
{
get { return _delegateType; }
set
{
if (!DelegateInfo.IsDelegate(value))
{
throw new ArgumentException("Not a delegate Type");
}
_delegateType = value;
}
}
#endregion
#region Methods
/// <summary>
/// Checks to see if the method encapsulated by the supplied method
/// metadata is compatible with the method signature associated with
/// this delegate type.
/// </summary>
/// <param name="method">The method to be checked.</param>
/// <returns>
/// <see langword="true"/> if the method signature is compatible with
/// the signature of this delegate; <see langword="false"/> if not, or
/// if the supplied <paramref name="method"/> parameter is
/// <see langword="null"/>.
/// </returns>
public bool IsSignatureCompatible(MethodInfo method)
{
if (method != null &&
method.ReturnType.Equals(GetReturnType()))
{
ParameterInfo[] methodParameters =
method.GetParameters();
Type[] delegateParameters = GetParameterTypes();
if (methodParameters.Length == delegateParameters.Length)
{
for (int i = 0; i < methodParameters.Length; ++i)
{
if (!methodParameters[i].ParameterType.
Equals(delegateParameters[i]))
{
return false;
}
}
return true;
}
}
return false;
}
/// <summary>
/// Gets the <see cref="System.Type"/>s of the parameters of the
/// method signature associated with this delegate type.
/// </summary>
/// <remarks>
/// <p>
/// This method will never return <see langword="null"/>; the returned
/// <see cref="System.Type"/> array may be empty, but it most certainly
/// will not be <see langword="null"/>.
/// </p>
/// </remarks>
/// <returns>
/// A <see cref="System.Type"/> array of the parameter
/// <see cref="System.Type"/>s; or the <see cref="System.Type.EmptyTypes"/>
/// array if the method signature has no parameters.
/// </returns>
public Type[] GetParameterTypes()
{
ParameterInfo[] parameters = GetMethod().GetParameters();
if (parameters != null
&& parameters.Length > 0)
{
Type[] types = new Type[parameters.Length];
for (int i = 0; i < parameters.Length; ++i)
{
types[i] = parameters[i].ParameterType;
}
return types;
}
return Type.EmptyTypes;
}
/// <summary>
/// Gets the return <see cref="System.Type"/> of the
/// method signature associated with this delegate type.
/// </summary>
/// <returns>The return <see cref="System.Type"/>.</returns>
public Type GetReturnType()
{
return GetMethod().ReturnType;
}
/// <summary>
/// Gets the metadata about the method signature associated
/// with this delegate type.
/// </summary>
/// <returns>
/// The metadata about the method signature associated
/// with this delegate type.
/// </returns>
public MethodInfo GetMethod()
{
return DelegateType.GetMethod(DelegateInfo.InvocationMethod);
}
/// <summary>
/// Determines whether the supplied <see cref="System.Type"/>
/// is a <see cref="System.Delegate"/> type.
/// </summary>
/// <param name="type">
/// The <see cref="System.Type"/> to be checked.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <see cref="System.Type"/>
/// is a <see cref="System.Delegate"/> <see cref="System.Type"/>;
/// <see langword="false"/> if not or the supplied
/// <paramref name="type"/> is <see langword="null"/>.
/// </returns>
public static bool IsDelegate(Type type)
{
return type == null ?
false :
type.IsSubclassOf(typeof (Delegate));
}
/// <summary>
/// Checks if the signature of the supplied <paramref name="handlerMethod"/>
/// is compatible with the signature expected by the supplied
/// <paramref name="eventMeta"/>.
/// </summary>
/// <param name="eventMeta">The event to be checked against.</param>
/// <param name="handlerMethod">
/// The method signature to check for compatibility.
/// </param>
/// <returns>
/// <see langword="true"/> if the signature of the supplied
/// <paramref name="handlerMethod"/> is compatible with the signature
/// expected by the supplied <paramref name="eventMeta"/>;
/// <see langword="false"/> if not or either of the supplied
/// parameters is <see langword="null"/>.
/// </returns>
/// <seealso cref="Spring.Util.DelegateInfo.IsSignatureCompatible(MethodInfo)"/>
public static bool IsSignatureCompatible(
EventInfo eventMeta, MethodInfo handlerMethod)
{
bool compatible = false;
if (eventMeta != null
&& DelegateInfo.IsDelegate(eventMeta.EventHandlerType))
{
compatible = new DelegateInfo(eventMeta.EventHandlerType)
.IsSignatureCompatible(handlerMethod);
}
return compatible;
}
#endregion
#region Fields
private Type _delegateType;
#endregion
}
}
|