Global reformat for files (#272)

This commit is contained in:
Marko Lahma
2025-03-28 23:33:23 +02:00
committed by GitHub
parent 07049eb630
commit 1d01cace77
2613 changed files with 309377 additions and 308353 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<clear />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>

View File

@@ -5,7 +5,6 @@ THE SPRING.NET FRAMEWORK
---------------------------------------------------------
http://www.springframework.net/
## INTRODUCTION
Spring.NET contains:
@@ -19,23 +18,29 @@ Spring.NET contains:
* ASP.NET MVC and ASP.NET WebAPI Framework
* Dependency Injection for MVC (includin WebAPI).
* Declarative transaction management abstraction
* Declarative transaction management via use of common XML configuration and attributes across different transaction APIs
* Declarative transaction management via use of common XML configuration and attributes across different transaction
APIs
* ADO.NET framework
* Simplifies use of ADO.NET. DAO support classes and integration with Spring's declarative transaction management functionality
* Simplifies use of ADO.NET. DAO support classes and integration with Spring's declarative transaction management
functionality
* Portable Service Abstractions
* Export plain .NET objects via .NET Remoting, Web Service or .NET Serviced Component and create client side proxies based on endpoint URL and service interface.
* Export plain .NET objects via .NET Remoting, Web Service or .NET Serviced Component and create client side proxies
based on endpoint URL and service interface.
* NHibernate Integation
* NHibernate 5 integration to simplify use of NHibernate and participate in Spring's declarative transaction management functionality.
* NHibernate 5 integration to simplify use of NHibernate and participate in Spring's declarative transaction
management functionality.
* ASP.NET AJAX Integration
* Exporter to expose plain object on which Dependency Injection and AOP have been applied to JavaScript.
* NUnit and MSTest integration
* Provides Dependency Injection of test cases and Spring container loading and caching. . Data access and transaction management features aid with integration testing.
* Provides Dependency Injection of test cases and Spring container loading and caching. . Data access and
transaction management features aid with integration testing.
* WCF integration
* Provides Dependency Injection and applicatin of AOP advice to WCF services
* Quartz integration
* Configure Quartz jobs using dependency injection and Spring's transactional support to persist job details
* MSMQ integration
* Simplifies the use MSMQ by providing helper classes for message sending and receiving. Integrates with Spring's transaction management features.
* Simplifies the use MSMQ by providing helper classes for message sending and receiving. Integrates with Spring's
transaction management features.
* NMS integration
* Simplifies the use of NMS by providing helper classes for message sending and receiving.
* TIBCO EMS integration
@@ -43,7 +48,8 @@ Spring.NET contains:
* NVelocity integration
* Simplifies the use of configuring NVelocity
Spring.NET is a port of the Java based Spring Framework. In turn, the Java/J2EE Spring Framework is based on code published in "Expert One-on-One J2EE Design and Development" by Rod Johnson (Wrox, 2002).
Spring.NET is a port of the Java based Spring Framework. In turn, the Java/J2EE Spring Framework is based on code
published in "Expert One-on-One J2EE Design and Development" by Rod Johnson (Wrox, 2002).
## SUPPORTED .NET FRAMEWORK VERSIONS
@@ -64,7 +70,7 @@ Release contents:
* `doc` contains reference documentation, MSDN-style API help, and the Spring.NET xsd.
* `examples` contains sample applications.
* `build-support` contains additonal applications need to build using NAnt as some convenience
VS.NET solution files.
VS.NET solution files.
* `dev-support` contains 'developer support' tools and code, such as solution templates for VS.NET
debug build is done using /DEBUG:full and release build using /DEBUG:pdbonly flags.
@@ -75,74 +81,89 @@ Latest info is available at the public website: http://www.springframework.net/
The Spring Framework is released under the terms of the Apache Software License (see license.txt).
## DISTRIBUTION DLLs
The "bin" directory contains the following distinct dll files for use in applications. Dependencies are those other than on the .NET BCL.
The "bin" directory contains the following distinct dll files for use in applications. Dependencies are those other than
on the .NET BCL.
* __Spring.Core__ (~765 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Core.svg)](https://www.nuget.org/packages/Spring.Core/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Core)](#)
* __Spring.Core__ (~765
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Core.svg)](https://www.nuget.org/packages/Spring.Core/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Core)](#)
* Contents: Inversion of control container. Collection classes.
* Dependencies: Common.Logging
* __Spring.Aop__ (~150 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Aop.svg)](https://www.nuget.org/packages/Spring.Aop/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Aop)](#)
* __Spring.Aop__ (~150
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Aop.svg)](https://www.nuget.org/packages/Spring.Aop/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Aop)](#)
* Contents: Abstract Oriented Programming Framework.
* Dependencies: Spring.Core, Common.Logging
* __Spring.Data__ (~320 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Data.svg)](https://www.nuget.org/packages/Spring.Data/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Data)](#)
* __Spring.Data__ (~320
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Data.svg)](https://www.nuget.org/packages/Spring.Data/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Data)](#)
* Contents: Transaction and ADO.NET Framework.
* Dependencies: Spring.Core, Spring.Aop
* __Spring.Data.NHibernate5__ (~90 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Data.NHibernate5.svg)](https://www.nuget.org/packages/Spring.Data.NHibernate5/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Data.NHibernate5)](#)
* __Spring.Data.NHibernate5__ (~90
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Data.NHibernate5.svg)](https://www.nuget.org/packages/Spring.Data.NHibernate5/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Data.NHibernate5)](#)
* Contents: NHibernate 5.x integration
* Dependencies: Spring.Core, Spring.Aop, Spring.Data, NHibernate
* __Spring.Services__ (~70 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Services.svg)](https://www.nuget.org/packages/Spring.Services/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Services)](#)
* __Spring.Services__ (~70
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Services.svg)](https://www.nuget.org/packages/Spring.Services/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Services)](#)
* Contents: Web Services, Remoting, and Enterprise Component based services.
* Dependencies: Spring.Core, Spring.Aop
* __Spring.Web__ (~165 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Web.svg)](https://www.nuget.org/packages/Spring.Web/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Web)](#)
* __Spring.Web__ (~165
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Web.svg)](https://www.nuget.org/packages/Spring.Web/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Web)](#)
* Contents: ASP.NET based Web Application Framework.
* Dependencies: Spring.Core, Spring.Aop
* __Spring.Web.Extensions__ (~8 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Web.Extensions.svg)](https://www.nuget.org/packages/Spring.Web.Extensions/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Web.Extensions)](#)
* __Spring.Web.Extensions__ (~8
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Web.Extensions.svg)](https://www.nuget.org/packages/Spring.Web.Extensions/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Web.Extensions)](#)
* Contents: ASP.NET AJAX Integartion
* Dependencies: Spring.Core, Spring.Aop, System.Web.Extensions
* __Spring.Web.Mvc5__ (~8 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Web.Mvc5.svg)](https://www.nuget.org/packages/Spring.Web.Mvc5/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Web.Mvc5)](#)
* __Spring.Web.Mvc5__ (~8
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Web.Mvc5.svg)](https://www.nuget.org/packages/Spring.Web.Mvc5/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Web.Mvc5)](#)
* Contents: ASP.NET MVC5 and WebAPI Integartion
* Dependencies: Spring.Core, Spring.Web
* __Spring.Testing.NUnit__ (~24 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Testing.NUnit.svg)](https://www.nuget.org/packages/Spring.Testing.NUnit/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Testing.NUnit)](#)
* __Spring.Testing.NUnit__ (~24
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Testing.NUnit.svg)](https://www.nuget.org/packages/Spring.Testing.NUnit/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Testing.NUnit)](#)
* Contents: NUnit Integration
* Dependencies: Spring.Core, Spring.Data, NUnit
* __Spring.Testing.Microsoft__ (~24 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Testing.Microsoft.svg)](https://www.nuget.org/packages/Spring.Testing.Microsoft/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Testing.Microsoft)](#)
* __Spring.Testing.Microsoft__ (~24
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Testing.Microsoft.svg)](https://www.nuget.org/packages/Spring.Testing.Microsoft/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Testing.Microsoft)](#)
* Contents: MSTest Integration
* Dependencies: Spring.Core, Spring.Data, MSTest
* __Spring.Messaging__ (~65 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Messaging.svg)](https://www.nuget.org/packages/Spring.Messaging/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Messaging)](#)
* __Spring.Messaging__ (~65
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Messaging.svg)](https://www.nuget.org/packages/Spring.Messaging/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Messaging)](#)
* Contents: MSMQ Integration
* Dependencies: Spring.Core, Spring.Data, System.Messaging
* __Spring.Messaging.Nms__ (~100 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Messaging.Nms.svg)](https://www.nuget.org/packages/Spring.Messaging.Nms/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Messaging.Nms)](#)
* __Spring.Messaging.Nms__ (~100
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Messaging.Nms.svg)](https://www.nuget.org/packages/Spring.Messaging.Nms/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Messaging.Nms)](#)
* Contents: NMS Integration
* Dependencies: Spring.Core, Spring.Data, Apache NMS
* __Spring.Scheduling.Quartz3__ (~44 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Scheduling.Quartz3.svg)](https://www.nuget.org/packages/Spring.Scheduling.Quartz3/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Scheduling.Quartz3)](#)
* __Spring.Scheduling.Quartz3__ (~44
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Scheduling.Quartz3.svg)](https://www.nuget.org/packages/Spring.Scheduling.Quartz3/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Scheduling.Quartz3)](#)
* Contents: Quartz32.x Integration
* Dependencies: Spring.Core, Spring.Data, Quartz
* __Spring.Template.Velocity__ (~44 KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Template.Velocity.svg)](https://www.nuget.org/packages/Spring.Template.Velocity/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Template.Velocity)](#)
* __Spring.Template.Velocity__ (~44
KB) [![NuGet](http://img.shields.io/nuget/v/Spring.Template.Velocity.svg)](https://www.nuget.org/packages/Spring.Template.Velocity/) [![Downloads](https://img.shields.io/nuget/dt/Spring.Template.Velocity)](#)
* Contents: NVelocity Integration
* Dependencies: Spring.Core, NVelocity
## WHERE TO START?
Documentation can be found in the "docs" directory:
* The Spring reference documentation
Documented sample applications can be found in "examples":
* IoCQuickStart.MovieFinder - A simple example demonstrating basic IoC container behavior.
* IoCQuickStart.AppContext - Show use of various IApplicationContext features.
* IoCQuickStart.EventRegistry - Show use of loosely coupled eventing features.
@@ -166,7 +187,8 @@ Documented sample applications can be found in "examples":
VS.NET
------
Visual Studio 2022 is required to open and build the solution. The free community version of Visual Studio should suffice.
Visual Studio 2022 is required to open and build the solution. The free community version of Visual Studio should
suffice.
## Acknowledgements

View File

@@ -5,4 +5,4 @@ public partial class Build
Target Ci => _ => _
.DependsOn(Compile, Test, Pack)
.Executes();
}
}

View File

@@ -3,7 +3,6 @@ using Nuke.Common;
using Nuke.Common.IO;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
public partial class Build
@@ -39,5 +38,4 @@ public partial class Build
bool PushCompleteOnFailure => true;
int PushDegreeOfParallelism => 5;
}

View File

@@ -1,21 +1,15 @@
using System.Linq;
using Nuke.Common;
using Nuke.Common.Tools.DotNet;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
public partial class Build
{
[Parameter]
readonly bool TestFull = false;
[Parameter]
readonly bool TestIntegrationData = false;
[Parameter]
readonly bool TestIntegrationEms = false;
[Parameter]
readonly bool TestIntegrationNms = false;
[Parameter]
readonly bool TestIntegrationMsMq = false;
[Parameter] readonly bool TestFull = false;
[Parameter] readonly bool TestIntegrationData = false;
[Parameter] readonly bool TestIntegrationEms = false;
[Parameter] readonly bool TestIntegrationNms = false;
[Parameter] readonly bool TestIntegrationMsMq = false;
Target Test => _ => _
.DependsOn(Restore)
@@ -55,5 +49,4 @@ public partial class Build
});
}
});
}
}

View File

@@ -27,17 +27,13 @@ partial class Build : NukeBuild
/// - JetBrains Rider https://nuke.build/rider
/// - Microsoft VisualStudio https://nuke.build/visualstudio
/// - Microsoft VSCode https://nuke.build/vscode
public static int Main() => Execute<Build>(x => x.Compile);
public static int Main () => Execute<Build>(x => x.Compile);
[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
[Parameter("Build EMS")] readonly bool BuildEms = false;
[Parameter("Build EMS")]
readonly bool BuildEms = false;
[Parameter("Version")]
readonly string ProjectVersion = "3.1.0";
[Parameter("Version")] readonly string ProjectVersion = "3.1.0";
[Solution] readonly Solution Solution;
[GitRepository] readonly GitRepository GitRepository;
@@ -180,35 +176,10 @@ partial class Build : NukeBuild
var binDirectory = RootDirectory / "bin";
binDirectory.CreateOrCleanDirectory();
var moduleNames = new[]
{
"Common.Logging",
"Common.Logging.Core",
"Spring.Core",
"Spring.Aop",
"Spring.Data",
"Spring.Data.NHibernate*",
"Spring.Web",
"Spring.Web.Mvc5",
"Spring.Web.Extensions",
"Spring.Services",
"Spring.Testing.NUnit",
"Spring.Testing.Microsoft",
"Spring.Messaging.Ems",
"Spring.Messaging.Nms",
"Spring.Messaging",
"Spring.Scheduling.Quartz3",
"Spring.Template.Velocity",
"Spring.Web.Conversation.NHibernate5",
};
var moduleNames = new[] { "Common.Logging", "Common.Logging.Core", "Spring.Core", "Spring.Aop", "Spring.Data", "Spring.Data.NHibernate*", "Spring.Web", "Spring.Web.Mvc5", "Spring.Web.Extensions", "Spring.Services", "Spring.Testing.NUnit", "Spring.Testing.Microsoft", "Spring.Messaging.Ems", "Spring.Messaging.Nms", "Spring.Messaging", "Spring.Scheduling.Quartz3", "Spring.Template.Velocity", "Spring.Web.Conversation.NHibernate5", };
var patterns = moduleNames
.SelectMany(x => new []
{
"**/" + Configuration + "/**/" + x + ".dll",
"**/" + Configuration + "/**/" + x + ".xml",
"**/" + Configuration + "/**/" + x + ".pdb"
})
.SelectMany(x => new[] { "**/" + Configuration + "/**/" + x + ".dll", "**/" + Configuration + "/**/" + x + ".xml", "**/" + Configuration + "/**/" + x + ".pdb" })
.ToArray();
foreach (var file in BuildDirectory.GlobFiles(patterns))

View File

@@ -2,8 +2,8 @@
<PropertyGroup>
<CleanedProjectName>$(MSBuildProjectName.Replace('.2010', ''))</CleanedProjectName>
<CleanedProjectName>$(MSBuildProjectName.Replace('.2010', ''))</CleanedProjectName>
<AssemblyName>$(CleanedProjectName)</AssemblyName>
<PackageId>$(CleanedProjectName)</PackageId>
<RootNamespace>Spring</RootNamespace>

View File

@@ -20,35 +20,34 @@
using Spring.Objects.Factory.Xml;
namespace Spring.Aop.Config
namespace Spring.Aop.Config;
/// <summary>
/// Namespace parser for the aop namespace.
/// </summary>
/// <remarks>
/// Using the <code>advisor</code> tag you can configure an <see cref="IAdvisor"/> and have it
/// applied to all the relevant objects in your application context automatically. The
/// <code>advisor</code> tag supports only referenced <see cref="IPointcut"/>s.
/// </remarks>
/// <author>Rob harrop</author>
/// <author>Adrian Colyer</author>
/// <author>Rod Johnson</author>
/// <author>Mark Pollack (.NET)</author>
[
NamespaceParser(
Namespace = "http://www.springframework.net/aop",
SchemaLocationAssemblyHint = typeof(AopNamespaceParser),
SchemaLocation = "/Spring.Aop.Config/spring-aop-1.1.xsd"
)
]
public class AopNamespaceParser : NamespaceParserSupport
{
/// <summary>
/// Namespace parser for the aop namespace.
/// Register the <see cref="IObjectDefinitionParser"/> for the '<code>config</code>' tag.
/// </summary>
/// <remarks>
/// Using the <code>advisor</code> tag you can configure an <see cref="IAdvisor"/> and have it
/// applied to all the relevant objects in your application context automatically. The
/// <code>advisor</code> tag supports only referenced <see cref="IPointcut"/>s.
/// </remarks>
/// <author>Rob harrop</author>
/// <author>Adrian Colyer</author>
/// <author>Rod Johnson</author>
/// <author>Mark Pollack (.NET)</author>
[
NamespaceParser(
Namespace = "http://www.springframework.net/aop",
SchemaLocationAssemblyHint = typeof (AopNamespaceParser),
SchemaLocation = "/Spring.Aop.Config/spring-aop-1.1.xsd"
)
]
public class AopNamespaceParser : NamespaceParserSupport
public override void Init()
{
/// <summary>
/// Register the <see cref="IObjectDefinitionParser"/> for the '<code>config</code>' tag.
/// </summary>
public override void Init()
{
RegisterObjectDefinitionParser("config", new ConfigObjectDefinitionParser());
}
RegisterObjectDefinitionParser("config", new ConfigObjectDefinitionParser());
}
}

View File

@@ -29,67 +29,66 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Config
namespace Spring.Aop.Config;
/// <summary>
/// Utility class for handling registration of auto-proxy creators used internally by the
/// <code>aop</code> and <code>tx</code> namespace tags.
/// </summary>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
public class AopNamespaceUtils
{
/// <summary>
/// Utility class for handling registration of auto-proxy creators used internally by the
/// <code>aop</code> and <code>tx</code> namespace tags.
/// The object name of the internally managed auto-proxy creator.
/// </summary>
/// <author>Rob Harrop</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
public class AopNamespaceUtils
public static readonly string AUTO_PROXY_CREATOR_OBJECT_NAME = "Spring.Aop.Config.InternalAutoProxyCreator";
/// <summary>
/// The type of the APC that handles advisors with object role <see cref="ObjectRole.ROLE_INFRASTRUCTURE"/>.
/// </summary>
private static readonly Type InfrastructureAutoProxyCreatorType = typeof(InfrastructureAdvisorAutoProxyCreator);
/// <summary>
/// Registers the internal auto proxy creator if necessary.
/// </summary>
/// <param name="parserContext">The parser context.</param>
/// <param name="sourceElement">The source element.</param>
public static void RegisterAutoProxyCreatorIfNecessary(ParserContext parserContext, XmlElement sourceElement)
{
/// <summary>
/// The object name of the internally managed auto-proxy creator.
/// </summary>
public static readonly string AUTO_PROXY_CREATOR_OBJECT_NAME = "Spring.Aop.Config.InternalAutoProxyCreator";
AssertUtils.ArgumentNotNull(parserContext, "parserContext");
IObjectDefinitionRegistry registry = parserContext.Registry;
RegisterAutoProxyCreatorIfNecessary(registry);
}
/// <summary>
/// The type of the APC that handles advisors with object role <see cref="ObjectRole.ROLE_INFRASTRUCTURE"/>.
/// </summary>
private static readonly Type InfrastructureAutoProxyCreatorType = typeof(InfrastructureAdvisorAutoProxyCreator);
/// <summary>
/// Registers the internal auto proxy creator if necessary.
/// </summary>
public static void RegisterAutoProxyCreatorIfNecessary(IObjectDefinitionRegistry registry)
{
AssertUtils.ArgumentNotNull(registry, "registry");
/// <summary>
/// Registers the internal auto proxy creator if necessary.
/// </summary>
/// <param name="parserContext">The parser context.</param>
/// <param name="sourceElement">The source element.</param>
public static void RegisterAutoProxyCreatorIfNecessary(ParserContext parserContext, XmlElement sourceElement)
if (!registry.ContainsObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME))
{
AssertUtils.ArgumentNotNull(parserContext, "parserContext");
IObjectDefinitionRegistry registry = parserContext.Registry;
RegisterAutoProxyCreatorIfNecessary(registry);
RootObjectDefinition objectDefinition = new RootObjectDefinition(InfrastructureAutoProxyCreatorType);
objectDefinition.Role = ObjectRole.ROLE_INFRASTRUCTURE;
objectDefinition.PropertyValues.Add("order", int.MaxValue);
registry.RegisterObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME, objectDefinition);
}
}
/// <summary>
/// Registers the internal auto proxy creator if necessary.
/// </summary>
public static void RegisterAutoProxyCreatorIfNecessary(IObjectDefinitionRegistry registry)
/// <summary>
/// Forces the auto proxy creator to use decorator proxy.
/// </summary>
/// <param name="registry">The registry.</param>
public static void ForceAutoProxyCreatorToUseDecoratorProxy(IObjectDefinitionRegistry registry)
{
if (registry.ContainsObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME))
{
AssertUtils.ArgumentNotNull(registry, "registry");
if (!registry.ContainsObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME))
{
RootObjectDefinition objectDefinition = new RootObjectDefinition(InfrastructureAutoProxyCreatorType);
objectDefinition.Role = ObjectRole.ROLE_INFRASTRUCTURE;
objectDefinition.PropertyValues.Add("order", int.MaxValue);
registry.RegisterObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME, objectDefinition);
}
}
/// <summary>
/// Forces the auto proxy creator to use decorator proxy.
/// </summary>
/// <param name="registry">The registry.</param>
public static void ForceAutoProxyCreatorToUseDecoratorProxy(IObjectDefinitionRegistry registry)
{
if (registry.ContainsObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME))
{
IObjectDefinition definition = registry.GetObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME);
definition.PropertyValues.Add("ProxyTargetType", true);
}
IObjectDefinition definition = registry.GetObjectDefinition(AUTO_PROXY_CREATOR_OBJECT_NAME);
definition.PropertyValues.Add("ProxyTargetType", true);
}
}
}

View File

@@ -18,7 +18,6 @@
#endregion
using System.Xml;
using Spring.Aop.Support;
using Spring.Objects.Factory.Config;
@@ -26,134 +25,129 @@ using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Util;
namespace Spring.Aop.Config
namespace Spring.Aop.Config;
/// <summary>
/// The <see cref="IObjectDefinitionParser"/> for the <code>&lt;aop:config&gt;</code> tag.
/// </summary>
/// <author>Mark Pollack (.NET)</author>
public class ConfigObjectDefinitionParser : IObjectDefinitionParser
{
/// <summary>
/// The <see cref="IObjectDefinitionParser"/> for the <code>&lt;aop:config&gt;</code> tag.
/// The '<code>proxy-target-type</code>' attribute
/// </summary>
/// <author>Mark Pollack (.NET)</author>
public class ConfigObjectDefinitionParser : IObjectDefinitionParser
private static readonly string PROXY_TARGET_TYPE = "proxy-target-type";
private static readonly string ID = "id";
private static readonly string ORDER_PROPERTY = "order";
private static readonly string ADVICE_REF = "advice-ref";
private static readonly string ADVICE_OBJECT_NAME = "adviceObjectName";
private static readonly string POINTCUT_REF = "pointcut-ref";
#region IObjectDefinitionParser Members
/// <summary>
/// Parse the specified XmlElement and register the resulting
/// ObjectDefinitions with the <see cref="ParserContext.Registry"/> IObjectDefinitionRegistry
/// embedded in the supplied <see cref="ParserContext"/>
/// </summary>
/// <param name="element">The element to be parsed.</param>
/// <param name="parserContext">The object encapsulating the current state of the parsing process.
/// Provides access to a IObjectDefinitionRegistry</param>
/// <returns>The primary object definition.</returns>
/// <remarks>
/// <p>
/// This method is never invoked if the parser is namespace aware
/// and was called to process the root node.
/// </p>
/// </remarks>
public IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext)
{
/// <summary>
/// The '<code>proxy-target-type</code>' attribute
/// </summary>
private static readonly string PROXY_TARGET_TYPE = "proxy-target-type";
ConfigureAutoProxyCreator(parserContext, element);
XmlNodeList advisorNodes = element.GetElementsByTagName("advisor", element.NamespaceURI);
private static readonly string ID = "id";
private static readonly string ORDER_PROPERTY = "order";
private static readonly string ADVICE_REF = "advice-ref";
private static readonly string ADVICE_OBJECT_NAME = "adviceObjectName";
private static readonly string POINTCUT_REF = "pointcut-ref";
#region IObjectDefinitionParser Members
/// <summary>
/// Parse the specified XmlElement and register the resulting
/// ObjectDefinitions with the <see cref="ParserContext.Registry"/> IObjectDefinitionRegistry
/// embedded in the supplied <see cref="ParserContext"/>
/// </summary>
/// <param name="element">The element to be parsed.</param>
/// <param name="parserContext">The object encapsulating the current state of the parsing process.
/// Provides access to a IObjectDefinitionRegistry</param>
/// <returns>The primary object definition.</returns>
/// <remarks>
/// <p>
/// This method is never invoked if the parser is namespace aware
/// and was called to process the root node.
/// </p>
/// </remarks>
public IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext)
//XmlNodeList advisorNodes = element.SelectNodes("*[local-name()='advisor' and namespace-uri()='" + element.NamespaceURI + "']");
foreach (XmlElement advisorElement in advisorNodes)
{
ConfigureAutoProxyCreator(parserContext, element);
XmlNodeList advisorNodes = element.GetElementsByTagName("advisor", element.NamespaceURI);
ParseAdvisor(advisorElement, parserContext);
}
//XmlNodeList advisorNodes = element.SelectNodes("*[local-name()='advisor' and namespace-uri()='" + element.NamespaceURI + "']");
foreach (XmlElement advisorElement in advisorNodes)
return null;
}
/// <summary>
/// Parses the supplied advisor element and registers the resulting <see cref="IAdvisor"/>
/// </summary>
/// <param name="advisorElement">The advisor element.</param>
/// <param name="parserContext">The parser context.</param>
private void ParseAdvisor(XmlElement advisorElement, ParserContext parserContext)
{
AbstractObjectDefinition advisorDef = CreateAdvisorObjectDefinition(advisorElement, parserContext);
string id = advisorElement.GetAttribute(ID);
string pointcutObjectName = ParsePointcutProperty(advisorElement, parserContext);
advisorDef.PropertyValues.Add(POINTCUT_REF, new RuntimeObjectReference(pointcutObjectName));
string advisorObjectName = id;
if (StringUtils.HasText(advisorObjectName))
{
parserContext.Registry.RegisterObjectDefinition(advisorObjectName, advisorDef);
}
else
{
parserContext.ReaderContext.RegisterWithGeneratedName(advisorDef);
}
}
private string ParsePointcutProperty(XmlElement element, ParserContext parserContext)
{
if (element.HasAttribute(POINTCUT_REF))
{
string pointcutRef = element.GetAttribute(POINTCUT_REF);
if (!StringUtils.HasText(pointcutRef))
{
ParseAdvisor(advisorElement, parserContext);
parserContext.ReaderContext.ReportException(element, "advisor", "'pointcut-ref' attribute contains empty value.");
}
return pointcutRef;
}
else
{
parserContext.ReaderContext.ReportException(element, "advisor", "'must define 'pointcut-ref' on <advisor> tag.");
return null;
}
/// <summary>
/// Parses the supplied advisor element and registers the resulting <see cref="IAdvisor"/>
/// </summary>
/// <param name="advisorElement">The advisor element.</param>
/// <param name="parserContext">The parser context.</param>
private void ParseAdvisor(XmlElement advisorElement, ParserContext parserContext)
{
AbstractObjectDefinition advisorDef = CreateAdvisorObjectDefinition(advisorElement, parserContext);
string id = advisorElement.GetAttribute(ID);
string pointcutObjectName = ParsePointcutProperty(advisorElement, parserContext);
advisorDef.PropertyValues.Add(POINTCUT_REF, new RuntimeObjectReference(pointcutObjectName));
string advisorObjectName = id;
if (StringUtils.HasText(advisorObjectName))
{
parserContext.Registry.RegisterObjectDefinition(advisorObjectName, advisorDef);
}
else
{
parserContext.ReaderContext.RegisterWithGeneratedName(advisorDef);
}
}
private string ParsePointcutProperty(XmlElement element, ParserContext parserContext)
{
if (element.HasAttribute(POINTCUT_REF))
{
string pointcutRef = element.GetAttribute(POINTCUT_REF);
if (!StringUtils.HasText(pointcutRef))
{
parserContext.ReaderContext.ReportException(element, "advisor", "'pointcut-ref' attribute contains empty value.");
}
return pointcutRef;
}
else
{
parserContext.ReaderContext.ReportException(element, "advisor", "'must define 'pointcut-ref' on <advisor> tag.");
return null;
}
}
private AbstractObjectDefinition CreateAdvisorObjectDefinition(XmlElement advisorElement, ParserContext parserContext)
{
ObjectDefinitionBuilder advisorDefinitionBuilder =
parserContext.ParserHelper.CreateRootObjectDefinitionBuilder(typeof(DefaultObjectFactoryPointcutAdvisor));
advisorDefinitionBuilder.RawObjectDefinition.Role = ObjectRole.ROLE_INFRASTRUCTURE;
if (advisorElement.HasAttribute(ORDER_PROPERTY))
{
advisorDefinitionBuilder.AddPropertyValue(ORDER_PROPERTY, advisorElement.GetAttribute(ORDER_PROPERTY));
}
advisorDefinitionBuilder.AddPropertyValue(ADVICE_OBJECT_NAME, advisorElement.GetAttribute(ADVICE_REF));
return advisorDefinitionBuilder.ObjectDefinition;
}
private static void ConfigureAutoProxyCreator(ParserContext parserContext, XmlElement element)
{
AopNamespaceUtils.RegisterAutoProxyCreatorIfNecessary(parserContext, element);
bool proxyTargetClass =
parserContext.ParserHelper.IsTrueStringValue(element.GetAttribute(PROXY_TARGET_TYPE));
if (proxyTargetClass)
{
AopNamespaceUtils.ForceAutoProxyCreatorToUseDecoratorProxy(parserContext.Registry);
}
}
#endregion
}
}
private AbstractObjectDefinition CreateAdvisorObjectDefinition(XmlElement advisorElement, ParserContext parserContext)
{
ObjectDefinitionBuilder advisorDefinitionBuilder =
parserContext.ParserHelper.CreateRootObjectDefinitionBuilder(typeof(DefaultObjectFactoryPointcutAdvisor));
advisorDefinitionBuilder.RawObjectDefinition.Role = ObjectRole.ROLE_INFRASTRUCTURE;
if (advisorElement.HasAttribute(ORDER_PROPERTY))
{
advisorDefinitionBuilder.AddPropertyValue(ORDER_PROPERTY, advisorElement.GetAttribute(ORDER_PROPERTY));
}
advisorDefinitionBuilder.AddPropertyValue(ADVICE_OBJECT_NAME, advisorElement.GetAttribute(ADVICE_REF));
return advisorDefinitionBuilder.ObjectDefinition;
}
private static void ConfigureAutoProxyCreator(ParserContext parserContext, XmlElement element)
{
AopNamespaceUtils.RegisterAutoProxyCreatorIfNecessary(parserContext, element);
bool proxyTargetClass =
parserContext.ParserHelper.IsTrueStringValue(element.GetAttribute(PROXY_TARGET_TYPE));
if (proxyTargetClass)
{
AopNamespaceUtils.ForceAutoProxyCreatorToUseDecoratorProxy(parserContext.Registry);
}
}
#endregion
}

View File

@@ -1,99 +1,99 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://www.springframework.net/aop"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:objects="http://www.springframework.net"
xmlns:tool="http://www.springframework.net/tool"
targetNamespace="http://www.springframework.net/aop"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:objects="http://www.springframework.net"
xmlns:tool="http://www.springframework.net/tool"
targetNamespace="http://www.springframework.net/aop"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.net"/>
<xsd:import namespace="http://www.springframework.net/tool"/>
<xsd:import namespace="http://www.springframework.net" />
<xsd:import namespace="http://www.springframework.net/tool" />
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for the Spring Framework's AOP support.
]]></xsd:documentation>
</xsd:annotation>
</xsd:annotation>
<xsd:element name="config">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:element name="config">
<xsd:annotation>
<xsd:documentation><![CDATA[
A section (compartmentalization) of AOP-specific configuration (including
aspects, pointcuts, etc).
]]></xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="advisor" type="advisorType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation source="net:Spring.Aop.IAdvisor"><![CDATA[
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="advisor" type="advisorType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation source="net:Spring.Aop.IAdvisor"><![CDATA[
A named advisor definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="proxy-target-type" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
</xsd:sequence>
<xsd:attribute name="proxy-target-type" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[
Are decorator-based (inheritance) proxies to be created? By default, composition-based proxies are created.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="advisorType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="Spring.Aop.IAdvisor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<!-- Rick : ID type written explicitly as opposed to being imported (c.f. [SPR-2290] -->
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="advice-ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:complexType name="advisorType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="Spring.Aop.IAdvisor" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<!-- Rick : ID type written explicitly as opposed to being imported (c.f. [SPR-2290] -->
<xsd:attribute name="id" type="xsd:ID" />
<xsd:attribute name="advice-ref" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to an advice bean.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.aop.Advisor"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pointcut-ref" type="pointcutRefType">
<xsd:annotation>
<xsd:documentation><![CDATA[
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.aop.Advisor" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="pointcut-ref" type="pointcutRefType">
<xsd:annotation>
<xsd:documentation><![CDATA[
A reference to a pointcut definition.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.core.Ordered"><![CDATA[
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="order" type="xsd:int">
<xsd:annotation>
<xsd:documentation source="java:org.springframework.core.Ordered"><![CDATA[
Controls the ordering of the execution of this advice when multiple
advice executes at a specific joinpoint.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="pointcutRefType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.aop.Pointcut"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string"/>
</xsd:simpleType>
<xsd:simpleType name="pointcutRefType">
<xsd:annotation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.aop.Pointcut" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:union memberTypes="xsd:string" />
</xsd:simpleType>
</xsd:schema>

View File

@@ -23,300 +23,302 @@
using System.Collections;
using System.Reflection;
using System.Text;
using AopAlliance.Intercept;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Convenience base class for <see cref="AopAlliance.Intercept.IMethodInvocation"/>
/// implementations.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override the
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint()"/>
/// method to change this behavior, so this is a useful/ base class for
/// <see cref="AopAlliance.Intercept.IMethodInvocation"/> implementations.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Rick Evans (.NET)</author>
/// <author>Bruno Baia (.NET)</author>
[Serializable]
public abstract class AbstractMethodInvocation : IMethodInvocation
{
/// <summary>
/// Convenience base class for <see cref="AopAlliance.Intercept.IMethodInvocation"/>
/// implementations.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override the
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint()"/>
/// method to change this behavior, so this is a useful/ base class for
/// <see cref="AopAlliance.Intercept.IMethodInvocation"/> implementations.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Rick Evans (.NET)</author>
/// <author>Bruno Baia (.NET)</author>
[Serializable]
public abstract class AbstractMethodInvocation : IMethodInvocation
{
/// <summary>
/// The arguments (if any = may be <see lang="null"/>) to the method
/// that is to be invoked.
/// </summary>
private object[] arguments;
/// <summary>
/// The arguments (if any = may be <see lang="null"/>) to the method
/// that is to be invoked.
/// </summary>
private object[] arguments;
/// <summary>
/// The target object that the method is to be invoked on.
/// </summary>
private readonly object target;
/// <summary>
/// The target object that the method is to be invoked on.
/// </summary>
private readonly object target;
/// <summary>
/// The AOP proxy for the target object.
/// </summary>
private object proxy;
/// <summary>
/// The AOP proxy for the target object.
/// </summary>
private object proxy;
/// <summary>
/// The method invocation that is to be invoked.
/// </summary>
private MethodInfo method;
/// <summary>
/// The method invocation that is to be invoked.
/// </summary>
private MethodInfo method;
/// <summary>
/// The list of <see cref="AopAlliance.Intercept.IMethodInterceptor"/> and
/// <cref see="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// that need dynamic checks.
/// </summary>
private IList interceptors;
/// <summary>
/// The list of <see cref="AopAlliance.Intercept.IMethodInterceptor"/> and
/// <cref see="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// that need dynamic checks.
/// </summary>
private IList interceptors;
/// <summary>
/// The declaring type of the method that is to be invoked.
/// </summary>
private Type targetType;
/// <summary>
/// The declaring type of the method that is to be invoked.
/// </summary>
private Type targetType;
/// <summary>
/// The index from 0 of the current interceptor we're invoking.
/// </summary>
private int currentInterceptorIndex;
/// <summary>
/// The index from 0 of the current interceptor we're invoking.
/// </summary>
private int currentInterceptorIndex;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such exposes no publicly visible
/// constructors.
/// </p>
/// <p>
/// <note type="implementnotes">
/// The <paramref name="interceptors"/> list can also contain any
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>s
/// that need evaluation at runtime.
/// <see cref="Spring.Aop.IMethodMatcher"/>s included in an
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// must already have been found to have matched as far as was possible
/// <b>statically</b>. Passing an array might be about 10% faster, but
/// would complicate the code, and it would work only for static
/// pointcuts.
/// </note>
/// </p>
/// </remarks>
/// <param name="proxy">The AOP proxy.</param>
/// <param name="target">The target object.</param>
/// <param name="method">the target method.</param>
/// <param name="arguments">The target method's arguments.</param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.</param>
/// <param name="interceptors">
/// The list of interceptors that are to be applied. May be
/// <cref lang="null"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the <paramref name="target"/> is <see lang="null"/>.
/// </exception>
protected AbstractMethodInvocation(object proxy, object target,
MethodInfo method, object[] arguments, Type targetType, IList interceptors)
{
// EE: There is not necessarily always a target - e.g. for DynamicEntities
// moved this check to InvokeJoinpoint()
AssertUtils.ArgumentNotNull(method, "method");
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such exposes no publicly visible
/// constructors.
/// </p>
/// <p>
/// <note type="implementnotes">
/// The <paramref name="interceptors"/> list can also contain any
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>s
/// that need evaluation at runtime.
/// <see cref="Spring.Aop.IMethodMatcher"/>s included in an
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// must already have been found to have matched as far as was possible
/// <b>statically</b>. Passing an array might be about 10% faster, but
/// would complicate the code, and it would work only for static
/// pointcuts.
/// </note>
/// </p>
/// </remarks>
/// <param name="proxy">The AOP proxy.</param>
/// <param name="target">The target object.</param>
/// <param name="method">the target method.</param>
/// <param name="arguments">The target method's arguments.</param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.</param>
/// <param name="interceptors">
/// The list of interceptors that are to be applied. May be
/// <cref lang="null"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the <paramref name="target"/> is <see lang="null"/>.
/// </exception>
protected AbstractMethodInvocation(object proxy, object target,
MethodInfo method, object[] arguments, Type targetType, IList interceptors)
{
// EE: There is not necessarily always a target - e.g. for DynamicEntities
// moved this check to InvokeJoinpoint()
AssertUtils.ArgumentNotNull(method, "method");
this.proxy = proxy;
this.target = target;
this.method = method;
this.targetType = targetType;
this.arguments = arguments;
this.interceptors = interceptors;
}
this.proxy = proxy;
this.target = target;
this.method = method;
this.targetType = targetType;
this.arguments = arguments;
this.interceptors = interceptors;
}
/// <summary>
/// Gets the method invocation that is to be invoked.
/// </summary>
/// <remarks>
/// <p>
/// May or may not correspond with a method invoked on an underlying
/// implementation of that interface.
/// </p>
/// </remarks>
/// <see cref="AopAlliance.Intercept.IMethodInvocation.Method"/>
public virtual MethodInfo Method
{
get { return method; }
protected set { method = value; }
}
/// <summary>
/// Gets the method invocation that is to be invoked.
/// </summary>
/// <remarks>
/// <p>
/// May or may not correspond with a method invoked on an underlying
/// implementation of that interface.
/// </p>
/// </remarks>
/// <see cref="AopAlliance.Intercept.IMethodInvocation.Method"/>
public virtual MethodInfo Method
{
get { return method; }
protected set { method = value; }
}
/// <summary>
/// Gets the static part of this joinpoint.
/// </summary>
/// <value>
/// The proxied member's information.
/// </value>
/// <see cref="AopAlliance.Intercept.IJoinpoint.StaticPart"/>
public virtual MemberInfo StaticPart
{
get { return Method; }
}
/// <summary>
/// Gets the static part of this joinpoint.
/// </summary>
/// <value>
/// The proxied member's information.
/// </value>
/// <see cref="AopAlliance.Intercept.IJoinpoint.StaticPart"/>
public virtual MemberInfo StaticPart
{
get { return Method; }
}
/// <summary>
/// Gets the proxy that this interception was made through.
/// </summary>
/// <value>
/// The proxy that this interception was made through.
/// </value>
public virtual object Proxy
{
get { return this.proxy; }
protected set { this.proxy = value; }
}
/// <summary>
/// Gets the target object for the invocation.
/// </summary>
/// <value>
/// The target object for this method invocation.
/// </value>
public virtual object Target
{
get { return this.target; }
}
/// <summary>
/// Gets the type of the target object.
/// </summary>
/// <value>
/// The type of the target object.
/// </value>
public virtual Type TargetType
{
get { return this.targetType; }
protected set { this.targetType = value; }
}
/// <summary>
/// Gets the proxy that this interception was made through.
/// </summary>
/// <value>
/// The proxy that this interception was made through.
/// </value>
public virtual object Proxy
{
get { return this.proxy; }
protected set { this.proxy = value; }
}
/// <summary>
/// Gets and sets the arguments (if any - may be <cref lang="null"/>)
/// to the method that is to be invoked.
/// </summary>
/// <value>
/// The arguments (if any - may be <cref lang="null"/>) to the
/// method that is to be invoked.
/// </value>
/// <see cref="AopAlliance.Intercept.IInvocation.Arguments"/>
public virtual object[] Arguments
{
get { return this.arguments; }
set { this.arguments = value; }
}
/// <summary>
/// Gets the target object for the invocation.
/// </summary>
/// <value>
/// The target object for this method invocation.
/// </value>
public virtual object Target
{
get { return this.target; }
}
/// <summary>
/// The list of method interceptors.
/// </summary>
/// <remarks>
/// <p>
/// May be <see lang="null"/>.
/// </p>
/// </remarks>
public virtual IList Interceptors
{
get { return this.interceptors; }
set { this.interceptors = value; }
}
/// <summary>
/// Gets the type of the target object.
/// </summary>
/// <value>
/// The type of the target object.
/// </value>
public virtual Type TargetType
{
get { return this.targetType; }
protected set { this.targetType = value; }
}
/// <summary>
/// Gets the target object.
/// </summary>
public virtual object This
{
get { return this.target; }
}
/// <summary>
/// Gets and sets the arguments (if any - may be <cref lang="null"/>)
/// to the method that is to be invoked.
/// </summary>
/// <value>
/// The arguments (if any - may be <cref lang="null"/>) to the
/// method that is to be invoked.
/// </value>
/// <see cref="AopAlliance.Intercept.IInvocation.Arguments"/>
public virtual object[] Arguments
{
get { return this.arguments; }
set { this.arguments = value; }
}
/// <summary>
/// The index from 0 of the current interceptor we're invoking.
/// </summary>
protected int CurrentInterceptorIndex
{
get { return currentInterceptorIndex; }
set { currentInterceptorIndex = value; }
}
/// <summary>
/// The list of method interceptors.
/// </summary>
/// <remarks>
/// <p>
/// May be <see lang="null"/>.
/// </p>
/// </remarks>
public virtual IList Interceptors
{
get { return this.interceptors; }
set { this.interceptors = value; }
}
/// <summary>
/// Proceeds to the next interceptor in the chain.
/// </summary>
/// <returns>
/// The return value of the method invocation.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors at the joinpoint throws an exception.
/// </exception>
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/>
public virtual object Proceed()
{
if (this.interceptors == null ||
this.currentInterceptorIndex == this.interceptors.Count)
{
AssertJoinpoint();
return InvokeJoinpoint();
}
object interceptor = this.interceptors[this.currentInterceptorIndex];
InterceptorAndDynamicMethodMatcher dynamicMatcher
= interceptor as InterceptorAndDynamicMethodMatcher;
IMethodInvocation nextInvocation = PrepareMethodInvocationForProceed(this);
if (dynamicMatcher != null)
{
// evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match...
if (dynamicMatcher.MethodMatcher.Matches(
/// <summary>
/// Gets the target object.
/// </summary>
public virtual object This
{
get { return this.target; }
}
/// <summary>
/// The index from 0 of the current interceptor we're invoking.
/// </summary>
protected int CurrentInterceptorIndex
{
get { return currentInterceptorIndex; }
set { currentInterceptorIndex = value; }
}
/// <summary>
/// Proceeds to the next interceptor in the chain.
/// </summary>
/// <returns>
/// The return value of the method invocation.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors at the joinpoint throws an exception.
/// </exception>
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/>
public virtual object Proceed()
{
if (this.interceptors == null ||
this.currentInterceptorIndex == this.interceptors.Count)
{
AssertJoinpoint();
return InvokeJoinpoint();
}
object interceptor = this.interceptors[this.currentInterceptorIndex];
InterceptorAndDynamicMethodMatcher dynamicMatcher
= interceptor as InterceptorAndDynamicMethodMatcher;
IMethodInvocation nextInvocation = PrepareMethodInvocationForProceed(this);
if (dynamicMatcher != null)
{
// evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match...
if (dynamicMatcher.MethodMatcher.Matches(
nextInvocation.Method, nextInvocation.TargetType, nextInvocation.Arguments))
{
return dynamicMatcher.Interceptor.Invoke(nextInvocation);
}
else
{
// dynamic match failed; skip this interceptor and invoke the next in the chain...
return nextInvocation.Proceed();
}
{
return dynamicMatcher.Interceptor.Invoke(nextInvocation);
}
else
{
// it's an interceptor so we just invoke it: the pointcut will have
// been evaluated statically before this object was constructed...
return ((IMethodInterceptor)interceptor).Invoke(nextInvocation);
// dynamic match failed; skip this interceptor and invoke the next in the chain...
return nextInvocation.Proceed();
}
}
/// <summary>
/// Retrieves a new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance
/// for the next Proceed method call.
/// </summary>
/// <param name="invocation">
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
/// </param>
/// <returns>
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
/// </returns>
/// <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation.PrepareMethodInvocationForProceed"/>
protected abstract IMethodInvocation PrepareMethodInvocationForProceed(
IMethodInvocation invocation);
/// <summary>
/// Performs sanity checks, whether the actual joinpoint may be invoked
/// </summary>
/// <remarks>
/// By default checks that the underlying target is not null and the called method is implemented
/// by the target's type.
/// </remarks>
/// <exception cref="ArgumentNullException">if <see cref="target"/> is <c>null</c>.</exception>
/// <exception cref="NotSupportedException">if the <see cref="target"/> 's type does not implement <see cref="method"/>.</exception>
protected virtual void AssertJoinpoint()
}
else
{
AssertUtils.ArgumentNotNull(target, "target");
// it's an interceptor so we just invoke it: the pointcut will have
// been evaluated statically before this object was constructed...
return ((IMethodInterceptor) interceptor).Invoke(nextInvocation);
}
}
/// <summary>
/// Retrieves a new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance
/// for the next Proceed method call.
/// </summary>
/// <param name="invocation">
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
/// </param>
/// <returns>
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
/// </returns>
/// <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation.PrepareMethodInvocationForProceed"/>
protected abstract IMethodInvocation PrepareMethodInvocationForProceed(
IMethodInvocation invocation);
/// <summary>
/// Performs sanity checks, whether the actual joinpoint may be invoked
/// </summary>
/// <remarks>
/// By default checks that the underlying target is not null and the called method is implemented
/// by the target's type.
/// </remarks>
/// <exception cref="ArgumentNullException">if <see cref="target"/> is <c>null</c>.</exception>
/// <exception cref="NotSupportedException">if the <see cref="target"/> 's type does not implement <see cref="method"/>.</exception>
protected virtual void AssertJoinpoint()
{
AssertUtils.ArgumentNotNull(target, "target");
// if (this.method != null
// && !this.method.DeclaringType.IsAssignableFrom(target.GetType()))
// {
@@ -324,56 +326,56 @@ namespace Spring.Aop.Framework
// // Since no interceptor has handled the call, we throw a sensible exception here.
// throw new NotSupportedException(string.Format("Interface method '{0}.{1}()' was not handled by any interceptor and the underlying target type '{2}' does not implement this method.", method.DeclaringType.FullName, method.Name, target.GetType().FullName));
// }
}
/// <summary>
/// Invokes the joinpoint.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override this to use custom invocation.
/// </p>
/// </remarks>
/// <returns>
/// The return value of the invocation of the joinpoint.
/// </returns>
/// <exception cref="System.Exception">
/// If invoking the joinpoint resulted in an exception.
/// </exception>
/// <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation.InvokeJoinpoint"/>
protected abstract object InvokeJoinpoint();
/// <summary>
/// A <see cref="System.String"/> that represents the current
/// invocation.
/// </summary>
/// <remarks>
/// <p>
/// <note type="implementnotes">
/// Does <b>not</b> invoke <see cref="System.Object.ToString()"/> on the
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.This"/> target
/// object, as that too may be proxied.
/// </note>
/// </p>
/// </remarks>
/// <returns>
/// A <see cref="System.String"/> that represents the current invocation.
/// </returns>
public override string ToString()
{
StringBuilder buffer = new StringBuilder("Invocation: method '");
buffer.Append(Method.Name).Append("', ").Append("arguments ");
buffer.Append(Arguments != null ? StringUtils.CollectionToCommaDelimitedString(Arguments) : "[none]");
buffer.Append("; ");
if (Target == null)
{
buffer.Append("target is null.");
}
else
{
buffer.Append("target is of Type [").Append(TargetType.FullName).Append(']');
}
/// <summary>
/// Invokes the joinpoint.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override this to use custom invocation.
/// </p>
/// </remarks>
/// <returns>
/// The return value of the invocation of the joinpoint.
/// </returns>
/// <exception cref="System.Exception">
/// If invoking the joinpoint resulted in an exception.
/// </exception>
/// <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation.InvokeJoinpoint"/>
protected abstract object InvokeJoinpoint();
/// <summary>
/// A <see cref="System.String"/> that represents the current
/// invocation.
/// </summary>
/// <remarks>
/// <p>
/// <note type="implementnotes">
/// Does <b>not</b> invoke <see cref="System.Object.ToString()"/> on the
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.This"/> target
/// object, as that too may be proxied.
/// </note>
/// </p>
/// </remarks>
/// <returns>
/// A <see cref="System.String"/> that represents the current invocation.
/// </returns>
public override string ToString()
{
StringBuilder buffer = new StringBuilder("Invocation: method '");
buffer.Append(Method.Name).Append("', ").Append("arguments ");
buffer.Append(Arguments != null ? StringUtils.CollectionToCommaDelimitedString(Arguments) : "[none]");
buffer.Append("; ");
if (Target == null)
{
buffer.Append("target is null.");
}
else
{
buffer.Append("target is of Type [").Append(TargetType.FullName).Append(']');
}
return buffer.ToString();
}
}
return buffer.ToString();
}
}

View File

@@ -24,85 +24,85 @@ using Spring.Objects.Factory.Config;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/> implementation
/// that registers instances of any non-default
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> instances with the
/// <see cref="Spring.Aop.Framework.Adapter.GlobalAdvisorAdapterRegistry"/>
/// singleton.
/// </summary>
/// <remarks>
/// <p>
/// The only requirement for it to work is that it needs to be defined
/// in an application context along with any arbitrary "non-native" Spring.NET
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> instances that need
/// to be recognized by Spring.NET's AOP framework.
/// </p>
/// </remarks>
/// <author>Dmitriy Kopylenko</author>
/// <author>Aleksandar Seovic (.NET)</author>
public class AdvisorAdapterRegistrationManager : IObjectPostProcessor
{
/// <summary>
/// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/> implementation
/// that registers instances of any non-default
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> instances with the
/// <see cref="Spring.Aop.Framework.Adapter.GlobalAdvisorAdapterRegistry"/>
/// singleton.
/// Apply this <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
/// to the given new object instance <i>before</i> any object initialization callbacks.
/// </summary>
/// <remarks>
/// <p>
/// The only requirement for it to work is that it needs to be defined
/// in an application context along with any arbitrary "non-native" Spring.NET
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> instances that need
/// to be recognized by Spring.NET's AOP framework.
/// Does nothing, simply returns the supplied <paramref name="instance"/> as is.
/// </p>
/// </remarks>
/// <author>Dmitriy Kopylenko</author>
/// <author>Aleksandar Seovic (.NET)</author>
public class AdvisorAdapterRegistrationManager : IObjectPostProcessor
/// <param name="instance">
/// The new object instance.
/// </param>
/// <param name="name">
/// The name of the object.
/// </param>
/// <returns>
/// The object instance to use, either the original or a wrapped one.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
public virtual object PostProcessBeforeInitialization(object instance, string name)
{
/// <summary>
/// Apply this <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
/// to the given new object instance <i>before</i> any object initialization callbacks.
/// </summary>
/// <remarks>
/// <p>
/// Does nothing, simply returns the supplied <paramref name="instance"/> as is.
/// </p>
/// </remarks>
/// <param name="instance">
/// The new object instance.
/// </param>
/// <param name="name">
/// The name of the object.
/// </param>
/// <returns>
/// The object instance to use, either the original or a wrapped one.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
public virtual object PostProcessBeforeInitialization(object instance, string name)
return instance;
}
/// <summary>
/// Apply this <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/> to the
/// given new object instance <i>after</i> any object initialization callbacks.
/// </summary>
/// <remarks>
/// <p>
/// Registers the supplied <paramref name="instance"/> with the
/// <see cref="Spring.Aop.Framework.Adapter.GlobalAdvisorAdapterRegistry"/>
/// singleton if it is an <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>
/// instance.
/// </p>
/// </remarks>
/// <param name="instance">
/// The new object instance.
/// </param>
/// <param name="objectName">
/// The name of the object.
/// </param>
/// <returns>
/// The object instance to use, either the original or a wrapped one.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
public virtual object PostProcessAfterInitialization(object instance, string objectName)
{
IAdvisorAdapter adapter = instance as IAdvisorAdapter;
if (adapter != null)
{
return instance;
GlobalAdvisorAdapterRegistry.Instance.RegisterAdvisorAdapter(adapter);
}
/// <summary>
/// Apply this <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/> to the
/// given new object instance <i>after</i> any object initialization callbacks.
/// </summary>
/// <remarks>
/// <p>
/// Registers the supplied <paramref name="instance"/> with the
/// <see cref="Spring.Aop.Framework.Adapter.GlobalAdvisorAdapterRegistry"/>
/// singleton if it is an <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>
/// instance.
/// </p>
/// </remarks>
/// <param name="instance">
/// The new object instance.
/// </param>
/// <param name="objectName">
/// The name of the object.
/// </param>
/// <returns>
/// The object instance to use, either the original or a wrapped one.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
public virtual object PostProcessAfterInitialization(object instance, string objectName)
{
IAdvisorAdapter adapter = instance as IAdvisorAdapter;
if (adapter != null)
{
GlobalAdvisorAdapterRegistry.Instance.RegisterAdvisorAdapter(adapter);
}
return instance;
}
return instance;
}
}
}

View File

@@ -25,55 +25,54 @@ using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> implementation
/// to enable <see cref="Spring.Aop.IAfterReturningAdvice"/> to be used in the
/// Spring.NET AOP framework.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal class AfterReturningAdviceAdapter : IAdvisorAdapter
{
/// <summary>
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> implementation
/// to enable <see cref="Spring.Aop.IAfterReturningAdvice"/> to be used in the
/// Spring.NET AOP framework.
/// Returns <see langword="true"/> if the supplied
/// <paramref name="advice"/> is an instance of the
/// <see cref="Spring.Aop.IAfterReturningAdvice"/> interface.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal class AfterReturningAdviceAdapter : IAdvisorAdapter
/// <param name="advice">The advice to check.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> is
/// an instance of the <see cref="Spring.Aop.IAfterReturningAdvice"/> interface;
/// <see langword="false"/> if not or if the supplied
/// <paramref name="advice"/> is <cref lang="null"/>.
/// </returns>
public virtual bool SupportsAdvice(IAdvice advice)
{
/// <summary>
/// Returns <see langword="true"/> if the supplied
/// <paramref name="advice"/> is an instance of the
/// <see cref="Spring.Aop.IAfterReturningAdvice"/> interface.
/// </summary>
/// <param name="advice">The advice to check.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> is
/// an instance of the <see cref="Spring.Aop.IAfterReturningAdvice"/> interface;
/// <see langword="false"/> if not or if the supplied
/// <paramref name="advice"/> is <cref lang="null"/>.
/// </returns>
public virtual bool SupportsAdvice(IAdvice advice)
{
return advice is IAfterReturningAdvice;
}
return advice is IAfterReturningAdvice;
}
/// <summary>
/// Wraps the supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> within a
/// <see cref="Spring.Aop.Framework.Adapter.AfterReturningAdviceInterceptor"/>
/// instance.
/// </summary>
/// <param name="advisor">
/// The advisor exposing the <see cref="AopAlliance.Aop.IAdvice"/> that
/// is to be wrapped.
/// </param>
/// <returns>
/// The supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> wrapped within a
/// <see cref="Spring.Aop.Framework.Adapter.AfterReturningAdviceInterceptor"/>
/// instance.
/// </returns>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
IAfterReturningAdvice advice = (IAfterReturningAdvice) advisor.Advice;
return new AfterReturningAdviceInterceptor(advice);
}
/// <summary>
/// Wraps the supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> within a
/// <see cref="Spring.Aop.Framework.Adapter.AfterReturningAdviceInterceptor"/>
/// instance.
/// </summary>
/// <param name="advisor">
/// The advisor exposing the <see cref="AopAlliance.Aop.IAdvice"/> that
/// is to be wrapped.
/// </param>
/// <returns>
/// The supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> wrapped within a
/// <see cref="Spring.Aop.Framework.Adapter.AfterReturningAdviceInterceptor"/>
/// instance.
/// </returns>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
IAfterReturningAdvice advice = (IAfterReturningAdvice) advisor.Advice;
return new AfterReturningAdviceInterceptor(advice);
}
}

View File

@@ -25,71 +25,70 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// Interceptor to wrap an <see cref="Spring.Aop.IAfterReturningAdvice"/>
/// instance.
/// </summary>
/// <remarks>
/// <p>
/// A more efficient alternative solution in cases where there is no
/// interception advice and therefore no need to create an
/// <see cref="AopAlliance.Intercept.IMethodInvocation"/> object may be
/// offered in future.
/// </p>
/// <p>
/// Used internally by the AOP framework: application developers should not need
/// to use this class directly.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class AfterReturningAdviceInterceptor : IMethodInterceptor
{
/// <summary>
/// Interceptor to wrap an <see cref="Spring.Aop.IAfterReturningAdvice"/>
/// instance.
/// </summary>
/// <remarks>
/// <p>
/// A more efficient alternative solution in cases where there is no
/// interception advice and therefore no need to create an
/// <see cref="AopAlliance.Intercept.IMethodInvocation"/> object may be
/// offered in future.
/// </p>
/// <p>
/// Used internally by the AOP framework: application developers should not need
/// to use this class directly.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class AfterReturningAdviceInterceptor : IMethodInterceptor
{
private IAfterReturningAdvice advice;
private IAfterReturningAdvice advice;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.AfterReturningAdviceInterceptor"/>
/// class.
/// </summary>
/// <param name="advice">
/// The advice to be applied after a target method successfully
/// returns.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="advice"/> is <see langword="null"/>.
/// </exception>
public AfterReturningAdviceInterceptor(IAfterReturningAdvice advice)
{
AssertUtils.ArgumentNotNull(advice, "advice");
this.advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.AfterReturningAdviceInterceptor"/>
/// class.
/// </summary>
/// <param name="advice">
/// The advice to be applied after a target method successfully
/// returns.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="advice"/> is <see langword="null"/>.
/// </exception>
public AfterReturningAdviceInterceptor(IAfterReturningAdvice advice)
{
AssertUtils.ArgumentNotNull(advice, "advice");
this.advice = advice;
}
/// <summary>
/// Executes interceptor after the target method successfully returns.
/// </summary>
/// <param name="invocation">
/// The method invocation that is being intercepted.
/// </param>
/// <returns>
/// The result of the call to the
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/> method of
/// the supplied <paramref name="invocation"/>; this return value may
/// well have been intercepted by the interceptor.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors in the chain or the target object itself
/// throws an exception.
/// </exception>
public object Invoke(IMethodInvocation invocation)
{
object returnValue = invocation.Proceed();
advice.AfterReturning(
returnValue, invocation.Method, invocation.Arguments, invocation.This);
return returnValue;
}
}
/// <summary>
/// Executes interceptor after the target method successfully returns.
/// </summary>
/// <param name="invocation">
/// The method invocation that is being intercepted.
/// </param>
/// <returns>
/// The result of the call to the
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/> method of
/// the supplied <paramref name="invocation"/>; this return value may
/// well have been intercepted by the interceptor.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors in the chain or the target object itself
/// throws an exception.
/// </exception>
public object Invoke(IMethodInvocation invocation)
{
object returnValue = invocation.Proceed();
advice.AfterReturning(
returnValue, invocation.Method, invocation.Arguments, invocation.This);
return returnValue;
}
}

View File

@@ -25,55 +25,54 @@ using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> implementation
/// to enable <see cref="Spring.Aop.IMethodBeforeAdvice"/> to be used in the
/// Spring.NET AOP framework.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal class BeforeAdviceAdapter : IAdvisorAdapter
{
/// <summary>
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> implementation
/// to enable <see cref="Spring.Aop.IMethodBeforeAdvice"/> to be used in the
/// Spring.NET AOP framework.
/// Returns <see langword="true"/> if the supplied
/// <paramref name="advice"/> is an instance of the
/// <see cref="Spring.Aop.IMethodBeforeAdvice"/> interface.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal class BeforeAdviceAdapter : IAdvisorAdapter
/// <param name="advice">The advice to check.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> is
/// an instance of the <see cref="Spring.Aop.IMethodBeforeAdvice"/> interface;
/// <see langword="false"/> if not or if the supplied
/// <paramref name="advice"/> is <cref lang="null"/>.
/// </returns>
public virtual bool SupportsAdvice(IAdvice advice)
{
/// <summary>
/// Returns <see langword="true"/> if the supplied
/// <paramref name="advice"/> is an instance of the
/// <see cref="Spring.Aop.IMethodBeforeAdvice"/> interface.
/// </summary>
/// <param name="advice">The advice to check.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> is
/// an instance of the <see cref="Spring.Aop.IMethodBeforeAdvice"/> interface;
/// <see langword="false"/> if not or if the supplied
/// <paramref name="advice"/> is <cref lang="null"/>.
/// </returns>
public virtual bool SupportsAdvice(IAdvice advice)
{
return advice is IMethodBeforeAdvice;
}
return advice is IMethodBeforeAdvice;
}
/// <summary>
/// Wraps the supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> within a
/// <see cref="Spring.Aop.Framework.Adapter.MethodBeforeAdviceInterceptor"/>
/// instance.
/// </summary>
/// <param name="advisor">
/// The advisor exposing the <see cref="AopAlliance.Aop.IAdvice"/> that
/// is to be wrapped.
/// </param>
/// <returns>
/// The supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> wrapped within a
/// <see cref="Spring.Aop.Framework.Adapter.MethodBeforeAdviceInterceptor"/>
/// instance.
/// </returns>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
IMethodBeforeAdvice advice = (IMethodBeforeAdvice) advisor.Advice;
return new MethodBeforeAdviceInterceptor(advice);
}
/// <summary>
/// Wraps the supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> within a
/// <see cref="Spring.Aop.Framework.Adapter.MethodBeforeAdviceInterceptor"/>
/// instance.
/// </summary>
/// <param name="advisor">
/// The advisor exposing the <see cref="AopAlliance.Aop.IAdvice"/> that
/// is to be wrapped.
/// </param>
/// <returns>
/// The supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> wrapped within a
/// <see cref="Spring.Aop.Framework.Adapter.MethodBeforeAdviceInterceptor"/>
/// instance.
/// </returns>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
IMethodBeforeAdvice advice = (IMethodBeforeAdvice) advisor.Advice;
return new MethodBeforeAdviceInterceptor(advice);
}
}

View File

@@ -26,126 +26,131 @@ using Spring.Aop.Support;
#endregion
namespace Spring.Aop.Framework.Adapter
{
/// <summary>
/// Default implementation of the
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapterRegistry"/>
/// interface.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class DefaultAdvisorAdapterRegistry : IAdvisorAdapterRegistry
{
private readonly IList<IAdvisorAdapter> adapters = new List<IAdvisorAdapter>();
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.DefaultAdvisorAdapterRegistry"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This constructor will also register the well-known
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> types.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>
public DefaultAdvisorAdapterRegistry()
/// <summary>
/// Default implementation of the
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapterRegistry"/>
/// interface.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class DefaultAdvisorAdapterRegistry : IAdvisorAdapterRegistry
{
private readonly IList<IAdvisorAdapter> adapters = new List<IAdvisorAdapter>();
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.DefaultAdvisorAdapterRegistry"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This constructor will also register the well-known
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> types.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>
public DefaultAdvisorAdapterRegistry()
{
// register well-known adapters...
RegisterAdvisorAdapter(new BeforeAdviceAdapter());
RegisterAdvisorAdapter(new AfterReturningAdviceAdapter());
RegisterAdvisorAdapter(new ThrowsAdviceAdapter());
}
/// <summary>
/// Returns an <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>.
/// </summary>
/// <param name="advice">
/// The object that should be an advice, such as
/// <see cref="Spring.Aop.IBeforeAdvice"/> or
/// <see cref="Spring.Aop.IThrowsAdvice"/>.
/// </param>
/// <returns>
/// An <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>. Never returns <cref lang="null"/>. If
/// the <paramref name="advice"/> parameter is an
/// <see cref="Spring.Aop.IAdvisor"/>, it will simply be returned.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If no registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> can wrap
/// the supplied <paramref name="advice"/>.
/// </exception>
public virtual IAdvisor Wrap(object advice)
{
if (advice is IAdvisor)
{
// register well-known adapters...
RegisterAdvisorAdapter(new BeforeAdviceAdapter());
RegisterAdvisorAdapter(new AfterReturningAdviceAdapter());
RegisterAdvisorAdapter(new ThrowsAdviceAdapter());
return (IAdvisor) advice;
}
/// <summary>
/// Returns an <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>.
/// </summary>
/// <param name="advice">
/// The object that should be an advice, such as
/// <see cref="Spring.Aop.IBeforeAdvice"/> or
/// <see cref="Spring.Aop.IThrowsAdvice"/>.
/// </param>
/// <returns>
/// An <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>. Never returns <cref lang="null"/>. If
/// the <paramref name="advice"/> parameter is an
/// <see cref="Spring.Aop.IAdvisor"/>, it will simply be returned.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If no registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> can wrap
/// the supplied <paramref name="advice"/>.
/// </exception>
public virtual IAdvisor Wrap(object advice)
{
if (advice is IAdvisor)
{
return (IAdvisor) advice;
}
if (!(advice is IAdvice))
{
throw new UnknownAdviceTypeException(advice);
}
IAdvice adviceObject = (IAdvice) advice;
if (adviceObject is IInterceptor)
{
// so well-known it doesn't even need an adapter...
return new DefaultPointcutAdvisor(adviceObject);
}
foreach (IAdvisorAdapter adapter in this.adapters)
{
// check that it is supported...
if (adapter.SupportsAdvice(adviceObject))
{
return new DefaultPointcutAdvisor(adviceObject);
}
}
throw new UnknownAdviceTypeException(advice);
}
if (!(advice is IAdvice))
{
throw new UnknownAdviceTypeException(advice);
}
/// <summary>
/// Returns an <see cref="AopAlliance.Intercept.IInterceptor"/> to
/// allow the use of the supplied <paramref name="advisor"/> in an
/// interception-based framework.
/// </summary>
/// <param name="advisor">The advisor to find an interceptor for.</param>
/// <returns>
/// An interceptor to expose this advisor's behaviour.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If the advisor type is not understood by any registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </exception>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
IAdvice advice = advisor.Advice;
if (advice is IInterceptor)
{
return (IInterceptor) advice;
}
foreach (IAdvisorAdapter adapter in this.adapters)
{
if (adapter.SupportsAdvice(advice))
{
return adapter.GetInterceptor(advisor);
}
}
throw new UnknownAdviceTypeException(advice);
}
IAdvice adviceObject = (IAdvice) advice;
if (adviceObject is IInterceptor)
{
// so well-known it doesn't even need an adapter...
return new DefaultPointcutAdvisor(adviceObject);
}
/// <summary>
/// Register the given <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </summary>
/// <param name="adapter">
/// An <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> that
/// understands the particular advisor and advice types.
/// </param>
public virtual void RegisterAdvisorAdapter(IAdvisorAdapter adapter)
{
this.adapters.Add(adapter);
}
}
foreach (IAdvisorAdapter adapter in this.adapters)
{
// check that it is supported...
if (adapter.SupportsAdvice(adviceObject))
{
return new DefaultPointcutAdvisor(adviceObject);
}
}
throw new UnknownAdviceTypeException(advice);
}
/// <summary>
/// Returns an <see cref="AopAlliance.Intercept.IInterceptor"/> to
/// allow the use of the supplied <paramref name="advisor"/> in an
/// interception-based framework.
/// </summary>
/// <param name="advisor">The advisor to find an interceptor for.</param>
/// <returns>
/// An interceptor to expose this advisor's behaviour.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If the advisor type is not understood by any registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </exception>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
IAdvice advice = advisor.Advice;
if (advice is IInterceptor)
{
return (IInterceptor) advice;
}
foreach (IAdvisorAdapter adapter in this.adapters)
{
if (adapter.SupportsAdvice(advice))
{
return adapter.GetInterceptor(advisor);
}
}
throw new UnknownAdviceTypeException(advice);
}
/// <summary>
/// Register the given <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </summary>
/// <param name="adapter">
/// An <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> that
/// understands the particular advisor and advice types.
/// </param>
public virtual void RegisterAdvisorAdapter(IAdvisorAdapter adapter)
{
this.adapters.Add(adapter);
}
}

View File

@@ -18,48 +18,47 @@
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// Provides Singleton-style access to the default
/// <see cref="IAdvisorAdapterRegistry"/> instance.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class GlobalAdvisorAdapterRegistry : DefaultAdvisorAdapterRegistry
{
private static readonly GlobalAdvisorAdapterRegistry instance
= new GlobalAdvisorAdapterRegistry();
/// <summary>
/// Provides Singleton-style access to the default
/// <see cref="IAdvisorAdapterRegistry"/> instance.
/// The default <see cref="IAdvisorAdapterRegistry"/> instance.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class GlobalAdvisorAdapterRegistry : DefaultAdvisorAdapterRegistry
public static GlobalAdvisorAdapterRegistry Instance
{
private static readonly GlobalAdvisorAdapterRegistry instance
= new GlobalAdvisorAdapterRegistry();
/// <summary>
/// The default <see cref="IAdvisorAdapterRegistry"/> instance.
/// </summary>
public static GlobalAdvisorAdapterRegistry Instance
{
get { return instance; }
}
#region Constructor (s) / Destructor
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.GlobalAdvisorAdapterRegistry"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This contructor is marked as <see langword="private"/> to enforce the
/// Singleton pattern
/// </p>
/// </remarks>
private GlobalAdvisorAdapterRegistry()
{
}
// CLOVER:ON
#endregion
get { return instance; }
}
#region Constructor (s) / Destructor
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.GlobalAdvisorAdapterRegistry"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This contructor is marked as <see langword="private"/> to enforce the
/// Singleton pattern
/// </p>
/// </remarks>
private GlobalAdvisorAdapterRegistry()
{
}
// CLOVER:ON
#endregion
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -25,74 +25,73 @@ using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework.Adapter
{
/// <summary>
/// Permits the handling of new advisors and advice types as extensions to
/// the Spring AOP framework.
/// </summary>
/// <remarks>
/// <p>
/// Implementors can create AOP Alliance
/// <see cref="AopAlliance.Intercept.IInterceptor"/>s from custom advice
/// types, enabling these advice types to be used in the Spring.NET AOP
/// framework, which uses interception under the covers.
/// </p>
/// <p>
/// There is no need for most Spring.NET users to implement this interface;
/// do so only if you need to introduce more
/// <see cref="Spring.Aop.IAdvisor"/> or <see cref="AopAlliance.Aop.IAdvice"/>
/// types to Spring.NET.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisorAdapter
{
/// <summary>
/// Does this adapter understand the supplied <paramref name="advice"/>?
/// </summary>
/// <remarks>
/// <p>
/// Is it valid to invoke the
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapterRegistry.Wrap"/>
/// method with the given advice as an argument?
/// </p>
/// </remarks>
/// <param name="advice">
/// <see cref="AopAlliance.Aop.IAdvice"/> such as
/// <see cref="Spring.Aop.IBeforeAdvice"/>.
/// </param>
/// <returns><see langword="true"/> if this adapter understands the
/// supplied <paramref name="advice"/>.
/// </returns>
bool SupportsAdvice(IAdvice advice);
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// Return an AOP Alliance
/// <see cref="AopAlliance.Intercept.IInterceptor"/> exposing the
/// behaviour of the given advice to an interception-based AOP
/// framework.
/// </summary>
/// <remarks>
/// <p>
/// Don't worry about any <see cref="Spring.Aop.IPointcut"/>
/// contained in the supplied <see cref="Spring.Aop.IAdvisor"/>;
/// the AOP framework will take care of checking the pointcut.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The advice. The
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter.SupportsAdvice"/>
/// method must have previously returned <see langword="true"/> on the
/// supplied <paramref name="advisor"/>.
/// </param>
/// <returns>
/// An AOP Alliance
/// <see cref="AopAlliance.Intercept.IInterceptor"/> exposing the
/// behaviour of the given advice to an interception-based AOP
/// framework.
/// </returns>
IInterceptor GetInterceptor(IAdvisor advisor);
}
}
/// <summary>
/// Permits the handling of new advisors and advice types as extensions to
/// the Spring AOP framework.
/// </summary>
/// <remarks>
/// <p>
/// Implementors can create AOP Alliance
/// <see cref="AopAlliance.Intercept.IInterceptor"/>s from custom advice
/// types, enabling these advice types to be used in the Spring.NET AOP
/// framework, which uses interception under the covers.
/// </p>
/// <p>
/// There is no need for most Spring.NET users to implement this interface;
/// do so only if you need to introduce more
/// <see cref="Spring.Aop.IAdvisor"/> or <see cref="AopAlliance.Aop.IAdvice"/>
/// types to Spring.NET.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisorAdapter
{
/// <summary>
/// Does this adapter understand the supplied <paramref name="advice"/>?
/// </summary>
/// <remarks>
/// <p>
/// Is it valid to invoke the
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapterRegistry.Wrap"/>
/// method with the given advice as an argument?
/// </p>
/// </remarks>
/// <param name="advice">
/// <see cref="AopAlliance.Aop.IAdvice"/> such as
/// <see cref="Spring.Aop.IBeforeAdvice"/>.
/// </param>
/// <returns><see langword="true"/> if this adapter understands the
/// supplied <paramref name="advice"/>.
/// </returns>
bool SupportsAdvice(IAdvice advice);
/// <summary>
/// Return an AOP Alliance
/// <see cref="AopAlliance.Intercept.IInterceptor"/> exposing the
/// behaviour of the given advice to an interception-based AOP
/// framework.
/// </summary>
/// <remarks>
/// <p>
/// Don't worry about any <see cref="Spring.Aop.IPointcut"/>
/// contained in the supplied <see cref="Spring.Aop.IAdvisor"/>;
/// the AOP framework will take care of checking the pointcut.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The advice. The
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter.SupportsAdvice"/>
/// method must have previously returned <see langword="true"/> on the
/// supplied <paramref name="advisor"/>.
/// </param>
/// <returns>
/// An AOP Alliance
/// <see cref="AopAlliance.Intercept.IInterceptor"/> exposing the
/// behaviour of the given advice to an interception-based AOP
/// framework.
/// </returns>
IInterceptor GetInterceptor(IAdvisor advisor);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -24,89 +24,88 @@ using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// A registry of
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> instances.
/// </summary>
/// <remarks>
/// <p>
/// Implementations <b>must</b> also automatically register adapters for
/// <see cref="AopAlliance.Intercept.IInterceptor"/> types.
/// </p>
/// <note>
/// This is an SPI interface, that should not need to be implemented by any
/// Spring.NET user.
/// </note>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisorAdapterRegistry
{
/// <summary>
/// A registry of
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> instances.
/// Returns an <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>.
/// </summary>
/// <param name="advice">
/// The object that should be an advice, such as
/// <see cref="Spring.Aop.IBeforeAdvice"/> or
/// <see cref="Spring.Aop.IThrowsAdvice"/>.
/// </param>
/// <returns>
/// An <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>. Never returns <cref lang="null"/>. If
/// the <paramref name="advice"/> parameter is an
/// <see cref="Spring.Aop.IAdvisor"/>, it will simply be returned.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If no registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> can wrap
/// the supplied <paramref name="advice"/>.
/// </exception>
IAdvisor Wrap(object advice);
/// <summary>
/// Returns an <see cref="AopAlliance.Intercept.IInterceptor"/> to
/// allow the use of the supplied <paramref name="advisor"/> in an
/// interception-based framework.
/// </summary>
/// <remarks>
/// <p>
/// Implementations <b>must</b> also automatically register adapters for
/// <see cref="AopAlliance.Intercept.IInterceptor"/> types.
/// Don't worry about the pointcut associated with the
/// <see cref="Spring.Aop.IAdvisor"/>; if it's an
/// <see cref="Spring.Aop.IPointcutAdvisor"/>, just return an
/// interceptor.
/// </p>
/// <note>
/// This is an SPI interface, that should not need to be implemented by any
/// Spring.NET user.
/// </note>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisorAdapterRegistry
{
/// <summary>
/// Returns an <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>.
/// </summary>
/// <param name="advice">
/// The object that should be an advice, such as
/// <see cref="Spring.Aop.IBeforeAdvice"/> or
/// <see cref="Spring.Aop.IThrowsAdvice"/>.
/// </param>
/// <returns>
/// An <see cref="Spring.Aop.IAdvisor"/> wrapping the supplied
/// <paramref name="advice"/>. Never returns <cref lang="null"/>. If
/// the <paramref name="advice"/> parameter is an
/// <see cref="Spring.Aop.IAdvisor"/>, it will simply be returned.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If no registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> can wrap
/// the supplied <paramref name="advice"/>.
/// </exception>
IAdvisor Wrap(object advice);
/// <param name="advisor">
/// The advisor to find an interceptor for.
/// </param>
/// <returns>
/// An interceptor to expose this advisor's behaviour.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If the advisor type is not understood by any registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </exception>
IInterceptor GetInterceptor(IAdvisor advisor);
/// <summary>
/// Returns an <see cref="AopAlliance.Intercept.IInterceptor"/> to
/// allow the use of the supplied <paramref name="advisor"/> in an
/// interception-based framework.
/// </summary>
/// <remarks>
/// <p>
/// Don't worry about the pointcut associated with the
/// <see cref="Spring.Aop.IAdvisor"/>; if it's an
/// <see cref="Spring.Aop.IPointcutAdvisor"/>, just return an
/// interceptor.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The advisor to find an interceptor for.
/// </param>
/// <returns>
/// An interceptor to expose this advisor's behaviour.
/// </returns>
/// <exception cref="UnknownAdviceTypeException">
/// If the advisor type is not understood by any registered
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </exception>
IInterceptor GetInterceptor(IAdvisor advisor);
/// <summary>
/// Register the given <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </summary>
/// <remarks>
/// <p>
/// Note that it is not necessary to register adapters for
/// <see cref="AopAlliance.Intercept.IInterceptor"/> instances: these
/// must be automatically recognized by an
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapterRegistry"/>
/// implementation.
/// </p>
/// </remarks>
/// <param name="adapter">
/// An <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> that
/// understands the particular advisor and advice types.
/// </param>
void RegisterAdvisorAdapter(IAdvisorAdapter adapter);
}
}
/// <summary>
/// Register the given <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/>.
/// </summary>
/// <remarks>
/// <p>
/// Note that it is not necessary to register adapters for
/// <see cref="AopAlliance.Intercept.IInterceptor"/> instances: these
/// must be automatically recognized by an
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapterRegistry"/>
/// implementation.
/// </p>
/// </remarks>
/// <param name="adapter">
/// An <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> that
/// understands the particular advisor and advice types.
/// </param>
void RegisterAdvisorAdapter(IAdvisorAdapter adapter);
}

View File

@@ -25,67 +25,66 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// <see cref="AopAlliance.Intercept.IInterceptor"/> implementation that
/// wraps <see cref="Spring.Aop.IMethodBeforeAdvice"/> instances.
/// </summary>
/// <remarks>
/// <p>
/// In the future Spring.NET may also offer a more efficient alternative
/// solution in cases where there is no interception advice and therefore
/// no need to create an <see cref="AopAlliance.Intercept.IMethodInvocation"/>
/// object.
/// </p>
/// <p>
/// Used internally by the Spring.NET AOP framework: application developers
/// should not need to use this class directly.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal sealed class MethodBeforeAdviceInterceptor : IMethodInterceptor
{
private IMethodBeforeAdvice advice;
/// <summary>
/// <see cref="AopAlliance.Intercept.IInterceptor"/> implementation that
/// wraps <see cref="Spring.Aop.IMethodBeforeAdvice"/> instances.
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.MethodBeforeAdviceInterceptor"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// In the future Spring.NET may also offer a more efficient alternative
/// solution in cases where there is no interception advice and therefore
/// no need to create an <see cref="AopAlliance.Intercept.IMethodInvocation"/>
/// object.
/// </p>
/// <p>
/// Used internally by the Spring.NET AOP framework: application developers
/// should not need to use this class directly.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal sealed class MethodBeforeAdviceInterceptor : IMethodInterceptor
/// <param name="advice">
/// The <see cref="Spring.Aop.IMethodBeforeAdvice"/> that is to be wrapped.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="advice"/> is <see langword="null"/>.
/// </exception>
public MethodBeforeAdviceInterceptor(IMethodBeforeAdvice advice)
{
private IMethodBeforeAdvice advice;
AssertUtils.ArgumentNotNull(advice, "advice");
this.advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.MethodBeforeAdviceInterceptor"/>
/// class.
/// </summary>
/// <param name="advice">
/// The <see cref="Spring.Aop.IMethodBeforeAdvice"/> that is to be wrapped.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="advice"/> is <see langword="null"/>.
/// </exception>
public MethodBeforeAdviceInterceptor(IMethodBeforeAdvice advice)
{
AssertUtils.ArgumentNotNull(advice, "advice");
this.advice = advice;
}
/// <summary>
/// Executes interceptor before the target method successfully returns.
/// </summary>
/// <param name="invocation">
/// The method invocation that is being intercepted.
/// </param>
/// <returns>
/// The result of the call to the
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/> method of
/// the supplied <paramref name="invocation"/>.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors in the chain or the target object itself
/// throws an exception.
/// </exception>
public object Invoke(IMethodInvocation invocation)
{
advice.Before(invocation.Method, invocation.Arguments, invocation.This);
return invocation.Proceed();
}
/// <summary>
/// Executes interceptor before the target method successfully returns.
/// </summary>
/// <param name="invocation">
/// The method invocation that is being intercepted.
/// </param>
/// <returns>
/// The result of the call to the
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/> method of
/// the supplied <paramref name="invocation"/>.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors in the chain or the target object itself
/// throws an exception.
/// </exception>
public object Invoke(IMethodInvocation invocation)
{
advice.Before(invocation.Method, invocation.Arguments, invocation.This);
return invocation.Proceed();
}
}

View File

@@ -25,54 +25,53 @@ using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> implementation
/// to enable <see cref="Spring.Aop.IThrowsAdvice"/> to be used in the
/// Spring.NET AOP framework.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal class ThrowsAdviceAdapter : IAdvisorAdapter
{
/// <summary>
/// <see cref="Spring.Aop.Framework.Adapter.IAdvisorAdapter"/> implementation
/// to enable <see cref="Spring.Aop.IThrowsAdvice"/> to be used in the
/// Spring.NET AOP framework.
/// Returns <see langword="true"/> if the supplied
/// <paramref name="advice"/> is an instance of the
/// <see cref="Spring.Aop.IThrowsAdvice"/> interface.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
internal class ThrowsAdviceAdapter : IAdvisorAdapter
/// <param name="advice">The advice to check.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> is
/// an instance of the <see cref="Spring.Aop.IThrowsAdvice"/> interface;
/// <see langword="false"/> if not or if the supplied
/// <paramref name="advice"/> is <cref lang="null"/>.
/// </returns>
public virtual bool SupportsAdvice(IAdvice advice)
{
/// <summary>
/// Returns <see langword="true"/> if the supplied
/// <paramref name="advice"/> is an instance of the
/// <see cref="Spring.Aop.IThrowsAdvice"/> interface.
/// </summary>
/// <param name="advice">The advice to check.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> is
/// an instance of the <see cref="Spring.Aop.IThrowsAdvice"/> interface;
/// <see langword="false"/> if not or if the supplied
/// <paramref name="advice"/> is <cref lang="null"/>.
/// </returns>
public virtual bool SupportsAdvice(IAdvice advice)
{
return advice is IThrowsAdvice;
}
return advice is IThrowsAdvice;
}
/// <summary>
/// Wraps the supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> within a
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/>
/// instance.
/// </summary>
/// <param name="advisor">
/// The advisor exposing the <see cref="AopAlliance.Aop.IAdvice"/> that
/// is to be wrapped.
/// </param>
/// <returns>
/// The supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> wrapped within a
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/>
/// instance.
/// </returns>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
return new ThrowsAdviceInterceptor(advisor.Advice);
}
/// <summary>
/// Wraps the supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> within a
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/>
/// instance.
/// </summary>
/// <param name="advisor">
/// The advisor exposing the <see cref="AopAlliance.Aop.IAdvice"/> that
/// is to be wrapped.
/// </param>
/// <returns>
/// The supplied <paramref name="advisor"/>'s
/// <see cref="Spring.Aop.IAdvisor.Advice"/> wrapped within a
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/>
/// instance.
/// </returns>
public virtual IInterceptor GetInterceptor(IAdvisor advisor)
{
return new ThrowsAdviceInterceptor(advisor.Advice);
}
}

View File

@@ -28,290 +28,292 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>Interceptor to wrap an after throwing advice.</summary>
/// <remarks>
/// <p>
/// Implementations of the <see cref="Spring.Aop.IThrowsAdvice"/> interface
/// <b>must</b> define methods of the form...
/// <code lang="C#">
/// AfterThrowing([MethodInfo method, Object[] args, Object target], Exception subclass);
/// </code>
/// The method name is fixed (i.e. your methods <b>must</b> be named
/// <c>AfterThrowing</c>. The first three arguments (<i>as a whole</i>) are
/// optional, and only useful if futher information about the joinpoint is
/// required. The return type <i>can</i> be anything, but is almost always
/// <see langword="void"/> by convention.
/// </p>
/// <p>
/// Please note that the object encapsulating the throws advice does not
/// need to implement the <see cref="Spring.Aop.IThrowsAdvice"/> interface.
/// Throws advice methods are discovered via reflection... the
/// <see cref="Spring.Aop.IThrowsAdvice"/> interface serves merely to
/// <i>discover</i> objects that are to be considered as throws advice.
/// Other mechanisms for discovering throws advice such as attributes are
/// also equally valid... all that this class cares about is that a throws
/// advice object implement one or more methods with a valid throws advice
/// signature (see above, and the examples below).
/// </p>
/// <p>
/// This is a framework class that should not normally need to be used
/// directly by Spring.NET users.
/// </p>
/// </remarks>
/// <example>
/// <p>
/// Find below some examples of valid <see cref="Spring.Aop.IThrowsAdvice"/>
/// method signatures...
/// </p>
/// <code language="C#">
/// public class GlobalExceptionHandlingAdvice : IThrowsAdvice
/// {
/// public void AfterThrowing(Exception ex) {
/// // handles absolutely any and every Exception...
/// }
/// }
/// </code>
/// <code language="C#">
/// public class RemotingExceptionHandlingAdvice : IThrowsAdvice
/// {
/// public void AfterThrowing(RemotingException ex) {
/// // handles any and every RemotingException (and subclasses of RemotingException)...
/// }
/// }
/// </code>
/// <code language="C#">
/// using System.Data;
///
/// public class DataExceptionHandlingAdvice
/// {
/// public void AfterThrowing(ConstraintException ex) {
/// // specialised handling of ConstraintExceptions
/// }
///
/// public void AfterThrowing(NoNullAllowedException ex) {
/// // specialised handling of NoNullAllowedExceptions
/// }
///
/// public void AfterThrowing(DataException ex) {
/// // handles all other DataExceptions...
/// }
/// }
/// </code>
/// </example>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
[Serializable]
public sealed class ThrowsAdviceInterceptor : IMethodInterceptor
{
/// <summary>Interceptor to wrap an after throwing advice.</summary>
private static readonly ILogger<ThrowsAdviceInterceptor> log = LogManager.GetLogger<ThrowsAdviceInterceptor>();
private const string SpecialThrowingMethodName = "AfterThrowing";
private readonly object throwsAdvice;
/// <summary>
/// The mapping of exception Types to MethodInfo handlers.
/// </summary>
private readonly IDictionary exceptionHandlers;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/> class.
/// </summary>
/// <remarks>
/// <p>
/// Implementations of the <see cref="Spring.Aop.IThrowsAdvice"/> interface
/// <b>must</b> define methods of the form...
/// <code lang="C#">
/// AfterThrowing([MethodInfo method, Object[] args, Object target], Exception subclass);
/// </code>
/// The method name is fixed (i.e. your methods <b>must</b> be named
/// <c>AfterThrowing</c>. The first three arguments (<i>as a whole</i>) are
/// optional, and only useful if futher information about the joinpoint is
/// required. The return type <i>can</i> be anything, but is almost always
/// <see langword="void"/> by convention.
/// </p>
/// <p>
/// Please note that the object encapsulating the throws advice does not
/// need to implement the <see cref="Spring.Aop.IThrowsAdvice"/> interface.
/// Throws advice methods are discovered via reflection... the
/// <see cref="Spring.Aop.IThrowsAdvice"/> interface serves merely to
/// <i>discover</i> objects that are to be considered as throws advice.
/// Other mechanisms for discovering throws advice such as attributes are
/// also equally valid... all that this class cares about is that a throws
/// advice object implement one or more methods with a valid throws advice
/// signature (see above, and the examples below).
/// </p>
/// <p>
/// This is a framework class that should not normally need to be used
/// directly by Spring.NET users.
/// </p>
/// </remarks>
/// <example>
/// <p>
/// Find below some examples of valid <see cref="Spring.Aop.IThrowsAdvice"/>
/// method signatures...
/// </p>
/// <code language="C#">
/// public class GlobalExceptionHandlingAdvice : IThrowsAdvice
/// {
/// public void AfterThrowing(Exception ex) {
/// // handles absolutely any and every Exception...
/// }
/// }
/// </code>
/// <code language="C#">
/// public class RemotingExceptionHandlingAdvice : IThrowsAdvice
/// {
/// public void AfterThrowing(RemotingException ex) {
/// // handles any and every RemotingException (and subclasses of RemotingException)...
/// }
/// }
/// </code>
/// <code language="C#">
/// using System.Data;
///
/// public class DataExceptionHandlingAdvice
/// {
/// public void AfterThrowing(ConstraintException ex) {
/// // specialised handling of ConstraintExceptions
/// }
///
/// public void AfterThrowing(NoNullAllowedException ex) {
/// // specialised handling of NoNullAllowedExceptions
/// }
///
/// public void AfterThrowing(DataException ex) {
/// // handles all other DataExceptions...
/// }
/// }
/// </code>
/// </example>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
[Serializable]
public sealed class ThrowsAdviceInterceptor : IMethodInterceptor
/// <param name="advice">
/// The throws advice to check for exception handler methods.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="advice"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="System.ArgumentException">
/// If no (0) handler methods were discovered on the supplied <paramref name="advice"/>;
/// or if more than one handler method suitable for a particular
/// <see cref="System.Exception"/> type was discovered on the supplied
/// <paramref name="advice"/>.
/// </exception>
public ThrowsAdviceInterceptor(object advice)
{
private static readonly ILogger<ThrowsAdviceInterceptor> log = LogManager.GetLogger<ThrowsAdviceInterceptor>();
private const string SpecialThrowingMethodName = "AfterThrowing";
private readonly object throwsAdvice;
/// <summary>
/// The mapping of exception Types to MethodInfo handlers.
/// </summary>
private readonly IDictionary exceptionHandlers;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/> class.
/// </summary>
/// <remarks>
/// </remarks>
/// <param name="advice">
/// The throws advice to check for exception handler methods.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="advice"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="System.ArgumentException">
/// If no (0) handler methods were discovered on the supplied <paramref name="advice"/>;
/// or if more than one handler method suitable for a particular
/// <see cref="System.Exception"/> type was discovered on the supplied
/// <paramref name="advice"/>.
/// </exception>
public ThrowsAdviceInterceptor(object advice)
AssertUtils.ArgumentNotNull(advice, "advice");
this.exceptionHandlers = new Hashtable();
this.throwsAdvice = advice;
MapAllExceptionHandlingMethods(advice);
if (exceptionHandlers.Count == 0)
{
AssertUtils.ArgumentNotNull(advice, "advice");
this.exceptionHandlers = new Hashtable();
this.throwsAdvice = advice;
MapAllExceptionHandlingMethods(advice);
if (exceptionHandlers.Count == 0)
{
throw new ArgumentException(
"At least one handler method must be found in class ["
+ advice.GetType().FullName + "].");
}
throw new ArgumentException(
"At least one handler method must be found in class ["
+ advice.GetType().FullName + "].");
}
}
private void MapAllExceptionHandlingMethods(object advice)
private void MapAllExceptionHandlingMethods(object advice)
{
MethodInfo[] methods = advice.GetType().GetMethods();
foreach (MethodInfo method in methods)
{
MethodInfo[] methods = advice.GetType().GetMethods();
foreach (MethodInfo method in methods)
int numParams = method.GetParameters().Length;
if (method.Name.Equals(SpecialThrowingMethodName)
&& (numParams == 1 || numParams == 4))
{
int numParams = method.GetParameters().Length;
if (method.Name.Equals(SpecialThrowingMethodName)
&& (numParams == 1 || numParams == 4))
Type lastParametersType = method.GetParameters()[numParams - 1].ParameterType;
if (typeof(Exception).IsAssignableFrom(lastParametersType))
{
Type lastParametersType = method.GetParameters()[numParams - 1].ParameterType;
if (typeof (Exception).IsAssignableFrom(lastParametersType))
#region Instrumentation
if (log.IsEnabled(LogLevel.Debug))
{
#region Instrumentation
if(log.IsEnabled(LogLevel.Debug))
{
log.LogDebug("Found exception handler method: " + method);
}
#endregion
if(this.exceptionHandlers.Contains(lastParametersType))
{
throw new ArgumentException(
"Throws advice handler method for the [" +
lastParametersType + "] type already exists; don't define " +
"both single and multiple argument methods for the same " +
"Exception type in the same class.");
}
this.exceptionHandlers[lastParametersType] = method;
log.LogDebug("Found exception handler method: " + method);
}
#endregion
if (this.exceptionHandlers.Contains(lastParametersType))
{
throw new ArgumentException(
"Throws advice handler method for the [" +
lastParametersType + "] type already exists; don't define " +
"both single and multiple argument methods for the same " +
"Exception type in the same class.");
}
this.exceptionHandlers[lastParametersType] = method;
}
}
}
}
/// <summary>
/// Convenience property that returns the number of exception handler
/// methods managed by this interceptor.
/// </summary>
/// <value>
/// The number of exception handler methods managed by this interceptor.
/// </value>
public int HandlerMethodCount
/// <summary>
/// Convenience property that returns the number of exception handler
/// methods managed by this interceptor.
/// </summary>
/// <value>
/// The number of exception handler methods managed by this interceptor.
/// </value>
public int HandlerMethodCount
{
get { return exceptionHandlers.Count; }
}
/// <summary>
/// Executes interceptor if (and only if) the supplied
/// <paramref name="invocation"/> throws an exception that is mapped to
/// an appropriate exception handler.
/// </summary>
/// <param name="invocation">
/// The method invocation that is being intercepted.
/// </param>
/// <returns>
/// The result of the call to the
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/> method of
/// the supplied <paramref name="invocation"/> (this assumes no
/// exception was thrown by the call to the supplied <paramref name="invocation"/>.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors in the chain or the target object itself
/// throws an exception.
/// </exception>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor.Invoke"/>
public object Invoke(IMethodInvocation invocation)
{
try
{
get { return exceptionHandlers.Count; }
return invocation.Proceed();
}
catch (TargetInvocationException ex)
{
// bah, this is a tad gross...
Exception realException = ex.InnerException;
LookupAndInvokeAnyHandler(realException, invocation);
throw realException;
}
catch (Exception ex)
{
LookupAndInvokeAnyHandler(ex, invocation);
throw;
}
}
private void LookupAndInvokeAnyHandler(Exception ex, IMethodInvocation invocation)
{
MethodInfo handlerMethod = GetExceptionHandler(ex);
if (handlerMethod != null)
{
InvokeHandlerMethod(invocation, ex, handlerMethod);
}
}
/// <summary>
/// Gets the exception handler (if any) that has been mapped to the
/// supplied <paramref name="exception"/>.
/// </summary>
/// <remarks>
/// <p>
/// Will return <cref lang="null"/> if not found.
/// </p>
/// </remarks>
/// <returns>
/// The exception handler for the <see cref="System.Type"/> of the
/// supplied <paramref name="exception"/> given exception.
/// </returns>
/// <param name="exception">exception that was thrown</param>
private MethodInfo GetExceptionHandler(Exception exception)
{
Type exceptionClass = exception.GetType();
#region Instrumentation
if (log.IsEnabled(LogLevel.Debug))
{
log.LogDebug("Trying to find handler for exception of type [" + exception.GetType().Name + "].");
}
/// <summary>
/// Executes interceptor if (and only if) the supplied
/// <paramref name="invocation"/> throws an exception that is mapped to
/// an appropriate exception handler.
/// </summary>
/// <param name="invocation">
/// The method invocation that is being intercepted.
/// </param>
/// <returns>
/// The result of the call to the
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/> method of
/// the supplied <paramref name="invocation"/> (this assumes no
/// exception was thrown by the call to the supplied <paramref name="invocation"/>.
/// </returns>
/// <exception cref="System.Exception">
/// If any of the interceptors in the chain or the target object itself
/// throws an exception.
/// </exception>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor.Invoke"/>
public object Invoke(IMethodInvocation invocation)
#endregion
MethodInfo handler = (MethodInfo) this.exceptionHandlers[exceptionClass];
while (handler == null && !exceptionClass.Equals(typeof(Exception)))
{
try
{
return invocation.Proceed();
}
catch (TargetInvocationException ex)
{
// bah, this is a tad gross...
Exception realException = ex.InnerException;
LookupAndInvokeAnyHandler(realException, invocation);
throw realException;
}
catch (Exception ex)
{
LookupAndInvokeAnyHandler(ex, invocation);
throw;
}
exceptionClass = exceptionClass.BaseType;
handler = (MethodInfo) this.exceptionHandlers[exceptionClass];
}
private void LookupAndInvokeAnyHandler(Exception ex, IMethodInvocation invocation)
return handler;
}
/// <summary>
/// Invokes handler method with appropriate number of parameters
/// </summary>
/// <param name="invocation">
/// The original method invocation that was intercepted.
/// </param>
/// <param name="triggeringException">
/// The exception that triggered this interceptor.
/// </param>
/// <param name="handlerMethod">
/// The exception handler method to invoke.
/// </param>
private void InvokeHandlerMethod(
IMethodInvocation invocation, Exception triggeringException, MethodInfo handlerMethod)
{
object[] handlerArgs;
if (handlerMethod.GetParameters().Length == 1)
{
MethodInfo handlerMethod = GetExceptionHandler(ex);
if (handlerMethod != null)
{
InvokeHandlerMethod(invocation, ex, handlerMethod);
}
handlerArgs = new object[] { triggeringException };
}
else
{
handlerArgs = new object[] { invocation.Method, invocation.Arguments, invocation.This, triggeringException };
}
/// <summary>
/// Gets the exception handler (if any) that has been mapped to the
/// supplied <paramref name="exception"/>.
/// </summary>
/// <remarks>
/// <p>
/// Will return <cref lang="null"/> if not found.
/// </p>
/// </remarks>
/// <returns>
/// The exception handler for the <see cref="System.Type"/> of the
/// supplied <paramref name="exception"/> given exception.
/// </returns>
/// <param name="exception">exception that was thrown</param>
private MethodInfo GetExceptionHandler(Exception exception)
try
{
Type exceptionClass = exception.GetType();
#region Instrumentation
if(log.IsEnabled(LogLevel.Debug))
{
log.LogDebug("Trying to find handler for exception of type [" + exception.GetType().Name + "].");
}
#endregion
MethodInfo handler = (MethodInfo) this.exceptionHandlers[exceptionClass];
while (handler == null && !exceptionClass.Equals(typeof(Exception)))
{
exceptionClass = exceptionClass.BaseType;
handler = (MethodInfo) this.exceptionHandlers[exceptionClass];
}
return handler;
handlerMethod.Invoke(this.throwsAdvice, handlerArgs);
}
/// <summary>
/// Invokes handler method with appropriate number of parameters
/// </summary>
/// <param name="invocation">
/// The original method invocation that was intercepted.
/// </param>
/// <param name="triggeringException">
/// The exception that triggered this interceptor.
/// </param>
/// <param name="handlerMethod">
/// The exception handler method to invoke.
/// </param>
private void InvokeHandlerMethod(
IMethodInvocation invocation, Exception triggeringException, MethodInfo handlerMethod)
catch (TargetInvocationException ex)
{
object[] handlerArgs;
if (handlerMethod.GetParameters().Length == 1)
{
handlerArgs = new object[] {triggeringException};
}
else
{
handlerArgs = new object[] {invocation.Method, invocation.Arguments, invocation.This, triggeringException};
}
try
{
handlerMethod.Invoke(this.throwsAdvice, handlerArgs);
}
catch (TargetInvocationException ex)
{
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
}
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
}
}
}

View File

@@ -24,69 +24,68 @@ using System.Runtime.Serialization;
#endregion
namespace Spring.Aop.Framework.Adapter
namespace Spring.Aop.Framework.Adapter;
/// <summary>
/// Exception thrown when an attempt is made to use an unsupported
/// <see cref="Spring.Aop.IAdvisor"/> or <see cref="AopAlliance.Aop.IAdvice"/>
/// type.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class UnknownAdviceTypeException : ArgumentException
{
/// <summary>
/// Exception thrown when an attempt is made to use an unsupported
/// <see cref="Spring.Aop.IAdvisor"/> or <see cref="AopAlliance.Aop.IAdvice"/>
/// type.
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class UnknownAdviceTypeException : ArgumentException
public UnknownAdviceTypeException()
{
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class.
/// </summary>
public UnknownAdviceTypeException()
{
}
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class.
/// </summary>
/// <param name="advice">The advice that caused the exception.</param>
public UnknownAdviceTypeException(object advice)
: base("No adapter for IAdvice of type ["
+ (advice != null ? advice.GetType().FullName : "null") + "].")
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class.
/// </summary>
/// <param name="advice">The advice that caused the exception.</param>
public UnknownAdviceTypeException(object advice)
: base("No adapter for IAdvice of type ["
+ (advice != null ? advice.GetType().FullName : "null") + "].")
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class with
/// the specified message.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
public UnknownAdviceTypeException(string message) : base(message)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class with
/// the specified message.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
public UnknownAdviceTypeException(string message) : base(message)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class with
/// the specified message and root cause.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
/// <param name="rootCause">
/// The root exception that is being wrapped.
/// </param>
public UnknownAdviceTypeException(string message, Exception rootCause)
: base(message, rootCause)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.Adapter.UnknownAdviceTypeException"/> class with
/// the specified message and root cause.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
/// <param name="rootCause">
/// The root exception that is being wrapped.
/// </param>
public UnknownAdviceTypeException(string message, Exception rootCause)
: base(message, rootCause)
{
}
/// <inheritdoc />
protected UnknownAdviceTypeException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <inheritdoc />
protected UnknownAdviceTypeException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,101 +21,99 @@
#region Imports
using System.Reflection;
using AopAlliance.Intercept;
using Spring.Aop.Framework.Adapter;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Utility methods for use by
/// <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/> implementations.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AdvisorChainFactoryUtils
{
/// <summary>
/// Utility methods for use by
/// <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/> implementations.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AdvisorChainFactoryUtils
{
/// <summary>
/// Gets the list of
/// <see langword="static"/> interceptors and dynamic interception
/// advice that may apply to the supplied <paramref name="method"/>
/// invocation.
/// </summary>
/// <param name="config">The proxy configuration.</param>
/// <param name="proxy">The object proxy.</param>
/// <param name="method">
/// The method to evaluate interceptors for.
/// </param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.
/// </param>
/// <returns>
/// A <see cref="System.Collections.IList"/> of
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> (if there's
/// a dynamic method matcher that needs evaluation at runtime).
/// </returns>
public static IList<object> CalculateInterceptors(
IAdvised config, object proxy, MethodInfo method, Type targetType)
{
IList<object> interceptors = new List<object>(config.Advisors.Count);
foreach (IAdvisor advisor in config.Advisors)
{
if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pointcutAdvisor = (IPointcutAdvisor) advisor;
if (pointcutAdvisor.Pointcut.TypeFilter.Matches(targetType))
{
IMethodInterceptor interceptor =
(IMethodInterceptor) GlobalAdvisorAdapterRegistry.Instance.GetInterceptor(advisor);
IMethodMatcher mm = pointcutAdvisor.Pointcut.MethodMatcher;
if (mm.Matches(method, targetType))
{
if (mm.IsRuntime)
{
// Creating a new object instance in the GetInterceptor() method
// isn't a problem as we normally cache created chains...
interceptors.Add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
else
{
interceptors.Add(interceptor);
}
}
}
}
}
return interceptors;
}
/// <summary>
/// Gets the list of
/// <see langword="static"/> interceptors and dynamic interception
/// advice that may apply to the supplied <paramref name="method"/>
/// invocation.
/// </summary>
/// <param name="config">The proxy configuration.</param>
/// <param name="proxy">The object proxy.</param>
/// <param name="method">
/// The method to evaluate interceptors for.
/// </param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.
/// </param>
/// <returns>
/// A <see cref="System.Collections.IList"/> of
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> (if there's
/// a dynamic method matcher that needs evaluation at runtime).
/// </returns>
public static IList<object> CalculateInterceptors(
IAdvised config, object proxy, MethodInfo method, Type targetType)
{
IList<object> interceptors = new List<object>(config.Advisors.Count);
foreach (IAdvisor advisor in config.Advisors)
{
if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pointcutAdvisor = (IPointcutAdvisor) advisor;
if (pointcutAdvisor.Pointcut.TypeFilter.Matches(targetType))
{
IMethodInterceptor interceptor =
(IMethodInterceptor) GlobalAdvisorAdapterRegistry.Instance.GetInterceptor(advisor);
IMethodMatcher mm = pointcutAdvisor.Pointcut.MethodMatcher;
if (mm.Matches(method, targetType))
{
if (mm.IsRuntime)
{
// Creating a new object instance in the GetInterceptor() method
// isn't a problem as we normally cache created chains...
interceptors.Add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
else
{
interceptors.Add(interceptor);
}
}
}
}
}
#region Constructor (s) / Destructor
return interceptors;
}
// CLOVER:OFF
#region Constructor (s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AdvisorChainFactoryUtils"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly visible
/// constructors.
/// </p>
/// </remarks>
private AdvisorChainFactoryUtils()
{
}
// CLOVER:OFF
// CLOVER:ON
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AdvisorChainFactoryUtils"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly visible
/// constructors.
/// </p>
/// </remarks>
private AdvisorChainFactoryUtils()
{
}
#endregion
}
// CLOVER:ON
#endregion
}

View File

@@ -24,57 +24,56 @@ using System.Runtime.Serialization;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Thrown in response to the misconfiguration of an AOP proxy.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class AopConfigException : ApplicationException
{
/// <summary>
/// Thrown in response to the misconfiguration of an AOP proxy.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class AopConfigException : ApplicationException
{
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopConfigException"/> class.
/// </summary>
public AopConfigException ()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopConfigException"/> class.
/// </summary>
public AopConfigException()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopConfigException"/> class with
/// the specified message.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
public AopConfigException (string message) : base(message)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopConfigException"/> class with
/// the specified message.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
public AopConfigException(string message) : base(message)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopConfigException"/> class with
/// the specified message and root cause.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
/// <param name="rootCause">
/// The root exception that is being wrapped.
/// </param>
public AopConfigException (string message, Exception rootCause)
: base(message, rootCause)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopConfigException"/> class with
/// the specified message and root cause.
/// </summary>
/// <param name="message">
/// A message about the exception.
/// </param>
/// <param name="rootCause">
/// The root exception that is being wrapped.
/// </param>
public AopConfigException(string message, Exception rootCause)
: base(message, rootCause)
{
}
/// <inheritdoc />
protected AopConfigException (
SerializationInfo info, StreamingContext context)
: base (info, context)
{
}
}
/// <inheritdoc />
protected AopConfigException(
SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}

View File

@@ -24,165 +24,166 @@ using System.Collections;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// This class contains various <see langword="static"/> methods used to
/// obtain information about the current AOP invocation.
/// </summary>
/// <remarks>
/// <p>
/// The <see langword="static"/>
/// <see cref="Spring.Aop.Framework.AopContext.CurrentProxy"/> property is
/// usable if the AOP framework is configured to expose the current proxy
/// (not the default)... it returns the AOP proxy in use. Target objects or
/// advice can use this to make advised calls. They can also use it to find
/// advice configuration.
/// </p>
/// <p>
/// To expose the current proxy, set the <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/>
/// property on the controlling proxy to <see langword="true"/>.
/// The default value for the <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// is <see langword="false"/>, for performance reasons.
/// </p>
/// <note>
/// The AOP framework does not expose proxies by default, as there is a
/// performance cost in doing so.
/// </note>
/// <p>
/// The functionality in this class might be used by a target object that
/// needed access to resources on the invocation. However, this approach
/// should not be used when there is a reasonable alternative, as it makes
/// application code dependent on usage under AOP and the Spring.NET AOP
/// framework.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopContext
{
/// <summary>
/// This class contains various <see langword="static"/> methods used to
/// obtain information about the current AOP invocation.
/// </summary>
/// <remarks>
/// <p>
/// The <see langword="static"/>
/// <see cref="Spring.Aop.Framework.AopContext.CurrentProxy"/> property is
/// usable if the AOP framework is configured to expose the current proxy
/// (not the default)... it returns the AOP proxy in use. Target objects or
/// advice can use this to make advised calls. They can also use it to find
/// advice configuration.
/// </p>
[ThreadStatic] private static Stack tls_ProxyStack;
/// <summary>
/// The AOP proxy stack associated with this thread.
/// </summary>
private static Stack ProxyStack
{
get
{
if (tls_ProxyStack == null)
{
tls_ProxyStack = new Stack();
}
return tls_ProxyStack;
}
}
/// <summary>
/// Indicates if the current call is executed under control of an AOP proxy.
/// </summary>
/// <remarks>
/// <p>
/// To expose the current proxy, set the <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/>
/// property on the controlling proxy to <see langword="true"/>.
/// The default value for the <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// Will be <cref lang="null"/> unless the
/// <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// on the controlling proxy has been set to <see langword="true"/>.
/// </p>
/// <p>
/// The default value for the
/// <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// is <see langword="false"/>, for performance reasons.
/// </p>
/// <note>
/// The AOP framework does not expose proxies by default, as there is a
/// performance cost in doing so.
/// </note>
/// <p>
/// The functionality in this class might be used by a target object that
/// needed access to resources on the invocation. However, this approach
/// should not be used when there is a reasonable alternative, as it makes
/// application code dependent on usage under AOP and the Spring.NET AOP
/// framework.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopContext
{
[ThreadStatic]
private static Stack tls_ProxyStack;
/// <summary>
/// The AOP proxy stack associated with this thread.
/// </summary>
private static Stack ProxyStack
/// </remarks>
public static bool IsActive
{
get
{
get
return (tls_ProxyStack != null && tls_ProxyStack.Count > 0);
}
}
/// <summary>
/// Gets the current AOP proxy.
/// </summary>
/// <exception cref="AopConfigException">
/// If the proxy stack is empty.
/// </exception>
public static object CurrentProxy
{
get
{
Stack proxyStack = ProxyStack;
if (proxyStack.Count == 0)
{
if (tls_ProxyStack == null)
{
tls_ProxyStack = new Stack();
}
return tls_ProxyStack;
throw new AopConfigException(
"Cannot find proxy: Set the 'ExposeProxy' property " +
"to 'true' on IAdvised to make it available.");
}
return proxyStack.Peek();
}
}
/// <summary>
/// Sets the current proxy by pushing it to the proxy stack.
/// </summary>
/// <remarks>
/// <p>
/// This method is for internal use only, and should never be called by
/// client code.
/// </p>
/// </remarks>
/// <param name="proxy">
/// The proxy to put on top of the proxy stack.
/// </param>
public static void PushProxy(object proxy)
{
ProxyStack.Push(proxy);
}
/// <summary>
/// Removes the current proxy from the proxy stack, making the previous
/// proxy (if any) the current proxy.
/// </summary>
/// <remarks>
/// <p>
/// This method is for internal use only, and should never be called by
/// client code.
/// </p>
/// </remarks>
/// <exception cref="AopConfigException">
/// If the proxy stack is empty.
/// </exception>
public static void PopProxy()
{
Stack proxyStack = ProxyStack;
if (proxyStack.Count == 0)
{
throw new AopConfigException(
"Proxy stack empty. Always call 'PushProxy' before 'PopProxy'.");
}
/// <summary>
/// Indicates if the current call is executed under control of an AOP proxy.
/// </summary>
/// <remarks>
/// <p>
/// Will be <cref lang="null"/> unless the
/// <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// on the controlling proxy has been set to <see langword="true"/>.
/// </p>
/// <p>
/// The default value for the
/// <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// is <see langword="false"/>, for performance reasons.
/// </p>
/// </remarks>
public static bool IsActive
{
get
{
return (tls_ProxyStack != null && tls_ProxyStack.Count > 0);
}
}
proxyStack.Pop();
}
/// <summary>
/// Gets the current AOP proxy.
/// </summary>
/// <exception cref="AopConfigException">
/// If the proxy stack is empty.
/// </exception>
public static object CurrentProxy
{
get
{
Stack proxyStack = ProxyStack;
if (proxyStack.Count == 0)
{
throw new AopConfigException(
"Cannot find proxy: Set the 'ExposeProxy' property " +
"to 'true' on IAdvised to make it available.");
}
return proxyStack.Peek();
}
}
#region Constructor (s) / Destructor
/// <summary>
/// Sets the current proxy by pushing it to the proxy stack.
/// </summary>
/// <remarks>
/// <p>
/// This method is for internal use only, and should never be called by
/// client code.
/// </p>
/// </remarks>
/// <param name="proxy">
/// The proxy to put on top of the proxy stack.
/// </param>
public static void PushProxy(object proxy)
{
ProxyStack.Push(proxy);
}
// CLOVER:OFF
/// <summary>
/// Removes the current proxy from the proxy stack, making the previous
/// proxy (if any) the current proxy.
/// </summary>
/// <remarks>
/// <p>
/// This method is for internal use only, and should never be called by
/// client code.
/// </p>
/// </remarks>
/// <exception cref="AopConfigException">
/// If the proxy stack is empty.
/// </exception>
public static void PopProxy()
{
Stack proxyStack = ProxyStack;
if (proxyStack.Count == 0)
{
throw new AopConfigException(
"Proxy stack empty. Always call 'PushProxy' before 'PopProxy'.");
}
proxyStack.Pop();
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopContext"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such exposes no public constructors.
/// </p>
/// </remarks>
private AopContext()
{
}
#region Constructor (s) / Destructor
// CLOVER:ON
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.AopContext"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such exposes no public constructors.
/// </p>
/// </remarks>
private AopContext()
{
}
// CLOVER:ON
#endregion
}
#endregion
}

View File

@@ -21,389 +21,395 @@
#region Imports
using System.Reflection;
using Spring.Collections;
using Spring.Util;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Utility methods used by the AOP framework.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopUtils
{
// This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations.
private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy";
private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy";
private const string INHERITANCE_PROXY_TYPE_NAME = "InheritanceAopProxy";
/// <summary>
/// Utility methods used by the AOP framework.
/// Is the supplied <paramref name="objectType"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given type is either a composition-based or a decorator-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is an AOP proxy type.</returns>
public static bool IsAopProxyType(Type objectType)
{
return IsCompositionAopProxyType(objectType) || IsDecoratorAopProxyType(objectType) || IsInheritanceAopProxyType(objectType);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given object is either
/// a composition-based proxy or a decorator-based proxy.
/// </remarks>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an AOP proxy.
/// </returns>
public static bool IsAopProxy(object instance)
{
return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance) || IsInheritanceAopProxy(instance);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a composition-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an composition-based AOP proxy.
/// </returns>
public static bool IsCompositionAopProxy(Object instance)
{
return ((instance != null) && IsCompositionAopProxyType(instance.GetType()));
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> a composition based AOP proxy type?
/// </summary>
/// <remarks>
/// Return whether the given type is a composition-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is a composition based AOP proxy type.</returns>
public static bool IsCompositionAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a decorator-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an decorator-based AOP proxy.
/// </returns>
public static bool IsDecoratorAopProxy(Object instance)
{
return ((instance != null) && IsDecoratorAopProxyType(instance.GetType()));
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> a composition based AOP proxy type?
/// </summary>
/// <remarks>
/// Return whether the given type is a composition-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is a composition based AOP proxy type.</returns>
public static bool IsDecoratorAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> an inheritance based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an inheritacne based AOP proxy.
/// </returns>
public static bool IsInheritanceAopProxy(Object instance)
{
return instance != null && IsInheritanceAopProxyType(instance.GetType());
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> an inheritance based AOP proxy type?
/// </summary>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is an inheritance based AOP proxy type.</returns>
public static bool IsInheritanceAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(INHERITANCE_PROXY_TYPE_NAME));
}
/// <summary>
/// Gets all of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements.
/// </summary>
/// <remarks>
/// <p>
/// Not intended to be used directly by applications.
/// This includes interfaces implemented by any superclasses.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Aleksandar Seovic (.NET)</author>
public sealed class AopUtils
/// <param name="instance">
/// The object to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements; or an empty
/// array if the supplied <paramref name="instance"/> is
/// <see langword="null"/>.
/// </returns>
public static Type[] GetAllInterfaces(object instance)
{
// This is a leaky abstraction as we have hardcoded known IAopProxyFactory implementations.
private const string COMPOSITION_PROXY_TYPE_NAME = "CompositionAopProxy";
private const string DECORATOR_PROXY_TYPE_NAME = "DecoratorAopProxy";
private const string INHERITANCE_PROXY_TYPE_NAME = "InheritanceAopProxy";
/// <summary>
/// Is the supplied <paramref name="objectType"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given type is either a composition-based or a decorator-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is an AOP proxy type.</returns>
public static bool IsAopProxyType(Type objectType)
if (instance != null)
{
return IsCompositionAopProxyType(objectType) || IsDecoratorAopProxyType(objectType) || IsInheritanceAopProxyType(objectType);
Type type = instance.GetType();
return GetAllInterfacesFromType(type);
}
/// <summary>
/// Is the supplied <paramref name="instance"/> an AOP proxy?
/// </summary>
/// <remarks>
/// Return whether the given object is either
/// a composition-based proxy or a decorator-based proxy.
/// </remarks>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an AOP proxy.
/// </returns>
public static bool IsAopProxy(object instance)
{
return IsCompositionAopProxy(instance) || IsDecoratorAopProxy(instance) || IsInheritanceAopProxy(instance);
}
return Type.EmptyTypes;
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a composition-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an composition-based AOP proxy.
/// </returns>
public static bool IsCompositionAopProxy(Object instance)
/// <summary>
/// Gets all of the interfaces that the
/// supplied <see cref="System.Type"/> implements.
/// </summary>
/// <remarks>
/// This includes interfaces implemented by any superclasses.
/// </remarks>
/// <param name="type">
/// The type to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the supplied <see cref="System.Type"/> implements.
/// </returns>
public static Type[] GetAllInterfacesFromType(Type type)
{
AssertUtils.ArgumentNotNull(type, "type");
ISet interfaces = new HybridSet();
do
{
return ((instance != null) && IsCompositionAopProxyType(instance.GetType()));
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> a composition based AOP proxy type?
/// </summary>
/// <remarks>
/// Return whether the given type is a composition-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is a composition based AOP proxy type.</returns>
public static bool IsCompositionAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(COMPOSITION_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> a decorator-based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an decorator-based AOP proxy.
/// </returns>
public static bool IsDecoratorAopProxy(Object instance)
{
return ((instance != null) && IsDecoratorAopProxyType(instance.GetType()));
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> a composition based AOP proxy type?
/// </summary>
/// <remarks>
/// Return whether the given type is a composition-based proxy type.
/// </remarks>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is a composition based AOP proxy type.</returns>
public static bool IsDecoratorAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(DECORATOR_PROXY_TYPE_NAME));
}
/// <summary>
/// Is the supplied <paramref name="instance"/> an inheritance based AOP proxy?
/// </summary>
/// <param name="instance">The instance to be checked.</param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="instance"/> is
/// an inheritacne based AOP proxy.
/// </returns>
public static bool IsInheritanceAopProxy(Object instance)
{
return instance != null && IsInheritanceAopProxyType(instance.GetType());
}
/// <summary>
/// Is the supplied <paramref name="objectType"/> an inheritance based AOP proxy type?
/// </summary>
/// <param name="objectType">The type to be checked.</param>
/// <returns><see langword="true"/> if the supplied <paramref name="objectType"/> is an inheritance based AOP proxy type.</returns>
public static bool IsInheritanceAopProxyType(Type objectType)
{
return ((objectType != null) && objectType.FullName.StartsWith(INHERITANCE_PROXY_TYPE_NAME));
}
/// <summary>
/// Gets all of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements.
/// </summary>
/// <remarks>
/// <p>
/// This includes interfaces implemented by any superclasses.
/// </p>
/// </remarks>
/// <param name="instance">
/// The object to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the <see cref="System.Type"/> of the
/// supplied <paramref name="instance"/> implements; or an empty
/// array if the supplied <paramref name="instance"/> is
/// <see langword="null"/>.
/// </returns>
public static Type[] GetAllInterfaces(object instance)
{
if (instance != null)
Type[] ifcs = type.GetInterfaces();
foreach (Type ifc in ifcs)
{
Type type = instance.GetType();
return GetAllInterfacesFromType(type);
}
return Type.EmptyTypes;
}
/// <summary>
/// Gets all of the interfaces that the
/// supplied <see cref="System.Type"/> implements.
/// </summary>
/// <remarks>
/// This includes interfaces implemented by any superclasses.
/// </remarks>
/// <param name="type">
/// The type to analyse for interfaces.
/// </param>
/// <returns>
/// All of the interfaces that the supplied <see cref="System.Type"/> implements.
/// </returns>
public static Type[] GetAllInterfacesFromType(Type type)
{
AssertUtils.ArgumentNotNull(type, "type");
ISet interfaces = new HybridSet();
do
{
Type[] ifcs = type.GetInterfaces();
foreach (Type ifc in ifcs)
{
interfaces.Add(ifc);
}
type = type.BaseType;
} while (type != null);
if (interfaces.Count > 0)
{
Type[] types = new Type[interfaces.Count];
interfaces.CopyTo(types, 0);
return types;
}
return Type.EmptyTypes;
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
{
return CanApply(pointcut, targetType, proxyInterfaces, false);
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (!pointcut.TypeFilter.Matches(targetType))
{
return false;
interfaces.Add(ifc);
}
// It may apply to the class
// Check whether it can apply on any method
// Checks public methods, including inherited methods
MethodInfo[] methods = targetType.GetMethods();
for (int i = 0; i < methods.Length; ++i)
{
MethodInfo m = methods[i];
// If we're looking only at interfaces and this method
// isn't on any of them, skip it
if (proxyInterfaces != null
&& !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces))
{
continue;
}
if (pointcut.MethodMatcher.Matches(m, targetType))
{
return true;
}
}
type = type.BaseType;
} while (type != null);
if (interfaces.Count > 0)
{
Type[] types = new Type[interfaces.Count];
interfaces.CopyTo(types, 0);
return types;
}
return Type.EmptyTypes;
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces)
{
return CanApply(pointcut, targetType, proxyInterfaces, false);
}
/// <summary>
/// Can the supplied <paramref name="pointcut"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out a
/// pointcut for a class.
/// </p>
/// <p>
/// Invoking this method with a <paramref name="targetType"/> that is
/// an interface type will always yield a <see langword="false"/>
/// return value.
/// </p>
/// </remarks>
/// <param name="pointcut">The pointcut being tested.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the pointcut can apply on any method.
/// </returns>
public static bool CanApply(IPointcut pointcut, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (!pointcut.TypeFilter.Matches(targetType))
{
return false;
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
// It may apply to the class
// Check whether it can apply on any method
// Checks public methods, including inherited methods
MethodInfo[] methods = targetType.GetMethods();
for (int i = 0; i < methods.Length; ++i)
{
return CanApply(advisor, targetType, proxyInterfaces, false);
MethodInfo m = methods[i];
// If we're looking only at interfaces and this method
// isn't on any of them, skip it
if (proxyInterfaces != null
&& !ReflectionUtils.MethodIsOnOneOfTheseInterfaces(m, proxyInterfaces))
{
continue;
}
if (pointcut.MethodMatcher.Matches(m, targetType))
{
return true;
}
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
return false;
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces)
{
return CanApply(advisor, targetType, proxyInterfaces, false);
}
/// <summary>
/// Can the supplied <paramref name="advisor"/> apply at all on the
/// supplied <paramref name="targetType"/>?
/// </summary>
/// <remarks>
/// <p>
/// This is an important test as it can be used to optimize out an
/// advisor for a class.
/// </p>
/// </remarks>
/// <param name="advisor">The advisor to check.</param>
/// <param name="targetType">The class being tested.</param>
/// <param name="proxyInterfaces">
/// The interfaces being proxied. If <see langword="null"/>, all
/// methods on a class may be proxied.
/// </param>
/// <param name="hasIntroductions">whether or not the advisor chain for the target object includes any introductions.</param>
/// <returns>
/// <see langword="true"/> if the advisor can apply on any method.
/// </returns>
public static bool CanApply(IAdvisor advisor, Type targetType, Type[] proxyInterfaces, bool hasIntroductions)
{
if (advisor is IIntroductionAdvisor)
{
if (advisor is IIntroductionAdvisor)
{
return ((IIntroductionAdvisor)advisor).TypeFilter.Matches(targetType);
}
else if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pca = (IPointcutAdvisor)advisor;
return CanApply(pca.Pointcut, targetType, proxyInterfaces, hasIntroductions);
}
// no pointcut specified so assume it applies...
return true;
return ((IIntroductionAdvisor) advisor).TypeFilter.Matches(targetType);
}
else if (advisor is IPointcutAdvisor)
{
IPointcutAdvisor pca = (IPointcutAdvisor) advisor;
return CanApply(pca.Pointcut, targetType, proxyInterfaces, hasIntroductions);
}
#region Constructor (s) / Destructor
// no pointcut specified so assume it applies...
return true;
}
// CLOVER:OFF
#region Constructor (s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="AopUtils"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
private AopUtils()
// CLOVER:OFF
/// <summary>
/// Creates a new instance of the
/// <see cref="AopUtils"/> class.
/// </summary>
/// <remarks>
/// <p>
/// This is a utility class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
private AopUtils()
{
}
// CLOVER:ON
#endregion
/// <summary>
/// Gets the type of the target.
/// </summary>
/// <param name="candidate">The candidate.</param>
/// <returns></returns>
public static Type GetTargetType(object candidate)
{
AssertUtils.ArgumentNotNull(candidate, "candidate", "Candidate object must not be null");
if (candidate is ITargetSource)
{
return ((ITargetSource) candidate).TargetType;
}
// CLOVER:ON
#endregion
/// <summary>
/// Gets the type of the target.
/// </summary>
/// <param name="candidate">The candidate.</param>
/// <returns></returns>
public static Type GetTargetType(object candidate)
if (candidate is IAdvised)
{
AssertUtils.ArgumentNotNull(candidate, "candidate", "Candidate object must not be null");
if (candidate is ITargetSource)
{
return ((ITargetSource)candidate).TargetType;
}
if (candidate is IAdvised)
{
return ((IAdvised)candidate).TargetSource.TargetType;
}
if (IsDecoratorAopProxy(candidate))
{
return candidate.GetType().BaseType;
}
return candidate.GetType();
return ((IAdvised) candidate).TargetSource.TargetType;
}
if (IsDecoratorAopProxy(candidate))
{
return candidate.GetType().BaseType;
}
return candidate.GetType();
}
}

View File

@@ -23,242 +23,246 @@ using Spring.Core;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// Abstract IObjectPostProcessor implementation that creates AOP proxies.
/// This class is completely generic; it contains no special code to handle
/// any particular aspects, such as pooling aspects.
/// </summary>
/// <remarks>
/// <p>Subclasses must implement the abstract FindCandidateAdvisors() method
/// to return a list of Advisors applying to any object. Subclasses can also
/// override the inherited ShouldSkip() method to exclude certain objects
/// from autoproxying, but they must be careful to invoke the ShouldSkip()
/// method of this class, which tries to avoid circular reference problems
/// and infinite loops.</p>
/// <p>Advisors or advices requiring ordering should implement the Ordered interface.
/// This class sorts advisors by Ordered order value. Advisors that don't implement
/// the Ordered interface will be considered to be unordered, and will appear
/// at the end of the advisor chain in undefined order.</p>
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.AutoProxy.AbstractAdvisorAutoProxyCreator.FindCandidateAdvisors"/>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger</author>
public abstract class AbstractAdvisorAutoProxyCreator : AbstractAutoProxyCreator
{
private IAdvisorRetrievalHelper _advisorRetrievalHelper;
/// <summary>
/// Abstract IObjectPostProcessor implementation that creates AOP proxies.
/// This class is completely generic; it contains no special code to handle
/// any particular aspects, such as pooling aspects.
/// We override this method to ensure that all candidate advisors are materialized
/// under a stack trace including this object. Otherwise, the dependencies won't
/// be apparent to the circular-reference prevention strategy in AbstractObjectFactory.
/// </summary>
public override IObjectFactory ObjectFactory
{
set
{
if (!(value is IConfigurableListableObjectFactory))
{
throw new InvalidOperationException("Can not use AdvisorAutoProxyCreator without a ConfigurableListableObjectFactory");
}
base.ObjectFactory = value;
InitObjectFactory((IConfigurableListableObjectFactory) value);
}
}
/// <summary>
/// An new <see cref="IConfigurableListableObjectFactory"/> was set. Initialize this creator instance
/// according to the specified object factory.
/// </summary>
/// <param name="objectFactory"></param>
protected virtual void InitObjectFactory(IConfigurableListableObjectFactory objectFactory)
{
_advisorRetrievalHelper = CreateAdvisorRetrievalHelper(objectFactory);
}
/// <summary>
/// Create the <see cref="IAdvisorRetrievalHelper"/> for retrieving the list of
/// applicable advisor objects. The default implementation calls back into
/// <see cref="IsEligibleAdvisorObject"/> thus it usually is sufficient to just
/// override <see cref="IsEligibleAdvisorObject"/>. Override <see cref="CreateAdvisorRetrievalHelper"/>
/// only if you know what you are doing!
/// </summary>
/// <param name="objectFactory"></param>
/// <returns></returns>
protected virtual IAdvisorRetrievalHelper CreateAdvisorRetrievalHelper(IConfigurableListableObjectFactory objectFactory)
{
return new ObjectFactoryAdvisorRetrievalHelperAdapter(this, objectFactory);
}
/// <summary>
/// Return whether the given object is to be proxied, what additional
/// advices (e.g. AOP Alliance interceptors) and advisors to apply.
/// </summary>
/// <remarks>
/// <p>Subclasses must implement the abstract FindCandidateAdvisors() method
/// to return a list of Advisors applying to any object. Subclasses can also
/// override the inherited ShouldSkip() method to exclude certain objects
/// from autoproxying, but they must be careful to invoke the ShouldSkip()
/// method of this class, which tries to avoid circular reference problems
/// and infinite loops.</p>
/// <p>Advisors or advices requiring ordering should implement the Ordered interface.
/// This class sorts advisors by Ordered order value. Advisors that don't implement
/// the Ordered interface will be considered to be unordered, and will appear
/// at the end of the advisor chain in undefined order.</p>
/// <p>The previous targetName of this method was "GetInterceptorAndAdvisorForObject".
/// It has been renamed in the course of general terminology clarification
/// in Spring 1.1. An AOP Alliance Interceptor is just a special form of
/// Advice, so the generic Advice term is preferred now.</p>
/// <p>The third parameter, customTargetSource, is new in Spring 1.1;
/// add it to existing implementations of this method.</p>
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.AutoProxy.AbstractAdvisorAutoProxyCreator.FindCandidateAdvisors"/>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger</author>
public abstract class AbstractAdvisorAutoProxyCreator : AbstractAutoProxyCreator
/// <param name="targetType">the type of the target object</param>
/// <param name="targetName">the name of the target object</param>
/// <param name="customTargetSource">targetSource returned by TargetSource property:
/// may be ignored. Will be null unless a custom target source is in use.</param>
/// <returns>
/// an array of additional interceptors for the particular object;
/// or an empty array if no additional interceptors but just the common ones;
/// or null if no proxy at all, not even with the common interceptors.
/// </returns>
protected override IList<object> GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
private IAdvisorRetrievalHelper _advisorRetrievalHelper;
/// <summary>
/// We override this method to ensure that all candidate advisors are materialized
/// under a stack trace including this object. Otherwise, the dependencies won't
/// be apparent to the circular-reference prevention strategy in AbstractObjectFactory.
/// </summary>
public override IObjectFactory ObjectFactory
IList<IAdvisor> advisors = FindEligibleAdvisors(targetType, targetName);
if (advisors.Count == 0)
{
set
return DO_NOT_PROXY;
}
return advisors.Cast<object>().ToArray();
}
/// <summary>
/// Find all eligible advices and for autoproxying this class.
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>
/// the empty list, not null, if there are no pointcuts or interceptors.
/// The by-order sorted list of advisors otherwise
/// </returns>
protected IList<IAdvisor> FindEligibleAdvisors(Type targetType, string targetName)
{
List<IAdvisor> candidateAdvisors = FindCandidateAdvisors(targetType, targetName);
List<IAdvisor> eligibleAdvisors = FindAdvisorsThatCanApply(candidateAdvisors, targetType, targetName);
ExtendAdvisors(eligibleAdvisors, targetType, targetName);
SortAdvisors(eligibleAdvisors);
return eligibleAdvisors;
}
/// <summary>
/// Find all possible advisor candidates to use in auto-proxying
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>the list of candidate advisors</returns>
protected virtual List<IAdvisor> FindCandidateAdvisors(Type targetType, string targetName)
{
return _advisorRetrievalHelper.FindAdvisorObjects(targetType, targetName);
}
/// <summary>
/// From the given list of candidate advisors, select the ones that are applicable
/// to the given target specified by targetType and name.
/// </summary>
/// <param name="candidateAdvisors">the list of candidate advisors to date</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
/// <returns>the list of applicable advisors</returns>
protected virtual List<IAdvisor> FindAdvisorsThatCanApply(List<IAdvisor> candidateAdvisors, Type targetType, string targetName)
{
if (candidateAdvisors.Count == 0)
{
return candidateAdvisors;
}
List<IAdvisor> eligibleAdvisors = new List<IAdvisor>();
foreach (IAdvisor candidate in candidateAdvisors)
{
if (candidate is IIntroductionAdvisor && AopUtils.CanApply(candidate, targetType, null))
{
if (!(value is IConfigurableListableObjectFactory))
if (logger.IsEnabled(LogLevel.Information))
{
throw new InvalidOperationException("Can not use AdvisorAutoProxyCreator without a ConfigurableListableObjectFactory");
logger.LogInformation($"Candidate advisor [{candidate}] accepted for targetType [{targetType}]");
}
base.ObjectFactory = value;
InitObjectFactory((IConfigurableListableObjectFactory)value);
eligibleAdvisors.Add(candidate);
}
}
/// <summary>
/// An new <see cref="IConfigurableListableObjectFactory"/> was set. Initialize this creator instance
/// according to the specified object factory.
/// </summary>
/// <param name="objectFactory"></param>
protected virtual void InitObjectFactory(IConfigurableListableObjectFactory objectFactory)
bool hasIntroductions = eligibleAdvisors.Count > 0;
foreach (IAdvisor candidate in candidateAdvisors)
{
_advisorRetrievalHelper = CreateAdvisorRetrievalHelper(objectFactory);
}
if (candidate is IIntroductionAdvisor) continue;
/// <summary>
/// Create the <see cref="IAdvisorRetrievalHelper"/> for retrieving the list of
/// applicable advisor objects. The default implementation calls back into
/// <see cref="IsEligibleAdvisorObject"/> thus it usually is sufficient to just
/// override <see cref="IsEligibleAdvisorObject"/>. Override <see cref="CreateAdvisorRetrievalHelper"/>
/// only if you know what you are doing!
/// </summary>
/// <param name="objectFactory"></param>
/// <returns></returns>
protected virtual IAdvisorRetrievalHelper CreateAdvisorRetrievalHelper(IConfigurableListableObjectFactory objectFactory)
{
return new ObjectFactoryAdvisorRetrievalHelperAdapter(this, objectFactory);
}
/// <summary>
/// Return whether the given object is to be proxied, what additional
/// advices (e.g. AOP Alliance interceptors) and advisors to apply.
/// </summary>
/// <remarks>
/// <p>The previous targetName of this method was "GetInterceptorAndAdvisorForObject".
/// It has been renamed in the course of general terminology clarification
/// in Spring 1.1. An AOP Alliance Interceptor is just a special form of
/// Advice, so the generic Advice term is preferred now.</p>
/// <p>The third parameter, customTargetSource, is new in Spring 1.1;
/// add it to existing implementations of this method.</p>
/// </remarks>
/// <param name="targetType">the type of the target object</param>
/// <param name="targetName">the name of the target object</param>
/// <param name="customTargetSource">targetSource returned by TargetSource property:
/// may be ignored. Will be null unless a custom target source is in use.</param>
/// <returns>
/// an array of additional interceptors for the particular object;
/// or an empty array if no additional interceptors but just the common ones;
/// or null if no proxy at all, not even with the common interceptors.
/// </returns>
protected override IList<object> GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
IList<IAdvisor> advisors = FindEligibleAdvisors(targetType, targetName);
if (advisors.Count == 0)
if (AopUtils.CanApply(candidate, targetType, null, hasIntroductions))
{
return DO_NOT_PROXY;
}
return advisors.Cast<object>().ToArray();
}
/// <summary>
/// Find all eligible advices and for autoproxying this class.
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>
/// the empty list, not null, if there are no pointcuts or interceptors.
/// The by-order sorted list of advisors otherwise
/// </returns>
protected IList<IAdvisor> FindEligibleAdvisors(Type targetType, string targetName)
{
List<IAdvisor> candidateAdvisors = FindCandidateAdvisors(targetType, targetName);
List<IAdvisor> eligibleAdvisors = FindAdvisorsThatCanApply(candidateAdvisors, targetType, targetName);
ExtendAdvisors(eligibleAdvisors, targetType, targetName);
SortAdvisors(eligibleAdvisors);
return eligibleAdvisors;
}
/// <summary>
/// Find all possible advisor candidates to use in auto-proxying
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>the list of candidate advisors</returns>
protected virtual List<IAdvisor> FindCandidateAdvisors(Type targetType, string targetName)
{
return _advisorRetrievalHelper.FindAdvisorObjects(targetType, targetName);
}
/// <summary>
/// From the given list of candidate advisors, select the ones that are applicable
/// to the given target specified by targetType and name.
/// </summary>
/// <param name="candidateAdvisors">the list of candidate advisors to date</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
/// <returns>the list of applicable advisors</returns>
protected virtual List<IAdvisor> FindAdvisorsThatCanApply(List<IAdvisor> candidateAdvisors, Type targetType, string targetName)
{
if (candidateAdvisors.Count==0)
{
return candidateAdvisors;
}
List<IAdvisor> eligibleAdvisors = new List<IAdvisor>();
foreach(IAdvisor candidate in candidateAdvisors)
{
if (candidate is IIntroductionAdvisor && AopUtils.CanApply(candidate, targetType, null))
if (logger.IsEnabled(LogLevel.Information))
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation($"Candidate advisor [{candidate}] accepted for targetType [{targetType}]");
}
eligibleAdvisors.Add(candidate);
logger.LogInformation($"Candidate advisor [{candidate}] accepted for targetType [{targetType}]");
}
eligibleAdvisors.Add(candidate);
}
else
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation($"Candidate advisor [{candidate}] rejected for targetType [{targetType}]");
}
}
bool hasIntroductions = eligibleAdvisors.Count > 0;
foreach(IAdvisor candidate in candidateAdvisors)
{
if (candidate is IIntroductionAdvisor) continue;
if (AopUtils.CanApply(candidate, targetType, null, hasIntroductions))
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation($"Candidate advisor [{candidate}] accepted for targetType [{targetType}]");
}
eligibleAdvisors.Add(candidate);
}
else
{
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation($"Candidate advisor [{candidate}] rejected for targetType [{targetType}]");
}
}
}
return eligibleAdvisors;
}
return eligibleAdvisors;
}
/// <summary>
/// Sorts the advisors.
/// </summary>
/// <param name="advisors">The advisors.</param>
/// <returns></returns>
protected virtual void SortAdvisors(List<IAdvisor> advisors)
/// <summary>
/// Sorts the advisors.
/// </summary>
/// <param name="advisors">The advisors.</param>
/// <returns></returns>
protected virtual void SortAdvisors(List<IAdvisor> advisors)
{
advisors.Sort(OrderComparator<IAdvisor>.Instance);
}
/// <summary>
/// Extension hook that subclasses can override to add additional advisors for the given object,
/// given the sorted advisors obtained to date.<br/>
/// The default implementation does nothing.<br/>
/// Typically used to add advisors that expose contextual information required by some of the later advisors.
/// </summary>
/// <remarks>
/// The advisor list passed into this method is already reduced to advisors applying to this particular object.
/// If you want to register additional common advisor candidates, override <see cref="FindCandidateAdvisors"/>.
/// </remarks>
/// <param name="advisors">Advisors that have already been identified as applying to a given object</param>
/// <param name="objectType">the type of the object to be advised</param>
/// <param name="objectName">the name of the object to be advised</param>
protected virtual void ExtendAdvisors(IList<IAdvisor> advisors, Type objectType, string objectName)
{
}
/// <summary>
/// Whether the given advisor is eligible for the specified target. The default implementation
/// always returns true.
/// </summary>
/// <param name="advisorName">the advisor name</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
protected virtual bool IsEligibleAdvisorObject(string advisorName, Type targetType, string targetName)
{
return true;
}
private class ObjectFactoryAdvisorRetrievalHelperAdapter : ObjectFactoryAdvisorRetrievalHelper
{
private readonly AbstractAdvisorAutoProxyCreator _owner;
public ObjectFactoryAdvisorRetrievalHelperAdapter(AbstractAdvisorAutoProxyCreator owner, IConfigurableListableObjectFactory owningFactory) : base(owningFactory)
{
advisors.Sort(OrderComparator<IAdvisor>.Instance);
_owner = owner;
}
/// <summary>
/// Extension hook that subclasses can override to add additional advisors for the given object,
/// given the sorted advisors obtained to date.<br/>
/// The default implementation does nothing.<br/>
/// Typically used to add advisors that expose contextual information required by some of the later advisors.
/// </summary>
/// <remarks>
/// The advisor list passed into this method is already reduced to advisors applying to this particular object.
/// If you want to register additional common advisor candidates, override <see cref="FindCandidateAdvisors"/>.
/// </remarks>
/// <param name="advisors">Advisors that have already been identified as applying to a given object</param>
/// <param name="objectType">the type of the object to be advised</param>
/// <param name="objectName">the name of the object to be advised</param>
protected virtual void ExtendAdvisors(IList<IAdvisor> advisors, Type objectType, string objectName)
{}
/// <summary>
/// Whether the given advisor is eligible for the specified target. The default implementation
/// always returns true.
/// </summary>
/// <param name="advisorName">the advisor name</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
protected virtual bool IsEligibleAdvisorObject(string advisorName, Type targetType, string targetName)
protected override bool IsEligibleObject(string advisorName, Type objectType, string objectName)
{
return true;
}
private class ObjectFactoryAdvisorRetrievalHelperAdapter : ObjectFactoryAdvisorRetrievalHelper
{
private readonly AbstractAdvisorAutoProxyCreator _owner;
public ObjectFactoryAdvisorRetrievalHelperAdapter(AbstractAdvisorAutoProxyCreator owner, IConfigurableListableObjectFactory owningFactory) : base(owningFactory)
{
_owner = owner;
}
protected override bool IsEligibleObject(string advisorName, Type objectType, string objectName)
{
return base.IsEligibleObject(advisorName, objectType, objectName)
&& _owner.IsEligibleAdvisorObject(advisorName, objectType, objectName);
}
return base.IsEligibleObject(advisorName, objectType, objectName)
&& _owner.IsEligibleAdvisorObject(advisorName, objectType, objectName);
}
}
}

View File

@@ -22,55 +22,54 @@
#endregion
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// The base class for AutoProxyCreator implementations that mark objects
/// eligible for proxying based on arbitrary criteria.
/// </summary>
/// <author>Erich Eichinger</author>
public abstract class AbstractFilteringAutoProxyCreator : AbstractAutoProxyCreator
{
/// <summary>
/// The base class for AutoProxyCreator implementations that mark objects
/// eligible for proxying based on arbitrary criteria.
///Overridden to call <see cref="IsEligibleForProxying"/>.
/// </summary>
/// <author>Erich Eichinger</author>
public abstract class AbstractFilteringAutoProxyCreator : AbstractAutoProxyCreator
/// <param name="targetType">the type of the object</param>
/// <param name="targetName">the name of the object</param>
/// <returns>if remarkable to skip</returns>
protected override bool ShouldSkip(Type targetType, string targetName)
{
/// <summary>
///Overridden to call <see cref="IsEligibleForProxying"/>.
/// </summary>
/// <param name="targetType">the type of the object</param>
/// <param name="targetName">the name of the object</param>
/// <returns>if remarkable to skip</returns>
protected override bool ShouldSkip( Type targetType, string targetName )
{
bool shouldSkip = !IsEligibleForProxying( targetType, targetName );
return shouldSkip;
}
/// <summary>
/// Override to always return <see cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/>.
/// </summary>
/// <remarks>
/// Whether an object shall be proxied or not is determined by the result of <see cref="IsEligibleForProxying"/>.
/// </remarks>
/// <param name="targetType">ingored</param>
/// <param name="targetName">ignored</param>
/// <param name="customTargetSource">ignored</param>
/// <returns>
/// Always <see cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/> to indicate, that the object shall be proxied.
/// </returns>
/// <seealso cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/>
protected override IList<object> GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
/// <summary>
/// Decide, whether the given object is eligible for proxying.
/// </summary>
/// <remarks>
/// Override this method to allow or reject proxying for the given object.
/// </remarks>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
/// <seealso cref="AbstractAutoProxyCreator.ShouldSkip"/>
/// <returns>whether the given object shall be proxied.</returns>
protected abstract bool IsEligibleForProxying( Type targetType, string targetName );
bool shouldSkip = !IsEligibleForProxying(targetType, targetName);
return shouldSkip;
}
/// <summary>
/// Override to always return <see cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/>.
/// </summary>
/// <remarks>
/// Whether an object shall be proxied or not is determined by the result of <see cref="IsEligibleForProxying"/>.
/// </remarks>
/// <param name="targetType">ingored</param>
/// <param name="targetName">ignored</param>
/// <param name="customTargetSource">ignored</param>
/// <returns>
/// Always <see cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/> to indicate, that the object shall be proxied.
/// </returns>
/// <seealso cref="AbstractAutoProxyCreator.PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS"/>
protected override IList<object> GetAdvicesAndAdvisorsForObject(Type targetType, string targetName, ITargetSource customTargetSource)
{
return PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS;
}
/// <summary>
/// Decide, whether the given object is eligible for proxying.
/// </summary>
/// <remarks>
/// Override this method to allow or reject proxying for the given object.
/// </remarks>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
/// <seealso cref="AbstractAutoProxyCreator.ShouldSkip"/>
/// <returns>whether the given object shall be proxied.</returns>
protected abstract bool IsEligibleForProxying(Type targetType, string targetName);
}

View File

@@ -24,89 +24,89 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// An AutoProxyCreator, that identifies objects to be proxied by checking <see cref="Attribute"/>s defined on their type.
/// </summary>
/// <author>Erich Eichinger</author>
public class AttributeAutoProxyCreator : AbstractFilteringAutoProxyCreator
{
private bool _checkInherited = false;
private Type[] _attributeTypes = null;
/// <summary>
/// An AutoProxyCreator, that identifies objects to be proxied by checking <see cref="Attribute"/>s defined on their type.
/// Indicates, whether to consider base types for filtering when checking declared attributes. Defaults to <c>false</c>.
/// </summary>
/// <author>Erich Eichinger</author>
public class AttributeAutoProxyCreator : AbstractFilteringAutoProxyCreator
public bool CheckInherited
{
private bool _checkInherited = false;
private Type[] _attributeTypes = null;
get { return _checkInherited; }
set { _checkInherited = value; }
}
/// <summary>
/// Indicates, whether to consider base types for filtering when checking declared attributes. Defaults to <c>false</c>.
/// </summary>
public bool CheckInherited
/// <summary>
/// The list of attribute types marking object types as eligible for auto-proxying by this AutoProxyCreator. Must not be <c>null</c>.
/// </summary>
public Type[] AttributeTypes
{
get { return _attributeTypes; }
set
{
get { return _checkInherited; }
set { _checkInherited = value; }
}
/// <summary>
/// The list of attribute types marking object types as eligible for auto-proxying by this AutoProxyCreator. Must not be <c>null</c>.
/// </summary>
public Type[] AttributeTypes
{
get { return _attributeTypes; }
set
{
AssertUtils.ArgumentNotNull( value, "AttributeTypes" );
_attributeTypes = value;
}
}
/// <summary>
/// Determines, whether the given object shall be proxied by matching <paramref name="targetType"/> against <see cref="AttributeTypes"/>.
/// </summary>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
protected override bool IsEligibleForProxying( Type targetType, string targetName )
{
AssertUtils.ArgumentNotNull(this.AttributeTypes, "AttributeTypes");
bool shallProxy = IsAnnotatedWithAnyOfAttribute( targetType, this.AttributeTypes, this.CheckInherited );
return shallProxy;
}
/// <summary>
/// Checks if <paramref name="objectType"/> is annotated with any of the attributes within the given list of <paramref name="attributeTypes"/>.
/// </summary>
/// <param name="objectType">the object's type</param>
/// <param name="attributeTypes">the list of <see cref="Attribute"/> types to match agains.</param>
/// <param name="checkInherited">whether to check base classes and intefaces for any of the given attributes.</param>
/// <returns><see langword="true"/> if any of the attributes is found</returns>
protected virtual bool IsAnnotatedWithAnyOfAttribute( Type objectType, Type[] attributeTypes, bool checkInherited )
{
foreach(Type attributeType in attributeTypes)
{
if (IsAnnotatedWithAttribute(objectType, attributeType, checkInherited))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks if <paramref name="objectType"/> is annotated with the specified <paramref name="attributeType"/>.
/// </summary>
/// <param name="objectType">the object's type</param>
/// <param name="attributeType">the <see cref="Attribute"/> type to match agains.</param>
/// <param name="checkInherited">whether to check base classes and intefaces for the specified attribute.</param>
/// <returns><see langword="true"/> if the attributes is found</returns>
protected virtual bool IsAnnotatedWithAttribute( Type objectType, Type attributeType, bool checkInherited )
{
if (checkInherited)
{
return AttributeUtils.FindAttribute( objectType, attributeType ) != null;
}
else
{
object[] atts = objectType.GetCustomAttributes( attributeType, false );
return ArrayUtils.HasLength( atts );
}
AssertUtils.ArgumentNotNull(value, "AttributeTypes");
_attributeTypes = value;
}
}
}
/// <summary>
/// Determines, whether the given object shall be proxied by matching <paramref name="targetType"/> against <see cref="AttributeTypes"/>.
/// </summary>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
protected override bool IsEligibleForProxying(Type targetType, string targetName)
{
AssertUtils.ArgumentNotNull(this.AttributeTypes, "AttributeTypes");
bool shallProxy = IsAnnotatedWithAnyOfAttribute(targetType, this.AttributeTypes, this.CheckInherited);
return shallProxy;
}
/// <summary>
/// Checks if <paramref name="objectType"/> is annotated with any of the attributes within the given list of <paramref name="attributeTypes"/>.
/// </summary>
/// <param name="objectType">the object's type</param>
/// <param name="attributeTypes">the list of <see cref="Attribute"/> types to match agains.</param>
/// <param name="checkInherited">whether to check base classes and intefaces for any of the given attributes.</param>
/// <returns><see langword="true"/> if any of the attributes is found</returns>
protected virtual bool IsAnnotatedWithAnyOfAttribute(Type objectType, Type[] attributeTypes, bool checkInherited)
{
foreach (Type attributeType in attributeTypes)
{
if (IsAnnotatedWithAttribute(objectType, attributeType, checkInherited))
{
return true;
}
}
return false;
}
/// <summary>
/// Checks if <paramref name="objectType"/> is annotated with the specified <paramref name="attributeType"/>.
/// </summary>
/// <param name="objectType">the object's type</param>
/// <param name="attributeType">the <see cref="Attribute"/> type to match agains.</param>
/// <param name="checkInherited">whether to check base classes and intefaces for the specified attribute.</param>
/// <returns><see langword="true"/> if the attributes is found</returns>
protected virtual bool IsAnnotatedWithAttribute(Type objectType, Type attributeType, bool checkInherited)
{
if (checkInherited)
{
return AttributeUtils.FindAttribute(objectType, attributeType) != null;
}
else
{
object[] atts = objectType.GetCustomAttributes(attributeType, false);
return ArrayUtils.HasLength(atts);
}
}
}

View File

@@ -24,116 +24,117 @@ using Spring.Objects.Factory;
#endregion
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// ObjectPostProcessor implementation that creates AOP proxies based on all candidate
/// Advisors in the current IObjectFactory. This class is completely generic; it contains
/// no special code to handle any particular aspects, such as pooling aspects.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware, IInitializingObject
{
/// <summary>
/// ObjectPostProcessor implementation that creates AOP proxies based on all candidate
/// Advisors in the current IObjectFactory. This class is completely generic; it contains
/// no special code to handle any particular aspects, such as pooling aspects.
/// Separator between prefix and remainder of object name
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
public class DefaultAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator, IObjectNameAware, IInitializingObject
public const string Separator = ".";
private bool usePrefix;
private string advisorObjectNamePrefix;
private List<IAdvisor> cachedAdvisors;
#region Properties
/// <summary>
/// Gets or sets a value indicating whether to exclude
/// advisors with a certain prefix.
/// </summary>
/// <value><c>true</c> if [use prefix]; otherwise, <c>false</c>.</value>
public bool UsePrefix
{
/// <summary>
/// Separator between prefix and remainder of object name
/// </summary>
public const string Separator = ".";
get { return usePrefix; }
set { usePrefix = value; }
}
private bool usePrefix;
private string advisorObjectNamePrefix;
private List<IAdvisor> cachedAdvisors;
/// <summary>
/// Set the prefix for object names that will cause them to be included for
/// auto-proxying by this object. This prefix should be set to avoid circular
/// references. Default value is the object name of this object + a dot.
/// </summary>
/// <value>The advisor object name prefix.</value>
public string AdvisorObjectNamePrefix
{
get { return advisorObjectNamePrefix; }
set { advisorObjectNamePrefix = value; }
}
#region Properties
#endregion
/// <summary>
/// Gets or sets a value indicating whether to exclude
/// advisors with a certain prefix.
/// </summary>
/// <value><c>true</c> if [use prefix]; otherwise, <c>false</c>.</value>
public bool UsePrefix
#region IObjectNameAware Members
/// <summary>
/// Set the name of the object in the object factory that created this object.
/// </summary>
/// <value>The name of the object in the factory.</value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="T:Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="M:Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
public string ObjectName
{
set
{
get { return usePrefix; }
set { usePrefix = value; }
}
/// <summary>
/// Set the prefix for object names that will cause them to be included for
/// auto-proxying by this object. This prefix should be set to avoid circular
/// references. Default value is the object name of this object + a dot.
/// </summary>
/// <value>The advisor object name prefix.</value>
public string AdvisorObjectNamePrefix
{
get { return advisorObjectNamePrefix; }
set { advisorObjectNamePrefix = value; }
}
#endregion
#region IObjectNameAware Members
/// <summary>
/// Set the name of the object in the object factory that created this object.
/// </summary>
/// <value>The name of the object in the factory.</value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="T:Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="M:Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
public string ObjectName
{
set
// If no infrastructure object name prefix has been set, override it.
if (advisorObjectNamePrefix == null)
{
// If no infrastructure object name prefix has been set, override it.
if (advisorObjectNamePrefix == null)
{
advisorObjectNamePrefix = value + Separator;
}
advisorObjectNamePrefix = value + Separator;
}
}
#endregion
/// <summary>
/// Find all possible advisor candidates to use in auto-proxying
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>the list of candidate advisors</returns>
protected override List<IAdvisor> FindCandidateAdvisors(Type targetType, string targetName)
{
if (cachedAdvisors == null) {
cachedAdvisors = base.FindCandidateAdvisors(targetType, targetName);
}
return cachedAdvisors;
}
/// <summary>
/// Whether the given advisor is eligible for the specified target.
/// </summary>
/// <param name="advisorName">the advisor name</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
protected override bool IsEligibleAdvisorObject(string advisorName, Type targetType, string targetName)
{
return (!usePrefix || advisorName.StartsWith(advisorObjectNamePrefix))
&& base.IsEligibleAdvisorObject(advisorName, targetType, targetName);
}
/// <summary>
/// Validate configuration
/// </summary>
public virtual void AfterPropertiesSet()
{
// eagerly resolve advisors at this stage already to prevent circular dep problems.
// TODO (EE): fix instantiation process to make test "AdvisorAutoProxyCreatorCircularReferencesTests" work.
cachedAdvisors = base.FindCandidateAdvisors(null, null);
}
}
#endregion
/// <summary>
/// Find all possible advisor candidates to use in auto-proxying
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>the list of candidate advisors</returns>
protected override List<IAdvisor> FindCandidateAdvisors(Type targetType, string targetName)
{
if (cachedAdvisors == null)
{
cachedAdvisors = base.FindCandidateAdvisors(targetType, targetName);
}
return cachedAdvisors;
}
/// <summary>
/// Whether the given advisor is eligible for the specified target.
/// </summary>
/// <param name="advisorName">the advisor name</param>
/// <param name="targetType">the target object's type</param>
/// <param name="targetName">the target object's name</param>
protected override bool IsEligibleAdvisorObject(string advisorName, Type targetType, string targetName)
{
return (!usePrefix || advisorName.StartsWith(advisorObjectNamePrefix))
&& base.IsEligibleAdvisorObject(advisorName, targetType, targetName);
}
/// <summary>
/// Validate configuration
/// </summary>
public virtual void AfterPropertiesSet()
{
// eagerly resolve advisors at this stage already to prevent circular dep problems.
// TODO (EE): fix instantiation process to make test "AdvisorAutoProxyCreatorCircularReferencesTests" work.
cachedAdvisors = base.FindCandidateAdvisors(null, null);
}
}

View File

@@ -1,15 +1,14 @@
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// Interface encapsulating the advisor retrieval strategy used by
/// an <see cref="AbstractAdvisorAutoProxyCreator"/> to retrieve the
/// applicable list of advisor objects.
/// </summary>
public interface IAdvisorRetrievalHelper
{
/// <summary>
/// Interface encapsulating the advisor retrieval strategy used by
/// an <see cref="AbstractAdvisorAutoProxyCreator"/> to retrieve the
/// applicable list of advisor objects.
/// Get the list of advisor objects to apply on the target.
/// </summary>
public interface IAdvisorRetrievalHelper
{
/// <summary>
/// Get the list of advisor objects to apply on the target.
/// </summary>
List<IAdvisor> FindAdvisorObjects(Type targetType, string targetName);
}
List<IAdvisor> FindAdvisorObjects(Type targetType, string targetName);
}

View File

@@ -24,28 +24,27 @@ using Spring.Objects.Factory;
#endregion
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// Implementations can create special target sources, such as pooling target
/// sources, for particular objects. For example, they may base their choice
/// on attributes, such as a pooling attribute, on the target type.
/// </summary>
/// <remarks><p>AbstractAutoProxyCreator can support a number of TargetSourceCreators,
/// which will be applied in order.</p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
public interface ITargetSourceCreator
{
/// <summary>
/// Implementations can create special target sources, such as pooling target
/// sources, for particular objects. For example, they may base their choice
/// on attributes, such as a pooling attribute, on the target type.
/// Create a special TargetSource for the given object, if any.
/// </summary>
/// <remarks><p>AbstractAutoProxyCreator can support a number of TargetSourceCreators,
/// which will be applied in order.</p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Adhari C Mahendra (.NET)</author>
public interface ITargetSourceCreator
{
/// <summary>
/// Create a special TargetSource for the given object, if any.
/// </summary>
/// <param name="objectType">The type of the object to create a TargetSource for</param>
/// <param name="objectName">the name of the object</param>
/// <param name="factory">the containing factory</param>
/// <returns>a special TargetSource or null if this TargetSourceCreator isn't
/// interested in the particular object</returns>
ITargetSource GetTargetSource(Type objectType, string objectName, IObjectFactory factory);
}
/// <param name="objectType">The type of the object to create a TargetSource for</param>
/// <param name="objectName">the name of the object</param>
/// <param name="factory">the containing factory</param>
/// <returns>a special TargetSource or null if this TargetSourceCreator isn't
/// interested in the particular object</returns>
ITargetSource GetTargetSource(Type objectType, string objectName, IObjectFactory factory);
}

View File

@@ -20,41 +20,40 @@
using Spring.Objects.Factory.Config;
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// A special version of an APC that explicitely cares for infrastructure (=internal)
/// advisors only
/// </summary>
/// <author>Erich Eichinger</author>
public class InfrastructureAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator
{
/// <summary>
/// A special version of an APC that explicitely cares for infrastructure (=internal)
/// advisors only
/// Overridden to create a special version of an <see cref="IAdvisorRetrievalHelper"/>
/// that accepts only infrastructure advisor definitions
/// </summary>
/// <author>Erich Eichinger</author>
public class InfrastructureAdvisorAutoProxyCreator : AbstractAdvisorAutoProxyCreator
/// <param name="objectFactory"></param>
/// <returns></returns>
protected override IAdvisorRetrievalHelper CreateAdvisorRetrievalHelper(IConfigurableListableObjectFactory objectFactory)
{
/// <summary>
/// Overridden to create a special version of an <see cref="IAdvisorRetrievalHelper"/>
/// that accepts only infrastructure advisor definitions
/// </summary>
/// <param name="objectFactory"></param>
/// <returns></returns>
protected override IAdvisorRetrievalHelper CreateAdvisorRetrievalHelper(IConfigurableListableObjectFactory objectFactory)
return new InfrastructurAdvisorRetrievalHelper(this, objectFactory);
}
private class InfrastructurAdvisorRetrievalHelper : ObjectFactoryAdvisorRetrievalHelper
{
private readonly InfrastructureAdvisorAutoProxyCreator _owner;
public InfrastructurAdvisorRetrievalHelper(InfrastructureAdvisorAutoProxyCreator owner, IConfigurableListableObjectFactory objectFactory)
: base(objectFactory)
{
return new InfrastructurAdvisorRetrievalHelper(this, objectFactory);
_owner = owner;
}
private class InfrastructurAdvisorRetrievalHelper : ObjectFactoryAdvisorRetrievalHelper
protected override bool IsEligibleObject(string advisorName, Type objectType, string objectName)
{
private readonly InfrastructureAdvisorAutoProxyCreator _owner;
public InfrastructurAdvisorRetrievalHelper(InfrastructureAdvisorAutoProxyCreator owner, IConfigurableListableObjectFactory objectFactory)
: base(objectFactory)
{
_owner = owner;
}
protected override bool IsEligibleObject(string advisorName, Type objectType, string objectName)
{
return this.ObjectFactory.ContainsObjectDefinition(advisorName)
&& this.ObjectFactory.GetObjectDefinition(advisorName).Role == ObjectRole.ROLE_INFRASTRUCTURE;
}
return this.ObjectFactory.ContainsObjectDefinition(advisorName)
&& this.ObjectFactory.GetObjectDefinition(advisorName).Role == ObjectRole.ROLE_INFRASTRUCTURE;
}
}
}

View File

@@ -16,9 +16,7 @@
using System.Collections;
using System.Runtime.Serialization;
using AopAlliance.Aop;
using Spring.Util;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
@@ -27,310 +25,310 @@ using Spring.Aop.Framework.Adapter;
using Spring.Aop.Framework.DynamicProxy;
using Spring.Core;
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// <see cref="IObjectFactoryPostProcessor"/> implementation that replaces a group of objects
/// with a 'true' inheritance based AOP mechanism that delegates
/// to the given interceptors before invoking the object itself.
/// </summary>
/// <author>Bruno Baia</author>
public class InheritanceBasedAopConfigurer : IObjectFactoryPostProcessor, IObjectFactoryAware, IOrdered
{
private IList objectNames;
private string[] interceptorNames = new string[0];
private bool proxyTargetAttributes = true;
private bool proxyDeclaredMembersOnly = true;
private bool proxyInterfaces = false;
private IObjectFactory objectFactory;
private int order = int.MaxValue;
private IAdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.Instance;
/// <summary>
/// <see cref="IObjectFactoryPostProcessor"/> implementation that replaces a group of objects
/// with a 'true' inheritance based AOP mechanism that delegates
/// to the given interceptors before invoking the object itself.
/// Set the names of the objects in IList fashioned way
/// that should automatically get intercepted.
/// </summary>
/// <author>Bruno Baia</author>
public class InheritanceBasedAopConfigurer : IObjectFactoryPostProcessor, IObjectFactoryAware, IOrdered
/// <remarks>
/// A name can specify a prefix to match by ending with "*", e.g. "myObject,tx*"
/// will match the object named "myObject" and all objects whose name start with "tx".
/// </remarks>
public virtual IList ObjectNames
{
private IList objectNames;
private string[] interceptorNames = new string[0];
private bool proxyTargetAttributes = true;
private bool proxyDeclaredMembersOnly = true;
private bool proxyInterfaces = false;
set { objectNames = value; }
}
private IObjectFactory objectFactory;
private int order = int.MaxValue;
private IAdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.Instance;
/// <summary>
/// Sets the common interceptors, a list of <see cref="AopAlliance.Aop.IAdvice"/>,
/// <see cref="Spring.Aop.IAdvisor"/> and introduction object names.
/// </summary>
/// <remarks>
/// <para>
/// If this property isn't set, there will be zero common interceptors.
/// This is perfectly valid, if "specific" interceptors such as
/// matching Advisors are all we want.
/// </para>
/// </remarks>
/// <value>
/// The list of <see cref="AopAlliance.Aop.IAdvice"/>,
/// <see cref="Spring.Aop.IAdvisor"/> and introduction object names.
/// </value>
/// <seealso cref="AopAlliance.Aop.IAdvice"/>
/// <seealso cref="Spring.Aop.IAdvisor"/>
public virtual string[] InterceptorNames
{
set { interceptorNames = value; }
}
/// <summary>
/// Set the names of the objects in IList fashioned way
/// that should automatically get intercepted.
/// </summary>
/// <remarks>
/// A name can specify a prefix to match by ending with "*", e.g. "myObject,tx*"
/// will match the object named "myObject" and all objects whose name start with "tx".
/// </remarks>
public virtual IList ObjectNames
/// <summary>
/// Is target type attributes, method attributes, method's return type attributes
/// and method's parameter attributes to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
public virtual bool ProxyTargetAttributes
{
get { return this.proxyTargetAttributes; }
set { this.proxyTargetAttributes = value; }
}
/// <summary>
/// Gets or sets a value indicating whether inherited members should be proxied.
/// </summary>
/// <value>
/// <see langword="true"/> if inherited members should be proxied;
/// otherwise, <see langword="false"/>.
/// </value>
public bool ProxyDeclaredMembersOnly
{
get { return proxyDeclaredMembersOnly; }
set { proxyDeclaredMembersOnly = value; }
}
/// <summary>
/// Gets or sets a value indicating whether interfaces members should be proxied.
/// </summary>
/// <value>
/// <see langword="true"/> if interfaces members should be proxied;
/// otherwise, <see langword="false"/>.
/// </value>
public bool ProxyInterfaces
{
get { return proxyInterfaces; }
set { proxyInterfaces = value; }
}
/// <summary>
/// Callback that supplies the owning factory to an object instance.
/// </summary>
/// <value>
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// (may not be <see langword="null"/>). The object can immediately
/// call methods on the factory.
/// </value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of initialization errors.
/// </exception>
public IObjectFactory ObjectFactory
{
set { objectFactory = value; }
}
/// <summary>
/// Allows for custom modification of an application context's object definitions.
/// </summary>
/// <remarks>
/// <p>
/// If the object name matches, replaces the type by a AOP proxied type based on inheritance.
/// </p>
/// </remarks>
public void PostProcessObjectFactory(IConfigurableListableObjectFactory factory)
{
var objectDefinitionNames = factory.GetObjectDefinitionNames();
for (int i = 0; i < objectDefinitionNames.Count; ++i)
{
set { objectNames = value; }
}
/// <summary>
/// Sets the common interceptors, a list of <see cref="AopAlliance.Aop.IAdvice"/>,
/// <see cref="Spring.Aop.IAdvisor"/> and introduction object names.
/// </summary>
/// <remarks>
/// <para>
/// If this property isn't set, there will be zero common interceptors.
/// This is perfectly valid, if "specific" interceptors such as
/// matching Advisors are all we want.
/// </para>
/// </remarks>
/// <value>
/// The list of <see cref="AopAlliance.Aop.IAdvice"/>,
/// <see cref="Spring.Aop.IAdvisor"/> and introduction object names.
/// </value>
/// <seealso cref="AopAlliance.Aop.IAdvice"/>
/// <seealso cref="Spring.Aop.IAdvisor"/>
public virtual string[] InterceptorNames
{
set { interceptorNames = value; }
}
/// <summary>
/// Is target type attributes, method attributes, method's return type attributes
/// and method's parameter attributes to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
public virtual bool ProxyTargetAttributes
{
get { return this.proxyTargetAttributes; }
set { this.proxyTargetAttributes = value; }
}
/// <summary>
/// Gets or sets a value indicating whether inherited members should be proxied.
/// </summary>
/// <value>
/// <see langword="true"/> if inherited members should be proxied;
/// otherwise, <see langword="false"/>.
/// </value>
public bool ProxyDeclaredMembersOnly
{
get { return proxyDeclaredMembersOnly; }
set { proxyDeclaredMembersOnly = value; }
}
/// <summary>
/// Gets or sets a value indicating whether interfaces members should be proxied.
/// </summary>
/// <value>
/// <see langword="true"/> if interfaces members should be proxied;
/// otherwise, <see langword="false"/>.
/// </value>
public bool ProxyInterfaces
{
get { return proxyInterfaces; }
set { proxyInterfaces = value; }
}
/// <summary>
/// Callback that supplies the owning factory to an object instance.
/// </summary>
/// <value>
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// (may not be <see langword="null"/>). The object can immediately
/// call methods on the factory.
/// </value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of initialization errors.
/// </exception>
public IObjectFactory ObjectFactory
{
set { objectFactory = value; }
}
/// <summary>
/// Allows for custom modification of an application context's object definitions.
/// </summary>
/// <remarks>
/// <p>
/// If the object name matches, replaces the type by a AOP proxied type based on inheritance.
/// </p>
/// </remarks>
public void PostProcessObjectFactory(IConfigurableListableObjectFactory factory)
{
var objectDefinitionNames = factory.GetObjectDefinitionNames();
for (int i = 0; i < objectDefinitionNames.Count; ++i)
string name = objectDefinitionNames[i];
if (IsObjectNameMatch(name))
{
string name = objectDefinitionNames[i];
if (IsObjectNameMatch(name))
var definition = factory.GetObjectDefinition(name) as IConfigurableObjectDefinition;
if (definition == null || IsInfrastructureType(definition.ObjectType, name))
{
var definition = factory.GetObjectDefinition(name) as IConfigurableObjectDefinition;
if (definition == null || IsInfrastructureType(definition.ObjectType, name))
{
continue;
}
ProxyFactory pf = CreateProxyFactory(definition.ObjectType, name);
InheritanceAopProxyTypeBuilder iaptb = new InheritanceAopProxyTypeBuilder(pf);
iaptb.ProxyDeclaredMembersOnly = this.ProxyDeclaredMembersOnly;
Type type = iaptb.BuildProxyType();
definition.ObjectType = type;
definition.ConstructorArgumentValues.AddIndexedArgumentValue(definition.ConstructorArgumentValues.ArgumentCount, pf);
continue;
}
}
}
/// <summary>
/// Return the order value of this object, where a higher value means greater in
/// terms of sorting.
/// </summary>
/// <remarks>
/// Ordering which will apply to this class's implementation
/// of Ordered, used when applying multiple ObjectPostProcessors.
/// Default value is int.MaxValue, meaning that it's non-ordered.
/// </remarks>
/// <returns>The order value.</returns>
public virtual int Order
{
get { return order; }
set { order = value; }
}
ProxyFactory pf = CreateProxyFactory(definition.ObjectType, name);
/// <summary>
/// Determines whether the object is an infrastructure type,
/// IAdvisor, IAdvice, IAdvisors, AbstractAutoProxyCreator or InheritanceBasedAopConfigurer.
/// </summary>
/// <param name="type">The object type to compare</param>
/// <param name="name">The name of the object</param>
/// <returns>
/// <c>true</c> if [is infrastructure type] [the specified obj]; otherwise, <c>false</c>.
/// </returns>
protected virtual bool IsInfrastructureType(Type type, String name)
{
return typeof(IAdvisor).IsAssignableFrom(type)
|| typeof(IAdvice).IsAssignableFrom(type)
|| typeof(IAdvisors).IsAssignableFrom(type)
|| typeof(AbstractAutoProxyCreator).IsAssignableFrom(type)
|| typeof(InheritanceBasedAopConfigurer).IsAssignableFrom(type);
}
InheritanceAopProxyTypeBuilder iaptb = new InheritanceAopProxyTypeBuilder(pf);
iaptb.ProxyDeclaredMembersOnly = this.ProxyDeclaredMembersOnly;
Type type = iaptb.BuildProxyType();
/// <summary>
/// Create an AOP proxy for the given object.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <param name="objectName">The name of the object.</param>
/// <returns>The AOP Proxy for the object.</returns>
protected virtual ProxyFactory CreateProxyFactory(Type objectType, string objectName)
{
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.ProxyTargetAttributes = this.ProxyTargetAttributes;
proxyFactory.TargetSource = new InheritanceBasedAopTargetSource(objectType);
if (!ProxyInterfaces)
{
proxyFactory.Interfaces = Type.EmptyTypes;
}
IList<IAdvisor> advisors = ResolveInterceptorNames();
foreach (IAdvisor advisor in advisors)
{
if (advisor is IIntroductionAdvisor)
{
proxyFactory.AddIntroduction((IIntroductionAdvisor)advisor);
}
else
{
proxyFactory.AddAdvisor(advisor);
}
}
return proxyFactory;
}
/// <summary>
/// Return if the given object name matches one of the object names specified.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
/// as well as direct equality. Can be overridden in subclasses.
/// </p>
/// </remarks>
/// <param name="objectName">the object name to check</param>
/// <returns>if the names match</returns>
protected virtual bool IsObjectNameMatch(string objectName)
{
if (objectNames != null)
{
for (int i = 0; i < objectNames.Count; i++)
{
string mappedName = String.Copy((string)objectNames[i]);
if (PatternMatchUtils.SimpleMatch(mappedName, objectName))
{
return true;
}
}
}
return false;
}
private IList<IAdvisor> ResolveInterceptorNames()
{
List<IAdvisor> advisors = new List<IAdvisor>();
foreach (string name in interceptorNames)
{
object next = objectFactory.GetObject(name);
if (next is IAdvisors)
{
advisors.AddRange(((IAdvisors)next).Advisors);
}
else
{
advisors.Add(advisorAdapterRegistry.Wrap(next));
}
}
return advisors;
}
[Serializable]
private class InheritanceBasedAopTargetSource : ITargetSource, ISerializable
{
private readonly Type _targetType;
public InheritanceBasedAopTargetSource(Type targetType)
{
_targetType = targetType;
}
/// <inheritdoc />
private InheritanceBasedAopTargetSource(SerializationInfo info, StreamingContext context)
{
var type = info.GetString("TargetType");
_targetType = type != null ? Type.GetType(type) : null;
}
/// <inheritdoc />
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("TargetType", _targetType?.AssemblyQualifiedName);
}
public object GetTarget()
{
return null;
}
public bool IsStatic
{
get { return true; }
}
public void ReleaseTarget(object target)
{
}
public Type TargetType
{
get { return _targetType; }
definition.ObjectType = type;
definition.ConstructorArgumentValues.AddIndexedArgumentValue(definition.ConstructorArgumentValues.ArgumentCount, pf);
}
}
}
/// <summary>
/// Return the order value of this object, where a higher value means greater in
/// terms of sorting.
/// </summary>
/// <remarks>
/// Ordering which will apply to this class's implementation
/// of Ordered, used when applying multiple ObjectPostProcessors.
/// Default value is int.MaxValue, meaning that it's non-ordered.
/// </remarks>
/// <returns>The order value.</returns>
public virtual int Order
{
get { return order; }
set { order = value; }
}
/// <summary>
/// Determines whether the object is an infrastructure type,
/// IAdvisor, IAdvice, IAdvisors, AbstractAutoProxyCreator or InheritanceBasedAopConfigurer.
/// </summary>
/// <param name="type">The object type to compare</param>
/// <param name="name">The name of the object</param>
/// <returns>
/// <c>true</c> if [is infrastructure type] [the specified obj]; otherwise, <c>false</c>.
/// </returns>
protected virtual bool IsInfrastructureType(Type type, String name)
{
return typeof(IAdvisor).IsAssignableFrom(type)
|| typeof(IAdvice).IsAssignableFrom(type)
|| typeof(IAdvisors).IsAssignableFrom(type)
|| typeof(AbstractAutoProxyCreator).IsAssignableFrom(type)
|| typeof(InheritanceBasedAopConfigurer).IsAssignableFrom(type);
}
/// <summary>
/// Create an AOP proxy for the given object.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <param name="objectName">The name of the object.</param>
/// <returns>The AOP Proxy for the object.</returns>
protected virtual ProxyFactory CreateProxyFactory(Type objectType, string objectName)
{
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.ProxyTargetAttributes = this.ProxyTargetAttributes;
proxyFactory.TargetSource = new InheritanceBasedAopTargetSource(objectType);
if (!ProxyInterfaces)
{
proxyFactory.Interfaces = Type.EmptyTypes;
}
IList<IAdvisor> advisors = ResolveInterceptorNames();
foreach (IAdvisor advisor in advisors)
{
if (advisor is IIntroductionAdvisor)
{
proxyFactory.AddIntroduction((IIntroductionAdvisor) advisor);
}
else
{
proxyFactory.AddAdvisor(advisor);
}
}
return proxyFactory;
}
/// <summary>
/// Return if the given object name matches one of the object names specified.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
/// as well as direct equality. Can be overridden in subclasses.
/// </p>
/// </remarks>
/// <param name="objectName">the object name to check</param>
/// <returns>if the names match</returns>
protected virtual bool IsObjectNameMatch(string objectName)
{
if (objectNames != null)
{
for (int i = 0; i < objectNames.Count; i++)
{
string mappedName = String.Copy((string) objectNames[i]);
if (PatternMatchUtils.SimpleMatch(mappedName, objectName))
{
return true;
}
}
}
return false;
}
private IList<IAdvisor> ResolveInterceptorNames()
{
List<IAdvisor> advisors = new List<IAdvisor>();
foreach (string name in interceptorNames)
{
object next = objectFactory.GetObject(name);
if (next is IAdvisors)
{
advisors.AddRange(((IAdvisors) next).Advisors);
}
else
{
advisors.Add(advisorAdapterRegistry.Wrap(next));
}
}
return advisors;
}
[Serializable]
private class InheritanceBasedAopTargetSource : ITargetSource, ISerializable
{
private readonly Type _targetType;
public InheritanceBasedAopTargetSource(Type targetType)
{
_targetType = targetType;
}
/// <inheritdoc />
private InheritanceBasedAopTargetSource(SerializationInfo info, StreamingContext context)
{
var type = info.GetString("TargetType");
_targetType = type != null ? Type.GetType(type) : null;
}
/// <inheritdoc />
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("TargetType", _targetType?.AssemblyQualifiedName);
}
public object GetTarget()
{
return null;
}
public bool IsStatic
{
get { return true; }
}
public void ReleaseTarget(object target)
{
}
public Type TargetType
{
get { return _targetType; }
}
}
}

View File

@@ -23,152 +23,155 @@ using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
using Spring.Util;
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// Helper for retrieving standard Spring advisors from an <see cref="IObjectFactory"/> for
/// use with auto-proxying.
/// </summary>
/// <author>Erich Eichinger</author>
public class ObjectFactoryAdvisorRetrievalHelper : IAdvisorRetrievalHelper
{
private readonly ILogger _log;
private readonly IConfigurableListableObjectFactory _objectFactory;
private List<string> _cachedObjectNames;
/// <summary>
/// Helper for retrieving standard Spring advisors from an <see cref="IObjectFactory"/> for
/// use with auto-proxying.
/// The object factory to lookup advisors from
/// </summary>
/// <author>Erich Eichinger</author>
public class ObjectFactoryAdvisorRetrievalHelper : IAdvisorRetrievalHelper
public IConfigurableListableObjectFactory ObjectFactory
{
private readonly ILogger _log;
private readonly IConfigurableListableObjectFactory _objectFactory;
private List<string> _cachedObjectNames;
get { return _objectFactory; }
}
/// <summary>
/// The object factory to lookup advisors from
/// </summary>
public IConfigurableListableObjectFactory ObjectFactory
/// <summary>
/// Create a new helper for the specified <paramref name="objectFactory"/>.
/// </summary>
public ObjectFactoryAdvisorRetrievalHelper(IConfigurableListableObjectFactory objectFactory)
{
AssertUtils.ArgumentNotNull(objectFactory, "objectFactory");
_log = LogManager.GetLogger(this.GetType());
_objectFactory = objectFactory;
}
/// <summary>
/// Find all all eligible advisor objects in the current object factory.
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>A list of eligible <see cref="IAdvisor"/> instances</returns>
public virtual List<IAdvisor> FindAdvisorObjects(Type targetType, string targetName)
{
IList<string> advisorNames = GetAdvisorCandidateNames(targetType, targetName);
List<IAdvisor> advisors = new List<IAdvisor>();
if (advisorNames.Count == 0)
{
get { return _objectFactory; }
}
/// <summary>
/// Create a new helper for the specified <paramref name="objectFactory"/>.
/// </summary>
public ObjectFactoryAdvisorRetrievalHelper(IConfigurableListableObjectFactory objectFactory )
{
AssertUtils.ArgumentNotNull(objectFactory, "objectFactory");
_log = LogManager.GetLogger(this.GetType());
_objectFactory = objectFactory;
}
/// <summary>
/// Find all all eligible advisor objects in the current object factory.
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>A list of eligible <see cref="IAdvisor"/> instances</returns>
public virtual List<IAdvisor> FindAdvisorObjects(Type targetType, string targetName)
{
IList<string> advisorNames = GetAdvisorCandidateNames(targetType, targetName);
List<IAdvisor> advisors = new List<IAdvisor>();
if (advisorNames.Count == 0)
{
return advisors;
}
for (int i = 0; i < advisorNames.Count; i++)
{
string name = advisorNames[i];
if (IsEligibleObject(name, targetType, targetName) && !_objectFactory.IsCurrentlyInCreation(name))
{
try
{
AddAdvisorCandidate(advisors, name);
}
catch (ObjectCreationException ex)
{
Exception rootEx = ex.GetBaseException();
if (rootEx is ObjectCurrentlyInCreationException)
{
ObjectCurrentlyInCreationException oce = (ObjectCurrentlyInCreationException)rootEx;
if (_objectFactory.IsCurrentlyInCreation(oce.ObjectName))
{
if (_log.IsEnabled(LogLevel.Debug))
{
_log.LogDebug(string.Format("Ignoring currently created advisor '{0}': exception message = {1}",
name, ex.Message));
}
continue;
}
}
throw;
}
}
}
return advisors;
}
/// <summary>
/// Add the named advisor instance to the list of advisors.
/// </summary>
/// <param name="advisors">the advisor list</param>
/// <param name="advisorName">the object name of the advisor to add</param>
private void AddAdvisorCandidate(List<IAdvisor> advisors, string advisorName)
for (int i = 0; i < advisorNames.Count; i++)
{
object advisorCandidate = _objectFactory.GetObject(advisorName);
if (advisorCandidate is IAdvisor)
string name = advisorNames[i];
if (IsEligibleObject(name, targetType, targetName) && !_objectFactory.IsCurrentlyInCreation(name))
{
advisors.Add((IAdvisor) advisorCandidate);
}
else if (advisorCandidate is IAdvisors)
{
advisors.AddRange(((IAdvisors)advisorCandidate).Advisors);
}
else
{
throw new InvalidOperationException("expected type IAdvisor or IAdvisors but was " +
advisorCandidate.GetType().FullName);
}
}
/// <summary>
/// Gets the names of advisor candidates
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>a non-null string array of advisor candidate names</returns>
protected virtual IList<string> GetAdvisorCandidateNames(Type targetType, string targetName)
{
if (_cachedObjectNames == null)
{
lock(this)
try
{
if (_cachedObjectNames == null)
AddAdvisorCandidate(advisors, name);
}
catch (ObjectCreationException ex)
{
Exception rootEx = ex.GetBaseException();
if (rootEx is ObjectCurrentlyInCreationException)
{
List<string> candidateNameList = new List<string>();
IList<string> advisorCandidateNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors( _objectFactory, typeof(IAdvisor), true, false);
candidateNameList.AddRange(advisorCandidateNames);
IList<string> advisorsCandidateNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_objectFactory, typeof(IAdvisors), true, false);
candidateNameList.AddRange(advisorsCandidateNames);
_cachedObjectNames = candidateNameList;
ObjectCurrentlyInCreationException oce = (ObjectCurrentlyInCreationException) rootEx;
if (_objectFactory.IsCurrentlyInCreation(oce.ObjectName))
{
if (_log.IsEnabled(LogLevel.Debug))
{
_log.LogDebug(string.Format("Ignoring currently created advisor '{0}': exception message = {1}",
name, ex.Message));
}
continue;
}
}
throw;
}
}
return _cachedObjectNames;
}
/// <summary>
/// Determine, whether the specified aspect object is eligible.
/// The default implementation accepts all except for advisors that are
/// part of the internal infrastructure.
/// </summary>
/// <param name="advisorName">the name of the candidate advisor</param>
/// <param name="objectType">the type of the object to be advised</param>
/// <param name="objectName">the name of the object to be advised</param>
protected virtual bool IsEligibleObject(string advisorName, Type objectType, string objectName )
return advisors;
}
/// <summary>
/// Add the named advisor instance to the list of advisors.
/// </summary>
/// <param name="advisors">the advisor list</param>
/// <param name="advisorName">the object name of the advisor to add</param>
private void AddAdvisorCandidate(List<IAdvisor> advisors, string advisorName)
{
object advisorCandidate = _objectFactory.GetObject(advisorName);
if (advisorCandidate is IAdvisor)
{
bool containsObjectDefinition = this.ObjectFactory.ContainsObjectDefinition(advisorName);
if (containsObjectDefinition)
advisors.Add((IAdvisor) advisorCandidate);
}
else if (advisorCandidate is IAdvisors)
{
advisors.AddRange(((IAdvisors) advisorCandidate).Advisors);
}
else
{
throw new InvalidOperationException("expected type IAdvisor or IAdvisors but was " +
advisorCandidate.GetType().FullName);
}
}
/// <summary>
/// Gets the names of advisor candidates
/// </summary>
/// <param name="targetType">the type of the object to be advised</param>
/// <param name="targetName">the name of the object to be advised</param>
/// <returns>a non-null string array of advisor candidate names</returns>
protected virtual IList<string> GetAdvisorCandidateNames(Type targetType, string targetName)
{
if (_cachedObjectNames == null)
{
lock (this)
{
return this.ObjectFactory.GetObjectDefinition(advisorName).Role != ObjectRole.ROLE_INFRASTRUCTURE;
if (_cachedObjectNames == null)
{
List<string> candidateNameList = new List<string>();
IList<string> advisorCandidateNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_objectFactory, typeof(IAdvisor), true, false);
candidateNameList.AddRange(advisorCandidateNames);
IList<string> advisorsCandidateNames = ObjectFactoryUtils.ObjectNamesForTypeIncludingAncestors(_objectFactory, typeof(IAdvisors), true, false);
candidateNameList.AddRange(advisorsCandidateNames);
_cachedObjectNames = candidateNameList;
}
}
return this.ObjectFactory.ContainsObject(advisorName);
}
}
return _cachedObjectNames;
}
/// <summary>
/// Determine, whether the specified aspect object is eligible.
/// The default implementation accepts all except for advisors that are
/// part of the internal infrastructure.
/// </summary>
/// <param name="advisorName">the name of the candidate advisor</param>
/// <param name="objectType">the type of the object to be advised</param>
/// <param name="objectName">the name of the object to be advised</param>
protected virtual bool IsEligibleObject(string advisorName, Type objectType, string objectName)
{
bool containsObjectDefinition = this.ObjectFactory.ContainsObjectDefinition(advisorName);
if (containsObjectDefinition)
{
return this.ObjectFactory.GetObjectDefinition(advisorName).Role != ObjectRole.ROLE_INFRASTRUCTURE;
}
return this.ObjectFactory.ContainsObject(advisorName);
}
}

View File

@@ -22,114 +22,117 @@ using System.Collections;
using Spring.Objects.Factory;
using Spring.Util;
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// AutoProxyCreator that identifies objects to proxy via a list of names.
/// </summary>
/// <remarks>
/// <para>
/// Auto proxy creator that identifies objects to proxy via a list of names.
/// Checks for direct, "xxx*", "*xxx" and "*xxx*" matches.
/// </para>
/// <para>In case of a IFactoryObject, only the objects created by the
/// FactoryBean will get proxied. If you intend to proxy a IFactoryObject instance itself
/// specify the object name of the IFactoryObject including
/// the factory-object prefix "&amp;" e.g. "&amp;MyFactoryObject".
/// </para>
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator.IsMatch"/>
/// <author>Juergen Hoeller</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger</author>
public class ObjectNameAutoProxyCreator : AbstractFilteringAutoProxyCreator
{
private IList objectNames;
/// <summary>
/// AutoProxyCreator that identifies objects to proxy via a list of names.
/// Initializes a new instance of <see cref="ObjectNameAutoProxyCreator"/>.
/// </summary>
/// <remarks>
/// <para>
/// Auto proxy creator that identifies objects to proxy via a list of names.
/// Checks for direct, "xxx*", "*xxx" and "*xxx*" matches.
/// </para>
/// <para>In case of a IFactoryObject, only the objects created by the
/// FactoryBean will get proxied. If you intend to proxy a IFactoryObject instance itself
/// specify the object name of the IFactoryObject including
/// the factory-object prefix "&amp;" e.g. "&amp;MyFactoryObject".
/// </para>
/// </remarks>
/// <seealso cref="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator.IsMatch"/>
/// <author>Juergen Hoeller</author>
/// <author>Adhari C Mahendra (.NET)</author>
/// <author>Erich Eichinger</author>
public class ObjectNameAutoProxyCreator : AbstractFilteringAutoProxyCreator
public ObjectNameAutoProxyCreator()
{
private IList objectNames;
}
/// <summary>
/// Initializes a new instance of <see cref="ObjectNameAutoProxyCreator"/>.
/// </summary>
public ObjectNameAutoProxyCreator()
{}
/// <summary>
/// Set the names of the objects in IList fashioned way that should automatically
/// get wrapped with proxies.
/// A name can specify a prefix to match by ending with "*", e.g. "myObject,tx*"
/// will match the object named "myObject" and all objects whose name start with "tx".
/// </summary>
public IList ObjectNames
/// <summary>
/// Set the names of the objects in IList fashioned way that should automatically
/// get wrapped with proxies.
/// A name can specify a prefix to match by ending with "*", e.g. "myObject,tx*"
/// will match the object named "myObject" and all objects whose name start with "tx".
/// </summary>
public IList ObjectNames
{
set
{
set
{
AssertUtils.ArgumentHasElements(value, "ObjectNames");
objectNames = value;
}
get
{
return objectNames;
}
AssertUtils.ArgumentHasElements(value, "ObjectNames");
objectNames = value;
}
/// <summary>
/// Identify as object to proxy if the object name is in the configured list of names.
/// </summary>
protected override bool IsEligibleForProxying( Type targetType, string targetName )
get
{
bool shallProxy = IsObjectNameMatch(targetType, targetName, this.ObjectNames);
return shallProxy;
}
/// <summary>
/// Return if the given object name matches the mapped name.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
/// as well as direct equality. Can be overridden in subclasses.
/// </p>
/// </remarks>
/// <param name="objectName">the object name to check</param>
/// <param name="mappedName">the name in the configured list of names</param>
/// <returns>if the names match</returns>
protected virtual bool IsMatch( string objectName, string mappedName )
{
return PatternMatchUtils.SimpleMatch( mappedName, objectName );
}
/// <summary>
/// Convenience method that may be used by derived classes. Iterates over the list of <paramref name="objectNamePatterns"/> to match <paramref name="objectName"/> against.
/// </summary>
/// <param name="objType">the object's type. Must not be <c>null</c>.</param>
/// <param name="objectName">the name of the object Must not be <c>null</c>.</param>
/// <param name="objectNamePatterns">the list of patterns, that <paramref name="objectName"/> shall be matched against. Must not be <c>null</c>.</param>
/// <returns>
/// If <paramref name="objectNamePatterns"/> is <c>null</c>, will always return <c>true</c>, otherwise
/// if <paramref name="objectName"/> matches any of the patterns specified in <paramref name="objectNamePatterns"/>.
/// </returns>
protected bool IsObjectNameMatch(Type objType, string objectName, IList objectNamePatterns)
{
AssertUtils.ArgumentNotNull(objType, "objType");
AssertUtils.ArgumentNotNull(objectName, "objectName" );
AssertUtils.ArgumentNotNull(objectNamePatterns, "objectNamePatterns");
for (int i = 0; i < objectNamePatterns.Count; i++)
{
string mappedName = (string)objectNamePatterns[i];
if (typeof(IFactoryObject).IsAssignableFrom(objType))
{
if (!objectName.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix))
{
continue;
}
mappedName = mappedName.Substring(ObjectFactoryUtils.FactoryObjectPrefix.Length);
}
if (IsMatch(objectName, mappedName))
{
return true;
}
}
return false;
return objectNames;
}
}
/// <summary>
/// Identify as object to proxy if the object name is in the configured list of names.
/// </summary>
protected override bool IsEligibleForProxying(Type targetType, string targetName)
{
bool shallProxy = IsObjectNameMatch(targetType, targetName, this.ObjectNames);
return shallProxy;
}
/// <summary>
/// Return if the given object name matches the mapped name.
/// </summary>
/// <remarks>
/// <p>
/// The default implementation checks for "xxx*", "*xxx" and "*xxx*" matches,
/// as well as direct equality. Can be overridden in subclasses.
/// </p>
/// </remarks>
/// <param name="objectName">the object name to check</param>
/// <param name="mappedName">the name in the configured list of names</param>
/// <returns>if the names match</returns>
protected virtual bool IsMatch(string objectName, string mappedName)
{
return PatternMatchUtils.SimpleMatch(mappedName, objectName);
}
/// <summary>
/// Convenience method that may be used by derived classes. Iterates over the list of <paramref name="objectNamePatterns"/> to match <paramref name="objectName"/> against.
/// </summary>
/// <param name="objType">the object's type. Must not be <c>null</c>.</param>
/// <param name="objectName">the name of the object Must not be <c>null</c>.</param>
/// <param name="objectNamePatterns">the list of patterns, that <paramref name="objectName"/> shall be matched against. Must not be <c>null</c>.</param>
/// <returns>
/// If <paramref name="objectNamePatterns"/> is <c>null</c>, will always return <c>true</c>, otherwise
/// if <paramref name="objectName"/> matches any of the patterns specified in <paramref name="objectNamePatterns"/>.
/// </returns>
protected bool IsObjectNameMatch(Type objType, string objectName, IList objectNamePatterns)
{
AssertUtils.ArgumentNotNull(objType, "objType");
AssertUtils.ArgumentNotNull(objectName, "objectName");
AssertUtils.ArgumentNotNull(objectNamePatterns, "objectNamePatterns");
for (int i = 0; i < objectNamePatterns.Count; i++)
{
string mappedName = (string) objectNamePatterns[i];
if (typeof(IFactoryObject).IsAssignableFrom(objType))
{
if (!objectName.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix))
{
continue;
}
mappedName = mappedName.Substring(ObjectFactoryUtils.FactoryObjectPrefix.Length);
}
if (IsMatch(objectName, mappedName))
{
return true;
}
}
return false;
}
}

View File

@@ -24,34 +24,33 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// This AutoProxyCreator only proxies objects matching the specified <see cref="IPointcut"/>.
/// </summary>
/// <author>Erich Eichinger</author>
public class PointcutFilteringAutoProxyCreator : AbstractFilteringAutoProxyCreator
{
private IPointcut _pointcut;
/// <summary>
/// This AutoProxyCreator only proxies objects matching the specified <see cref="IPointcut"/>.
/// Set the pointcut used to filter objects that should automatically get wrapped with proxies.
/// </summary>
/// <author>Erich Eichinger</author>
public class PointcutFilteringAutoProxyCreator : AbstractFilteringAutoProxyCreator
public IPointcut Pointcut
{
private IPointcut _pointcut;
set { _pointcut = value; }
get { return _pointcut; }
}
/// <summary>
/// Set the pointcut used to filter objects that should automatically get wrapped with proxies.
/// </summary>
public IPointcut Pointcut
{
set { _pointcut = value; }
get { return _pointcut; }
}
/// <summary>
/// Determines, whether the given object shall be proxied.
/// </summary>
protected override bool IsEligibleForProxying(Type targetType, string targetName)
{
AssertUtils.ArgumentNotNull(_pointcut, "Pointcut");
/// <summary>
/// Determines, whether the given object shall be proxied.
/// </summary>
protected override bool IsEligibleForProxying( Type targetType, string targetName )
{
AssertUtils.ArgumentNotNull(_pointcut, "Pointcut");
bool shallProxy = AopUtils.CanApply( _pointcut, targetType, null );
return shallProxy;
}
bool shallProxy = AopUtils.CanApply(_pointcut, targetType, null);
return shallProxy;
}
}

View File

@@ -27,80 +27,79 @@ using Spring.Objects.Factory.Support;
#endregion
namespace Spring.Aop.Framework.AutoProxy.Target
namespace Spring.Aop.Framework.AutoProxy.Target;
/// <summary>
/// Summary description for AbstractPrototypeBasedTargetSourceCreator.
/// </summary>
public abstract class AbstractPrototypeTargetSourceCreator : ITargetSourceCreator
{
/// <summary>
/// Summary description for AbstractPrototypeBasedTargetSourceCreator.
/// The logger
/// </summary>
public abstract class AbstractPrototypeTargetSourceCreator : ITargetSourceCreator
protected readonly ILogger logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#region ITargetSourceCreator Members
/// <summary>
/// Create a special TargetSource for the given object, if any.
/// </summary>
/// <param name="objectType">the type of the object to create a TargetSource for</param>
/// <param name="name">the name of the object</param>
/// <param name="factory">the containing factory</param>
/// <returns>
/// a special TargetSource or null if this TargetSourceCreator isn't
/// interested in the particular object
/// </returns>
public ITargetSource GetTargetSource(Type objectType, string name, IObjectFactory factory)
{
/// <summary>
/// The logger
/// </summary>
protected readonly ILogger logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#region ITargetSourceCreator Members
/// <summary>
/// Create a special TargetSource for the given object, if any.
/// </summary>
/// <param name="objectType">the type of the object to create a TargetSource for</param>
/// <param name="name">the name of the object</param>
/// <param name="factory">the containing factory</param>
/// <returns>
/// a special TargetSource or null if this TargetSourceCreator isn't
/// interested in the particular object
/// </returns>
public ITargetSource GetTargetSource(Type objectType, string name, IObjectFactory factory)
AbstractPrototypeTargetSource prototypeTargetSource = CreatePrototypeTargetSource(objectType, name, factory);
if (prototypeTargetSource == null)
{
AbstractPrototypeTargetSource prototypeTargetSource = CreatePrototypeTargetSource(objectType, name, factory);
if (prototypeTargetSource == null)
return null;
}
else
{
if (!(factory is IObjectDefinitionRegistry))
{
if (logger.IsEnabled(LogLevel.Warning))
logger.LogWarning("Cannot do autopooling with a IObjectFactory that doesn't implement IObjectDefinitionRegistry");
return null;
}
else
{
if (!(factory is IObjectDefinitionRegistry))
{
if (logger.IsEnabled(LogLevel.Warning))
logger.LogWarning("Cannot do autopooling with a IObjectFactory that doesn't implement IObjectDefinitionRegistry");
return null;
}
IObjectDefinitionRegistry definitionRegistry = (IObjectDefinitionRegistry) factory;
RootObjectDefinition definition = (RootObjectDefinition) definitionRegistry.GetObjectDefinition(name);
if (logger.IsEnabled(LogLevel.Information))
logger.LogInformation("Configuring AbstractPrototypeBasedTargetSource...");
IObjectDefinitionRegistry definitionRegistry = (IObjectDefinitionRegistry) factory;
RootObjectDefinition definition = (RootObjectDefinition) definitionRegistry.GetObjectDefinition(name);
// Infinite cycle will result if we don't use a different factory,
// because a GetObject() call with this objectName will go through the autoproxy
// infrastructure again.
// We to override just this object definition, as it may reference other objects
// and we're happy to take the parent's definition for those.
DefaultListableObjectFactory objectFactory = new DefaultListableObjectFactory(factory);
if (logger.IsEnabled(LogLevel.Information))
logger.LogInformation("Configuring AbstractPrototypeBasedTargetSource...");
// Override the prototype object
objectFactory.RegisterObjectDefinition(name, definition);
// Infinite cycle will result if we don't use a different factory,
// because a GetObject() call with this objectName will go through the autoproxy
// infrastructure again.
// We to override just this object definition, as it may reference other objects
// and we're happy to take the parent's definition for those.
DefaultListableObjectFactory objectFactory = new DefaultListableObjectFactory(factory);
// Complete configuring the PrototypeTargetSource
prototypeTargetSource.TargetObjectName = name;
prototypeTargetSource.ObjectFactory = objectFactory;
// Override the prototype object
objectFactory.RegisterObjectDefinition(name, definition);
return prototypeTargetSource;
}
// Complete configuring the PrototypeTargetSource
prototypeTargetSource.TargetObjectName = name;
prototypeTargetSource.ObjectFactory = objectFactory;
return prototypeTargetSource;
}
#endregion
/// <summary>
/// Creates the prototype target source.
/// </summary>
/// <param name="objectType">The type of the object to create a target source for.</param>
/// <param name="name">The name.</param>
/// <param name="factory">The factory.</param>
/// <returns></returns>
protected abstract AbstractPrototypeTargetSource CreatePrototypeTargetSource(Type objectType, string name,
IObjectFactory factory);
}
#endregion
/// <summary>
/// Creates the prototype target source.
/// </summary>
/// <param name="objectType">The type of the object to create a target source for.</param>
/// <param name="name">The name.</param>
/// <param name="factory">The factory.</param>
/// <returns></returns>
protected abstract AbstractPrototypeTargetSource CreatePrototypeTargetSource(Type objectType, string name,
IObjectFactory factory);
}

View File

@@ -25,52 +25,52 @@ using Spring.Util;
#endregion
namespace Spring.Aop.Framework.AutoProxy
namespace Spring.Aop.Framework.AutoProxy;
/// <summary>
/// AutoProxyCreator, that identifies objects to proxy by matching their <see cref="Type.FullName"/> against a list of patterns.
/// </summary>
/// <author>Erich Eichinger</author>
public class TypeNameAutoProxyCreator : AbstractFilteringAutoProxyCreator
{
/// <summary>
/// AutoProxyCreator, that identifies objects to proxy by matching their <see cref="Type.FullName"/> against a list of patterns.
/// </summary>
/// <author>Erich Eichinger</author>
public class TypeNameAutoProxyCreator : AbstractFilteringAutoProxyCreator
private TypeNameTypeFilter _typeNameFilter = null;
///<summary>
/// The list of patterns to match <see cref="Type.FullName"/> against. For pattern syntax, see <see cref="TypeNameTypeFilter"/>
///</summary>
public string[] TypeNames
{
private TypeNameTypeFilter _typeNameFilter = null;
///<summary>
/// The list of patterns to match <see cref="Type.FullName"/> against. For pattern syntax, see <see cref="TypeNameTypeFilter"/>
///</summary>
public string[] TypeNames
get
{
get
if (_typeNameFilter != null)
{
if (_typeNameFilter != null)
{
return _typeNameFilter.TypeNamePatterns;
}
return null;
}
set
{
AssertUtils.ArgumentNotNull(value, "TypeNames");
_typeNameFilter = new TypeNameTypeFilter(value);
return _typeNameFilter.TypeNamePatterns;
}
return null;
}
/// <summary>
/// Decide, whether the given object is eligible for proxying.
/// </summary>
/// <remarks>
/// Override this method to allow or reject proxying for the given object.
/// </remarks>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
/// <seealso cref="AbstractAutoProxyCreator.ShouldSkip"/>
/// <returns>whether the given object shall be proxied.</returns>
protected override bool IsEligibleForProxying(Type targetType, string targetName)
set
{
AssertUtils.ArgumentNotNull(_typeNameFilter, "TypeNames");
bool shallProxy = _typeNameFilter.Matches(targetType);
return shallProxy;
AssertUtils.ArgumentNotNull(value, "TypeNames");
_typeNameFilter = new TypeNameTypeFilter(value);
}
}
/// <summary>
/// Decide, whether the given object is eligible for proxying.
/// </summary>
/// <remarks>
/// Override this method to allow or reject proxying for the given object.
/// </remarks>
/// <param name="targetType">the object's type</param>
/// <param name="targetName">the name of the object</param>
/// <seealso cref="AbstractAutoProxyCreator.ShouldSkip"/>
/// <returns>whether the given object shall be proxied.</returns>
protected override bool IsEligibleForProxying(Type targetType, string targetName)
{
AssertUtils.ArgumentNotNull(_typeNameFilter, "TypeNames");
bool shallProxy = _typeNameFilter.Matches(targetType);
return shallProxy;
}
}

View File

@@ -22,115 +22,113 @@
using System.Collections;
using System.Reflection;
using Spring.Util;
using Spring.Reflection.Dynamic;
using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Invokes a target method using dynamic reflection.
/// </summary>
/// <seealso cref="Spring.Reflection.Dynamic.DynamicMethod"/>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
[Serializable]
public class DynamicMethodInvocation : AbstractMethodInvocation
{
/// <summary>
/// Invokes a target method using dynamic reflection.
/// The method invocation that is to be invoked on the proxy.
/// </summary>
/// <seealso cref="Spring.Reflection.Dynamic.DynamicMethod"/>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
[Serializable]
public class DynamicMethodInvocation : AbstractMethodInvocation
private MethodInfo proxyMethod;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> class.
/// </summary>
/// <param name="proxy">The AOP proxy.</param>
/// <param name="target">The target object.</param>
/// <param name="method">The target method proxied.</param>
/// <param name="proxyMethod">The method to invoke on proxy.</param>
/// <param name="arguments">The target method's arguments.</param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.</param>
/// <param name="interceptors">
/// The list of interceptors that are to be applied. May be
/// <cref lang="null"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If any of the <paramref name="target"/> or <paramref name="method"/>
/// parameters is <see langword="null"/>.
/// </exception>
public DynamicMethodInvocation(
object proxy, object target, MethodInfo method, MethodInfo proxyMethod,
object[] arguments, Type targetType, IList interceptors)
: base(proxy, target, method, arguments, targetType, interceptors)
{
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
private MethodInfo proxyMethod;
this.proxyMethod = proxyMethod;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> class.
/// </summary>
/// <param name="proxy">The AOP proxy.</param>
/// <param name="target">The target object.</param>
/// <param name="method">The target method proxied.</param>
/// <param name="proxyMethod">The method to invoke on proxy.</param>
/// <param name="arguments">The target method's arguments.</param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.</param>
/// <param name="interceptors">
/// The list of interceptors that are to be applied. May be
/// <cref lang="null"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If any of the <paramref name="target"/> or <paramref name="method"/>
/// parameters is <see langword="null"/>.
/// </exception>
public DynamicMethodInvocation(
object proxy, object target, MethodInfo method, MethodInfo proxyMethod,
object[] arguments, Type targetType, IList interceptors)
: base(proxy, target, method, arguments, targetType, interceptors)
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
protected MethodInfo ProxyMethod
{
get { return proxyMethod; }
set { proxyMethod = value; }
}
/// <summary>
/// Invokes the joinpoint using dynamic reflection.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override this to use custom invocation.
/// </p>
/// </remarks>
/// <returns>
/// The return value of the invocation of the joinpoint.
/// </returns>
/// <exception cref="System.Exception">
/// If invoking the joinpoint resulted in an exception.
/// </exception>
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint"/>
protected override object InvokeJoinpoint()
{
MethodInfo targetMethodInfo = this.proxyMethod ?? Method;
IDynamicMethod targetMethod = new SafeMethod(targetMethodInfo);
try
{
this.proxyMethod = proxyMethod;
AssertUtils.Understands(Target, "target", targetMethodInfo);
return targetMethod.Invoke(Target, Arguments);
}
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
protected MethodInfo ProxyMethod
// Only happens if fallback to standard reflection.
catch (TargetInvocationException ex)
{
get { return proxyMethod; }
set { proxyMethod = value; }
}
/// <summary>
/// Invokes the joinpoint using dynamic reflection.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override this to use custom invocation.
/// </p>
/// </remarks>
/// <returns>
/// The return value of the invocation of the joinpoint.
/// </returns>
/// <exception cref="System.Exception">
/// If invoking the joinpoint resulted in an exception.
/// </exception>
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint"/>
protected override object InvokeJoinpoint()
{
MethodInfo targetMethodInfo = this.proxyMethod ?? Method;
IDynamicMethod targetMethod = new SafeMethod(targetMethodInfo);
try
{
AssertUtils.Understands(Target, "target", targetMethodInfo);
return targetMethod.Invoke(Target, Arguments);
}
// Only happens if fallback to standard reflection.
catch (TargetInvocationException ex)
{
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
}
}
/// <summary>
/// Creates a new <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> instance
/// from the specified <see cref="AopAlliance.Intercept.IMethodInvocation"/> and
/// increments the interceptor index.
/// </summary>
/// <param name="invocation">
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
/// </param>
/// <returns>
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
/// </returns>
protected override IMethodInvocation PrepareMethodInvocationForProceed(IMethodInvocation invocation)
{
var rmi = new DynamicMethodInvocation(Proxy, Target, Method, ProxyMethod, Arguments, TargetType, Interceptors);
rmi.CurrentInterceptorIndex = CurrentInterceptorIndex + 1;
return rmi;
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
}
}
/// <summary>
/// Creates a new <see cref="Spring.Aop.Framework.DynamicMethodInvocation"/> instance
/// from the specified <see cref="AopAlliance.Intercept.IMethodInvocation"/> and
/// increments the interceptor index.
/// </summary>
/// <param name="invocation">
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
/// </param>
/// <returns>
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
/// </returns>
protected override IMethodInvocation PrepareMethodInvocationForProceed(IMethodInvocation invocation)
{
var rmi = new DynamicMethodInvocation(Proxy, Target, Method, ProxyMethod, Arguments, TargetType, Interceptors);
rmi.CurrentInterceptorIndex = CurrentInterceptorIndex + 1;
return rmi;
}
}

View File

@@ -1,88 +1,88 @@
using Spring.Aop.Support;
using Spring.Aop.Target;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// A reusable base implementation of <see cref="IAopProxyFactory"/>, providing
/// some useful default implementations
/// </summary>
/// <author>Erich Eichinger</author>
[Serializable]
public abstract class AbstractAopProxyFactory : IAopProxyFactory
{
/// <summary>
/// A reusable base implementation of <see cref="IAopProxyFactory"/>, providing
/// some useful default implementations
/// Creates an <see cref="Spring.Aop.Framework.IAopProxy"/> for the
/// supplied <paramref name="advisedSupport"/> configuration.
/// </summary>
/// <author>Erich Eichinger</author>
[Serializable]
public abstract class AbstractAopProxyFactory : IAopProxyFactory
/// <param name="advisedSupport">The AOP configuration.</param>
/// <returns>An <see cref="Spring.Aop.Framework.IAopProxy"/>.</returns>
/// <exception cref="AopConfigException">
/// If the supplied <paramref name="advisedSupport"/> configuration is
/// invalid.
/// </exception>
/// <seealso cref="Spring.Aop.Framework.IAopProxyFactory.CreateAopProxy"/>
public IAopProxy CreateAopProxy(AdvisedSupport advisedSupport)
{
/// <summary>
/// Creates an <see cref="Spring.Aop.Framework.IAopProxy"/> for the
/// supplied <paramref name="advisedSupport"/> configuration.
/// </summary>
/// <param name="advisedSupport">The AOP configuration.</param>
/// <returns>An <see cref="Spring.Aop.Framework.IAopProxy"/>.</returns>
/// <exception cref="AopConfigException">
/// If the supplied <paramref name="advisedSupport"/> configuration is
/// invalid.
/// </exception>
/// <seealso cref="Spring.Aop.Framework.IAopProxyFactory.CreateAopProxy"/>
public IAopProxy CreateAopProxy(AdvisedSupport advisedSupport)
if (advisedSupport == null)
{
if (advisedSupport == null)
{
throw new AopConfigException("Cannot create IAopProxy with null ProxyConfig");
}
if (advisedSupport.Advisors.Count == 0 && advisedSupport.TargetSource == EmptyTargetSource.Empty)
{
throw new AopConfigException("Cannot create IAopProxy with no advisors and no target source");
}
EliminateDuplicateAdvisors(advisedSupport);
return DoCreateAopProxyInstance(advisedSupport);
throw new AopConfigException("Cannot create IAopProxy with null ProxyConfig");
}
/// <summary>
/// Actually creates the proxy instance based on the supplied <see cref="AdvisedSupport"/>.
/// </summary>
/// <returns>the proxy instance described by <paramref name="advisedSupport"/>. Must not be <c>null</c></returns>
protected abstract IAopProxy DoCreateAopProxyInstance(AdvisedSupport advisedSupport);
/// <summary>
/// If possible, checks for advisor duplicates on the supplied <paramref name="advisedSupport"/> and
/// eliminates them.
/// </summary>
protected virtual void EliminateDuplicateAdvisors(AdvisedSupport advisedSupport)
if (advisedSupport.Advisors.Count == 0 && advisedSupport.TargetSource == EmptyTargetSource.Empty)
{
if (advisedSupport.TargetSource is SingletonTargetSource
&& IsAopProxyType(advisedSupport.TargetSource))
throw new AopConfigException("Cannot create IAopProxy with no advisors and no target source");
}
EliminateDuplicateAdvisors(advisedSupport);
return DoCreateAopProxyInstance(advisedSupport);
}
/// <summary>
/// Actually creates the proxy instance based on the supplied <see cref="AdvisedSupport"/>.
/// </summary>
/// <returns>the proxy instance described by <paramref name="advisedSupport"/>. Must not be <c>null</c></returns>
protected abstract IAopProxy DoCreateAopProxyInstance(AdvisedSupport advisedSupport);
/// <summary>
/// If possible, checks for advisor duplicates on the supplied <paramref name="advisedSupport"/> and
/// eliminates them.
/// </summary>
protected virtual void EliminateDuplicateAdvisors(AdvisedSupport advisedSupport)
{
if (advisedSupport.TargetSource is SingletonTargetSource
&& IsAopProxyType(advisedSupport.TargetSource))
{
IAdvised innerProxy = (IAdvised) advisedSupport.TargetSource.GetTarget();
// eliminate duplicate advisors
List<IAdvisor> thisAdvisors = new List<IAdvisor>(advisedSupport.Advisors);
foreach (IAdvisor innerAdvisor in innerProxy.Advisors)
{
IAdvised innerProxy = (IAdvised)advisedSupport.TargetSource.GetTarget();
// eliminate duplicate advisors
List<IAdvisor> thisAdvisors = new List<IAdvisor>(advisedSupport.Advisors);
foreach (IAdvisor innerAdvisor in innerProxy.Advisors)
foreach (IAdvisor thisAdvisor in thisAdvisors)
{
foreach (IAdvisor thisAdvisor in thisAdvisors)
if (ReferenceEquals(thisAdvisor, innerAdvisor)
|| (thisAdvisor.GetType() == typeof(DefaultPointcutAdvisor)
&& thisAdvisor.Equals(innerAdvisor)
)
)
{
if (ReferenceEquals(thisAdvisor, innerAdvisor)
|| (thisAdvisor.GetType() == typeof(DefaultPointcutAdvisor)
&& thisAdvisor.Equals(innerAdvisor)
)
)
{
advisedSupport.RemoveAdvisor(thisAdvisor);
}
advisedSupport.RemoveAdvisor(thisAdvisor);
}
}
// elimination of duplicate introductions is not necessary
// since they do not propagate to nested proxy anyway
}
}
/// <summary>
/// Checks, if the given <paramref name="targetSource"/> holds a proxy generated by this factory.
/// </summary>
/// <returns></returns>
protected virtual bool IsAopProxyType(ITargetSource targetSource)
{
return AopUtils.IsAopProxyType(targetSource.TargetType);
// elimination of duplicate introductions is not necessary
// since they do not propagate to nested proxy anyway
}
}
/// <summary>
/// Checks, if the given <paramref name="targetSource"/> holds a proxy generated by this factory.
/// </summary>
/// <returns></returns>
protected virtual bool IsAopProxyType(ITargetSource targetSource)
{
return AopUtils.IsAopProxyType(targetSource.TargetType);
}
}

View File

@@ -22,73 +22,69 @@
using System.Collections;
using System.Reflection.Emit;
using Spring.Proxy;
#endregion
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Base class for proxy builders that can be used
/// to create an AOP proxy for any object.
/// </summary>
/// <author>Bruno Baia</author>
public abstract class AbstractAopProxyTypeBuilder :
AbstractProxyTypeBuilder, IAopProxyTypeGenerator
{
/// <summary>
/// Base class for proxy builders that can be used
/// to create an AOP proxy for any object.
/// </summary>
/// <author>Bruno Baia</author>
public abstract class AbstractAopProxyTypeBuilder :
AbstractProxyTypeBuilder, IAopProxyTypeGenerator
#region IProxyTypeGenerator Members
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushTarget(ILGenerator il)
{
#region IProxyTypeGenerator Members
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushTarget(ILGenerator il)
{
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
il.EmitCall(OpCodes.Callvirt, References.GetTargetMethod, null);
}
#endregion
#region IAopProxyTypeGenerator Members
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public abstract void PushAdvisedProxy(ILGenerator il);
#endregion
#region Protected Methods
/// <inheritdoc />
protected override IList GetTypeAttributes(Type type)
{
IList attrs = base.GetTypeAttributes(type);
int i = 0;
while (i < attrs.Count)
{
if (IsAttributeMatchingType(attrs[i], typeof(SerializableAttribute)))
{
attrs.RemoveAt(i);
}
else
{
i++;
}
}
return attrs;
}
#endregion
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
il.EmitCall(OpCodes.Callvirt, References.GetTargetMethod, null);
}
#endregion
#region IAopProxyTypeGenerator Members
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public abstract void PushAdvisedProxy(ILGenerator il);
#endregion
#region Protected Methods
/// <inheritdoc />
protected override IList GetTypeAttributes(Type type)
{
IList attrs = base.GetTypeAttributes(type);
int i = 0;
while (i < attrs.Count)
{
if (IsAttributeMatchingType(attrs[i], typeof(SerializableAttribute)))
{
attrs.RemoveAt(i);
}
else
{
i++;
}
}
return attrs;
}
#endregion
}

View File

@@ -24,368 +24,369 @@ using AopAlliance.Aop;
using AopAlliance.Intercept;
using Spring.Util;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Represents the AOP configuration data built-in with the proxy.
/// </summary>
/// <author>Bruno Baia</author>
[Serializable]
public class AdvisedProxy : IAdvised, ISerializable
{
/// <summary>
/// Represents the AOP configuration data built-in with the proxy.
/// Should we use dynamic reflection for method invocation ?
/// </summary>
/// <author>Bruno Baia</author>
[Serializable]
public class AdvisedProxy : IAdvised, ISerializable
public static bool UseDynamicReflection;
/// <summary>
/// Optimization fields
/// </summary>
private static IList<object> EmptyList = new ReadOnlyCollection<object>(new object[0]);
/// <summary>
/// IAdvised delegate
/// </summary>
public IAdvised m_advised;
/// <summary>
/// Array of introduction delegates
/// </summary>
public IAdvice[] m_introductions;
/// <summary>
/// Target source
/// </summary>
public ITargetSource m_targetSource;
/// <summary>
/// Type of target object.
/// </summary>
public Type m_targetType;
/// <summary>
/// Creates a new instance of the <see cref="AdvisedProxy"/> class.
/// </summary>
static AdvisedProxy()
{
/// <summary>
/// Should we use dynamic reflection for method invocation ?
/// </summary>
public static bool UseDynamicReflection;
string appSettingsKey = typeof(AdvisedProxy).FullName + ".UseDynamicReflection";
NameValueCollection appSettings =
ConfigurationUtils.GetSection("appSettings") as NameValueCollection;
/// <summary>
/// Optimization fields
/// </summary>
private static IList<object> EmptyList = new ReadOnlyCollection<object>(new object[0]);
/// <summary>
/// IAdvised delegate
/// </summary>
public IAdvised m_advised;
/// <summary>
/// Array of introduction delegates
/// </summary>
public IAdvice[] m_introductions;
/// <summary>
/// Target source
/// </summary>
public ITargetSource m_targetSource;
/// <summary>
/// Type of target object.
/// </summary>
public Type m_targetType;
/// <summary>
/// Creates a new instance of the <see cref="AdvisedProxy"/> class.
/// </summary>
static AdvisedProxy()
if (appSettings != null && StringUtils.HasLength(appSettings[appSettingsKey]))
{
string appSettingsKey = typeof(AdvisedProxy).FullName + ".UseDynamicReflection";
NameValueCollection appSettings =
ConfigurationUtils.GetSection("appSettings") as NameValueCollection;
if (appSettings != null && StringUtils.HasLength(appSettings[appSettingsKey]))
{
UseDynamicReflection = bool.Parse(appSettings[appSettingsKey]);
}
else
{
UseDynamicReflection = true;
}
UseDynamicReflection = bool.Parse(appSettings[appSettingsKey]);
}
/// <summary>
/// Creates a new instance of the <see cref="AdvisedProxy"/> class.
/// </summary>
public AdvisedProxy()
{ }
/// <summary>
/// Creates a new instance of the <see cref="AdvisedProxy"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
protected AdvisedProxy(IAdvised advised)
else
{
m_advised = advised;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
/// <param name="proxy">The proxy.</param>
public AdvisedProxy(IAdvised advised, IAopProxy proxy)
{
Initialize(advised, proxy);
}
/// <summary>
/// Deserialization constructor.
/// </summary>
/// <param name="info">Serialization data.</param>
/// <param name="context">Serialization context.</param>
protected AdvisedProxy(SerializationInfo info, StreamingContext context)
{
m_advised = (IAdvised)info.GetValue("advised", typeof(IAdvised));
m_introductions = (IAdvice[])info.GetValue("introductions", typeof(IAdvice[]));
m_targetSource = (ITargetSource)info.GetValue("targetSource", typeof(ITargetSource));
var type = info.GetString("targetType");
m_targetType = type != null ? Type.GetType(type) : null;
}
/// <summary>
/// Serializes this instance.
/// </summary>
/// <param name="info">Serialization data.</param>
/// <param name="context">Serialization context.</param>
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("advised", m_advised);
info.AddValue("introductions", m_introductions);
info.AddValue("targetSource", m_targetSource);
info.AddValue("targetType", m_targetType?.AssemblyQualifiedName);
}
/// <summary>
/// Initialization method.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
/// <param name="proxy">
/// The current <see cref="Spring.Aop.Framework.IAopProxy"/> implementation.
/// </param>
protected void Initialize(IAdvised advised, IAopProxy proxy)
{
this.m_advised = advised;
this.m_targetSource = advised.TargetSource;
this.m_targetType = advised.TargetSource.TargetType;
// initialize introduction advice
this.m_introductions = new IAdvice[advised.Introductions.Count];
for (int i = 0; i < advised.Introductions.Count; i++)
{
this.m_introductions[i] = advised.Introductions[i].Advice;
// set target proxy on introduction instance if it implements ITargetAware
if (this.m_introductions[i] is ITargetAware)
{
((ITargetAware)this.m_introductions[i]).TargetProxy = proxy;
}
}
}
/// <summary>
/// Invokes intercepted methods using reflection
/// </summary>
/// <param name="proxy">proxy object</param>
/// <param name="target">target object to invoke method on</param>
/// <param name="targetType">target type</param>
/// <param name="targetMethod">taget method to invoke</param>
/// <param name="proxyMethod">The method to invoke on proxy.</param>
/// <param name="args">method arguments</param>
/// <param name="interceptors">interceptor chain</param>
/// <returns>value returned by invocation chain</returns>
public object Invoke(object proxy, object target, Type targetType,
MethodInfo targetMethod, MethodInfo proxyMethod, object[] args, IList interceptors)
{
IMethodInvocation invocation = null;
if (UseDynamicReflection)
{
invocation = new DynamicMethodInvocation(
proxy, target, targetMethod, proxyMethod, args, targetType, interceptors);
}
else
{
invocation = new ReflectiveMethodInvocation(
proxy, target, targetMethod, proxyMethod, args, targetType, interceptors);
}
return invocation.Proceed();
}
/// <summary>
/// Returns a list of method interceptors
/// </summary>
/// <param name="targetType">target type</param>
/// <param name="method">target method</param>
/// <returns>list of inteceptors for the specified method</returns>
public IList<object> GetInterceptors(Type targetType, MethodInfo method)
{
if (m_advised.Advisors.Count == 0)
{
return EmptyList;
}
else
{
return m_advised.AdvisorChainFactory.GetInterceptors(m_advised, this, method, targetType);
}
}
bool IAdvised.ExposeProxy
{
get { return m_advised.ExposeProxy; }
}
IAdvisorChainFactory IAdvised.AdvisorChainFactory
{
get { return m_advised.AdvisorChainFactory; }
}
bool IAdvised.ProxyTargetType
{
get { return m_advised.ProxyTargetType; }
}
bool IAdvised.ProxyTargetAttributes
{
get { return m_advised.ProxyTargetAttributes; }
}
IList<IAdvisor> IAdvised.Advisors
{
get { return m_advised.Advisors; }
}
IList<IIntroductionAdvisor> IAdvised.Introductions
{
get { return m_advised.Introductions; }
}
IList<Type> IAdvised.Interfaces
{
get { return m_advised.Interfaces; }
}
IDictionary<Type, object> IAdvised.InterfaceMap
{
get { return m_advised.InterfaceMap; }
}
bool IAdvised.IsFrozen
{
get { return m_advised.IsFrozen; }
}
ITargetSource IAdvised.TargetSource
{
get { return m_advised.TargetSource; }
}
bool IAdvised.IsSerializable
{
get { return m_advised.IsSerializable; }
}
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the end (or tail)
/// of the advice (interceptor) chain.
/// </summary>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(int,IAdvice)"/>
public void AddAdvice(IAdvice advice)
{
this.m_advised.AddAdvice(advice);
}
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the supplied
/// <paramref name="position"/> in the advice (interceptor) chain.
/// </summary>
/// <param name="position">
/// The zero (0) indexed position (from the head) at which the
/// supplied <paramref name="advice"/> is to be inserted into the
/// advice (interceptor) chain.
/// </param>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(IAdvice)"/>
public void AddAdvice(int position, IAdvice advice)
{
this.m_advised.AddAdvice(position, advice);
}
bool IAdvised.IsInterfaceProxied(Type intf)
{
return m_advised.IsInterfaceProxied(intf);
}
void IAdvised.AddAdvisors(IAdvisors advisors)
{
m_advised.AddAdvisors(advisors);
}
void IAdvised.AddAdvisor(IAdvisor advisor)
{
m_advised.AddAdvisor(advisor);
}
void IAdvised.AddAdvisor(int pos, IAdvisor advisor)
{
m_advised.AddAdvisor(pos, advisor);
}
void IAdvised.AddIntroduction(IIntroductionAdvisor advisor)
{
m_advised.AddIntroduction(advisor);
}
void IAdvised.AddIntroduction(int pos, IIntroductionAdvisor advisor)
{
m_advised.AddIntroduction(pos, advisor);
}
int IAdvised.IndexOf(IAdvisor advisor)
{
return m_advised.IndexOf(advisor);
}
int IAdvised.IndexOf(IIntroductionAdvisor advisor)
{
return m_advised.IndexOf(advisor);
}
bool IAdvised.RemoveAdvisor(IAdvisor advisor)
{
return m_advised.RemoveAdvisor(advisor);
}
void IAdvised.RemoveAdvisor(int index)
{
m_advised.RemoveAdvisor(index);
}
bool IAdvised.RemoveAdvice(IAdvice advice)
{
return m_advised.RemoveAdvice(advice);
}
bool IAdvised.RemoveIntroduction(IIntroductionAdvisor advisor)
{
return m_advised.RemoveIntroduction(advisor);
}
void IAdvised.RemoveIntroduction(int index)
{
m_advised.RemoveIntroduction(index);
}
void IAdvised.ReplaceIntroduction(int index, IIntroductionAdvisor advisor)
{
m_advised.ReplaceIntroduction(index, advisor);
}
bool IAdvised.ReplaceAdvisor(IAdvisor a, IAdvisor b)
{
return m_advised.ReplaceAdvisor(a, b);
}
string IAdvised.ToProxyConfigString()
{
return m_advised.ToProxyConfigString();
}
/// <summary>
/// Gets the target type behind the implementing object.
/// Ttypically a proxy configuration or an actual proxy.
/// </summary>
/// <value>The type of the target or null if not known.</value>
public Type TargetType
{
get { return m_targetType; }
UseDynamicReflection = true;
}
}
/// <summary>
/// Creates a new instance of the <see cref="AdvisedProxy"/> class.
/// </summary>
public AdvisedProxy()
{
}
/// <summary>
/// Creates a new instance of the <see cref="AdvisedProxy"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
protected AdvisedProxy(IAdvised advised)
{
m_advised = advised;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
/// <param name="proxy">The proxy.</param>
public AdvisedProxy(IAdvised advised, IAopProxy proxy)
{
Initialize(advised, proxy);
}
/// <summary>
/// Deserialization constructor.
/// </summary>
/// <param name="info">Serialization data.</param>
/// <param name="context">Serialization context.</param>
protected AdvisedProxy(SerializationInfo info, StreamingContext context)
{
m_advised = (IAdvised) info.GetValue("advised", typeof(IAdvised));
m_introductions = (IAdvice[]) info.GetValue("introductions", typeof(IAdvice[]));
m_targetSource = (ITargetSource) info.GetValue("targetSource", typeof(ITargetSource));
var type = info.GetString("targetType");
m_targetType = type != null ? Type.GetType(type) : null;
}
/// <summary>
/// Serializes this instance.
/// </summary>
/// <param name="info">Serialization data.</param>
/// <param name="context">Serialization context.</param>
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter = true)]
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("advised", m_advised);
info.AddValue("introductions", m_introductions);
info.AddValue("targetSource", m_targetSource);
info.AddValue("targetType", m_targetType?.AssemblyQualifiedName);
}
/// <summary>
/// Initialization method.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
/// <param name="proxy">
/// The current <see cref="Spring.Aop.Framework.IAopProxy"/> implementation.
/// </param>
protected void Initialize(IAdvised advised, IAopProxy proxy)
{
this.m_advised = advised;
this.m_targetSource = advised.TargetSource;
this.m_targetType = advised.TargetSource.TargetType;
// initialize introduction advice
this.m_introductions = new IAdvice[advised.Introductions.Count];
for (int i = 0; i < advised.Introductions.Count; i++)
{
this.m_introductions[i] = advised.Introductions[i].Advice;
// set target proxy on introduction instance if it implements ITargetAware
if (this.m_introductions[i] is ITargetAware)
{
((ITargetAware) this.m_introductions[i]).TargetProxy = proxy;
}
}
}
/// <summary>
/// Invokes intercepted methods using reflection
/// </summary>
/// <param name="proxy">proxy object</param>
/// <param name="target">target object to invoke method on</param>
/// <param name="targetType">target type</param>
/// <param name="targetMethod">taget method to invoke</param>
/// <param name="proxyMethod">The method to invoke on proxy.</param>
/// <param name="args">method arguments</param>
/// <param name="interceptors">interceptor chain</param>
/// <returns>value returned by invocation chain</returns>
public object Invoke(object proxy, object target, Type targetType,
MethodInfo targetMethod, MethodInfo proxyMethod, object[] args, IList interceptors)
{
IMethodInvocation invocation = null;
if (UseDynamicReflection)
{
invocation = new DynamicMethodInvocation(
proxy, target, targetMethod, proxyMethod, args, targetType, interceptors);
}
else
{
invocation = new ReflectiveMethodInvocation(
proxy, target, targetMethod, proxyMethod, args, targetType, interceptors);
}
return invocation.Proceed();
}
/// <summary>
/// Returns a list of method interceptors
/// </summary>
/// <param name="targetType">target type</param>
/// <param name="method">target method</param>
/// <returns>list of inteceptors for the specified method</returns>
public IList<object> GetInterceptors(Type targetType, MethodInfo method)
{
if (m_advised.Advisors.Count == 0)
{
return EmptyList;
}
else
{
return m_advised.AdvisorChainFactory.GetInterceptors(m_advised, this, method, targetType);
}
}
bool IAdvised.ExposeProxy
{
get { return m_advised.ExposeProxy; }
}
IAdvisorChainFactory IAdvised.AdvisorChainFactory
{
get { return m_advised.AdvisorChainFactory; }
}
bool IAdvised.ProxyTargetType
{
get { return m_advised.ProxyTargetType; }
}
bool IAdvised.ProxyTargetAttributes
{
get { return m_advised.ProxyTargetAttributes; }
}
IList<IAdvisor> IAdvised.Advisors
{
get { return m_advised.Advisors; }
}
IList<IIntroductionAdvisor> IAdvised.Introductions
{
get { return m_advised.Introductions; }
}
IList<Type> IAdvised.Interfaces
{
get { return m_advised.Interfaces; }
}
IDictionary<Type, object> IAdvised.InterfaceMap
{
get { return m_advised.InterfaceMap; }
}
bool IAdvised.IsFrozen
{
get { return m_advised.IsFrozen; }
}
ITargetSource IAdvised.TargetSource
{
get { return m_advised.TargetSource; }
}
bool IAdvised.IsSerializable
{
get { return m_advised.IsSerializable; }
}
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the end (or tail)
/// of the advice (interceptor) chain.
/// </summary>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(int,IAdvice)"/>
public void AddAdvice(IAdvice advice)
{
this.m_advised.AddAdvice(advice);
}
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the supplied
/// <paramref name="position"/> in the advice (interceptor) chain.
/// </summary>
/// <param name="position">
/// The zero (0) indexed position (from the head) at which the
/// supplied <paramref name="advice"/> is to be inserted into the
/// advice (interceptor) chain.
/// </param>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(IAdvice)"/>
public void AddAdvice(int position, IAdvice advice)
{
this.m_advised.AddAdvice(position, advice);
}
bool IAdvised.IsInterfaceProxied(Type intf)
{
return m_advised.IsInterfaceProxied(intf);
}
void IAdvised.AddAdvisors(IAdvisors advisors)
{
m_advised.AddAdvisors(advisors);
}
void IAdvised.AddAdvisor(IAdvisor advisor)
{
m_advised.AddAdvisor(advisor);
}
void IAdvised.AddAdvisor(int pos, IAdvisor advisor)
{
m_advised.AddAdvisor(pos, advisor);
}
void IAdvised.AddIntroduction(IIntroductionAdvisor advisor)
{
m_advised.AddIntroduction(advisor);
}
void IAdvised.AddIntroduction(int pos, IIntroductionAdvisor advisor)
{
m_advised.AddIntroduction(pos, advisor);
}
int IAdvised.IndexOf(IAdvisor advisor)
{
return m_advised.IndexOf(advisor);
}
int IAdvised.IndexOf(IIntroductionAdvisor advisor)
{
return m_advised.IndexOf(advisor);
}
bool IAdvised.RemoveAdvisor(IAdvisor advisor)
{
return m_advised.RemoveAdvisor(advisor);
}
void IAdvised.RemoveAdvisor(int index)
{
m_advised.RemoveAdvisor(index);
}
bool IAdvised.RemoveAdvice(IAdvice advice)
{
return m_advised.RemoveAdvice(advice);
}
bool IAdvised.RemoveIntroduction(IIntroductionAdvisor advisor)
{
return m_advised.RemoveIntroduction(advisor);
}
void IAdvised.RemoveIntroduction(int index)
{
m_advised.RemoveIntroduction(index);
}
void IAdvised.ReplaceIntroduction(int index, IIntroductionAdvisor advisor)
{
m_advised.ReplaceIntroduction(index, advisor);
}
bool IAdvised.ReplaceAdvisor(IAdvisor a, IAdvisor b)
{
return m_advised.ReplaceAdvisor(a, b);
}
string IAdvised.ToProxyConfigString()
{
return m_advised.ToProxyConfigString();
}
/// <summary>
/// Gets the target type behind the implementing object.
/// Ttypically a proxy configuration or an actual proxy.
/// </summary>
/// <value>The type of the target or null if not known.</value>
public Type TargetType
{
get { return m_targetType; }
}
}

View File

@@ -20,94 +20,93 @@
using System.Reflection;
using System.Reflection.Emit;
using Spring.Util;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation
/// that delegates method calls to the base method.
/// </summary>
/// <author>Bruno Baia</author>
public class BaseAopProxyMethodBuilder : AbstractAopProxyMethodBuilder
{
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation
/// that delegates method calls to the base method.
/// Creates a new instance of the method builder.
/// </summary>
/// <author>Bruno Baia</author>
public class BaseAopProxyMethodBuilder : AbstractAopProxyMethodBuilder
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="targetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </param>
/// <param name="onProxyTargetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s defined on the proxy.
/// </param>
public BaseAopProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator,
IDictionary<string, MethodInfo> targetMethods, IDictionary<string, MethodInfo> onProxyTargetMethods)
: base(typeBuilder, aopProxyGenerator, false, targetMethods, onProxyTargetMethods)
{
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="targetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </param>
/// <param name="onProxyTargetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s defined on the proxy.
/// </param>
public BaseAopProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator,
IDictionary<string, MethodInfo> targetMethods, IDictionary<string, MethodInfo> onProxyTargetMethods)
: base(typeBuilder, aopProxyGenerator, false, targetMethods, onProxyTargetMethods)
{
}
}
/// <summary>
/// Create static field that will cache target method when defined on the proxy.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The target method.</param>
protected override void GenerateOnProxyTargetMethodCacheField(
ILGenerator il, MethodInfo method)
/// <summary>
/// Create static field that will cache target method when defined on the proxy.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The target method.</param>
protected override void GenerateOnProxyTargetMethodCacheField(
ILGenerator il, MethodInfo method)
{
if (method.IsVirtual && !method.IsFinal)
{
if (method.IsVirtual && !method.IsFinal)
string methodId = GenerateMethodCacheFieldId(method);
// generate proxy method
MethodBuilder baseMethod = typeBuilder.DefineMethod("proxy_" + methodId,
MethodAttributes.Public | MethodAttributes.HideBySig,
CallingConventions.Standard,
method.ReturnType, ReflectionUtils.GetParameterTypes(method));
DefineGenericParameters(baseMethod, method);
//DefineParameters(baseMethod, method);
ILGenerator localIL = baseMethod.GetILGenerator();
localIL.Emit(OpCodes.Ldarg_0);
// setup parameters for call
for (int i = 0; i < method.GetParameters().Length; i++)
{
string methodId = GenerateMethodCacheFieldId(method);
// generate proxy method
MethodBuilder baseMethod = typeBuilder.DefineMethod("proxy_" + methodId,
MethodAttributes.Public | MethodAttributes.HideBySig,
CallingConventions.Standard,
method.ReturnType, ReflectionUtils.GetParameterTypes(method));
DefineGenericParameters(baseMethod, method);
//DefineParameters(baseMethod, method);
ILGenerator localIL = baseMethod.GetILGenerator();
localIL.Emit(OpCodes.Ldarg_0);
// setup parameters for call
for (int i = 0; i < method.GetParameters().Length; i++)
{
localIL.Emit(OpCodes.Ldarg_S, i + 1);
}
localIL.EmitCall(OpCodes.Call, method, null);
localIL.Emit(OpCodes.Ret);
// create static field that will cache proxy method
onProxyTargetMethods.Add(methodId, method);
onProxyTargetMethodCacheField = typeBuilder.DefineField(
methodId, typeof(MethodInfo), FieldAttributes.Private | FieldAttributes.Static);
MakeGenericMethod(il, method, onProxyTargetMethodCacheField, genericOnProxyTargetMethod);
localIL.Emit(OpCodes.Ldarg_S, i + 1);
}
}
/// <summary>
/// Calls target method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
CallDirectBaseMethod(il, method);
localIL.EmitCall(OpCodes.Call, method, null);
localIL.Emit(OpCodes.Ret);
// create static field that will cache proxy method
onProxyTargetMethods.Add(methodId, method);
onProxyTargetMethodCacheField = typeBuilder.DefineField(
methodId, typeof(MethodInfo), FieldAttributes.Private | FieldAttributes.Static);
MakeGenericMethod(il, method, onProxyTargetMethodCacheField, genericOnProxyTargetMethod);
}
}
/// <summary>
/// Calls target method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
CallDirectBaseMethod(il, method);
}
}

View File

@@ -24,142 +24,147 @@ using System.Runtime.Serialization;
#endregion
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Base class that each dynamic composition proxy has to extend.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
[Serializable]
public abstract class BaseCompositionAopProxy : AdvisedProxy, IAopProxy, ISerializable
{
/// <summary>
/// Base class that each dynamic composition proxy has to extend.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
[Serializable]
public abstract class BaseCompositionAopProxy : AdvisedProxy, IAopProxy, ISerializable
#region Constructor (s) / Destructor
/// <summary>
/// Default constructor.
/// </summary>
public BaseCompositionAopProxy()
{
#region Constructor (s) / Destructor
/// <summary>
/// Default constructor.
/// </summary>
public BaseCompositionAopProxy()
{}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.DynamicProxy.BaseCompositionAopProxy"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public BaseCompositionAopProxy(IAdvised advised) : base(advised)
{
base.Initialize(advised, this);
}
/// <summary>
/// Deserialization constructor.
/// </summary>
/// <param name="info">Serialization data.</param>
/// <param name="context">Serialization context.</param>
protected BaseCompositionAopProxy(SerializationInfo info, StreamingContext context) : base(info, context)
{}
///<summary>
///Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> with the data needed to serialize the target object.
///</summary>
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
#endregion
#region IAopProxy Members
/// <summary>
/// Returns this proxy instance
/// </summary>
/// <returns></returns>
object IAopProxy.GetProxy()
{
return this;
}
#endregion
#region Equal, HashCode and ToString overrides
/// <summary>
/// Delegate to target object handling of equals method.
/// </summary>
/// <param name="obj">The object to compare with the current target object</param>
/// <returns>true if the specified Object is equal to the current target object; otherwise, false</returns>
public override bool Equals(object obj)
{
bool equals = false;
object target = m_targetSource.GetTarget();
AdvisedProxy otherProxy = obj as AdvisedProxy;
object otherTarget = null;
if (otherProxy != null)
{
otherTarget = otherProxy.m_targetSource.GetTarget();
if (target == null)
{
equals = (otherTarget == null);
}
else
{
equals = target.Equals(otherTarget);
}
}
else if (target == null)
{
equals = (obj == null);
}
else
{
equals = target.Equals(obj);
}
m_targetSource.ReleaseTarget(target);
if (otherProxy != null)
{
otherProxy.m_targetSource.ReleaseTarget(otherTarget);
}
return equals;
}
/// <summary>
/// Delgate to the target object generation of the hash code.
/// </summary>
/// <returns>A hash code for the target object.</returns>
public override int GetHashCode()
{
int hashCode = 0;
object target = m_targetSource.GetTarget();
if (target != null)
{
hashCode = target.GetHashCode();
}
m_targetSource.ReleaseTarget(target);
return hashCode;
}
/// <summary>
/// Returns a String the represents the target object.
/// </summary>
/// <returns>A String that represents the target object</returns>
public override string ToString()
{
string str;
object target = m_targetSource.GetTarget();
if (target != null)
{
str = target.ToString();
}
else
{
str = base.ToString();
}
m_targetSource.ReleaseTarget(target);
return str;
}
#endregion
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.DynamicProxy.BaseCompositionAopProxy"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public BaseCompositionAopProxy(IAdvised advised) : base(advised)
{
base.Initialize(advised, this);
}
/// <summary>
/// Deserialization constructor.
/// </summary>
/// <param name="info">Serialization data.</param>
/// <param name="context">Serialization context.</param>
protected BaseCompositionAopProxy(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
///<summary>
///Populates a <see cref="T:System.Runtime.Serialization.SerializationInfo"></see> with the data needed to serialize the target object.
///</summary>
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
#endregion
#region IAopProxy Members
/// <summary>
/// Returns this proxy instance
/// </summary>
/// <returns></returns>
object IAopProxy.GetProxy()
{
return this;
}
#endregion
#region Equal, HashCode and ToString overrides
/// <summary>
/// Delegate to target object handling of equals method.
/// </summary>
/// <param name="obj">The object to compare with the current target object</param>
/// <returns>true if the specified Object is equal to the current target object; otherwise, false</returns>
public override bool Equals(object obj)
{
bool equals = false;
object target = m_targetSource.GetTarget();
AdvisedProxy otherProxy = obj as AdvisedProxy;
object otherTarget = null;
if (otherProxy != null)
{
otherTarget = otherProxy.m_targetSource.GetTarget();
if (target == null)
{
equals = (otherTarget == null);
}
else
{
equals = target.Equals(otherTarget);
}
}
else if (target == null)
{
equals = (obj == null);
}
else
{
equals = target.Equals(obj);
}
m_targetSource.ReleaseTarget(target);
if (otherProxy != null)
{
otherProxy.m_targetSource.ReleaseTarget(otherTarget);
}
return equals;
}
/// <summary>
/// Delgate to the target object generation of the hash code.
/// </summary>
/// <returns>A hash code for the target object.</returns>
public override int GetHashCode()
{
int hashCode = 0;
object target = m_targetSource.GetTarget();
if (target != null)
{
hashCode = target.GetHashCode();
}
m_targetSource.ReleaseTarget(target);
return hashCode;
}
/// <summary>
/// Returns a String the represents the target object.
/// </summary>
/// <returns>A String that represents the target object</returns>
public override string ToString()
{
string str;
object target = m_targetSource.GetTarget();
if (target != null)
{
str = target.ToString();
}
else
{
str = base.ToString();
}
m_targetSource.ReleaseTarget(target);
return str;
}
#endregion
}

View File

@@ -27,184 +27,193 @@ using Spring.Proxy;
#endregion
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Implementation of the <see cref="Spring.Aop.Framework.IAopProxyFactory"/>
/// interface that caches the AOP proxy <see cref="System.Type"/> instance.
/// </summary>
/// <remarks>
/// <p>
/// Caches against a key based on :
/// - the base type
/// - the target type
/// - the interfaces to proxy
/// </p>
/// </remarks>
/// <author>Bruno Baia</author>
/// <author>Erich Eichinger</author>
/// <seealso cref="Spring.Aop.Framework.DynamicProxy.DefaultAopProxyFactory"/>
/// <seealso cref="Spring.Aop.Framework.IAopProxyFactory"/>
[Serializable]
public class CachedAopProxyFactory : DefaultAopProxyFactory
{
/// <summary>
/// Implementation of the <see cref="Spring.Aop.Framework.IAopProxyFactory"/>
/// interface that caches the AOP proxy <see cref="System.Type"/> instance.
/// The shared <see cref="ILogger"/> instance for this class.
/// </summary>
/// <remarks>
/// <p>
/// Caches against a key based on :
/// - the base type
/// - the target type
/// - the interfaces to proxy
/// </p>
/// </remarks>
/// <author>Bruno Baia</author>
/// <author>Erich Eichinger</author>
/// <seealso cref="Spring.Aop.Framework.DynamicProxy.DefaultAopProxyFactory"/>
/// <seealso cref="Spring.Aop.Framework.IAopProxyFactory"/>
[Serializable]
public class CachedAopProxyFactory : DefaultAopProxyFactory
private static readonly ILogger<CachedAopProxyFactory> logger = LogManager.GetLogger<CachedAopProxyFactory>();
private static readonly Hashtable typeCache = new Hashtable();
/// <summary>
/// Returns the number of proxy types in the cache
/// </summary>
public static int CountCachedTypes
{
/// <summary>
/// The shared <see cref="ILogger"/> instance for this class.
/// </summary>
private static readonly ILogger<CachedAopProxyFactory> logger = LogManager.GetLogger<CachedAopProxyFactory>();
get { return typeCache.Count; }
}
private static readonly Hashtable typeCache = new Hashtable();
/// <summary>
/// Clears the type cache
/// </summary>
public static void ClearCache()
{
typeCache.Clear();
}
/// <summary>
/// Returns the number of proxy types in the cache
/// </summary>
public static int CountCachedTypes
/// <summary>
/// Creates a new instance
/// </summary>
public CachedAopProxyFactory()
{
}
/// <summary>
/// Generates the proxy type and caches the <see cref="System.Type"/>
/// instance against the base type and the interfaces to proxy.
/// </summary>
/// <param name="typeBuilder">
/// The <see cref="Spring.Proxy.IProxyTypeBuilder"/> to use
/// </param>
/// <returns>The generated or cached proxy class.</returns>
protected override Type BuildProxyType(IProxyTypeBuilder typeBuilder)
{
ProxyTypeCacheKey cacheKey = new ProxyTypeCacheKey(
typeBuilder.BaseType, typeBuilder.TargetType, typeBuilder.Interfaces, typeBuilder.ProxyTargetAttributes);
Type proxyType = null;
lock (typeCache)
{
get { return typeCache.Count; }
proxyType = typeCache[cacheKey] as Type;
if (proxyType == null)
{
proxyType = typeBuilder.BuildProxyType();
typeCache[cacheKey] = proxyType;
}
else
{
#region Instrumentation
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("AOP proxy type found in cache for {CacheKey}", cacheKey);
}
#endregion
}
}
/// <summary>
/// Clears the type cache
/// </summary>
public static void ClearCache()
return proxyType;
}
#region ProxyTypeCacheKey inner class implementation
/// <summary>
/// Uniquely identifies a proxytype in the cache
/// </summary>
private sealed class ProxyTypeCacheKey
{
private sealed class HashCodeComparer : IComparer<Type>
{
typeCache.Clear();
public int Compare(Type x, Type y)
{
return x.GetHashCode().CompareTo(y.GetHashCode());
}
}
/// <summary>
/// Creates a new instance
/// </summary>
public CachedAopProxyFactory()
{}
private static HashCodeComparer interfaceComparer = new HashCodeComparer();
/// <summary>
/// Generates the proxy type and caches the <see cref="System.Type"/>
/// instance against the base type and the interfaces to proxy.
/// </summary>
/// <param name="typeBuilder">
/// The <see cref="Spring.Proxy.IProxyTypeBuilder"/> to use
/// </param>
/// <returns>The generated or cached proxy class.</returns>
protected override Type BuildProxyType(IProxyTypeBuilder typeBuilder)
private Type baseType;
private Type targetType;
private List<Type> interfaceTypes;
private bool proxyTargetAttributes;
public ProxyTypeCacheKey(Type baseType, Type targetType, IList<Type> interfaceTypes, bool proxyTargetAttributes)
{
ProxyTypeCacheKey cacheKey = new ProxyTypeCacheKey(
typeBuilder.BaseType, typeBuilder.TargetType, typeBuilder.Interfaces, typeBuilder.ProxyTargetAttributes);
Type proxyType = null;
lock (typeCache)
{
proxyType = typeCache[cacheKey] as Type;
if (proxyType == null)
{
proxyType = typeBuilder.BuildProxyType();
typeCache[cacheKey] = proxyType;
}
else
{
#region Instrumentation
if (logger.IsEnabled(LogLevel.Debug))
{
logger.LogDebug("AOP proxy type found in cache for {CacheKey}", cacheKey);
}
#endregion
}
}
return proxyType;
this.baseType = baseType;
this.targetType = targetType;
this.interfaceTypes = new List<Type>(interfaceTypes);
this.interfaceTypes.Sort(interfaceComparer); // sort by GetHashcode()? to have a defined order
this.proxyTargetAttributes = proxyTargetAttributes;
}
#region ProxyTypeCacheKey inner class implementation
/// <summary>
/// Uniquely identifies a proxytype in the cache
/// </summary>
private sealed class ProxyTypeCacheKey
public override bool Equals(object obj)
{
private sealed class HashCodeComparer : IComparer<Type>
if (this == obj)
{
public int Compare(Type x, Type y)
{
return x.GetHashCode().CompareTo(y.GetHashCode());
}
}
private static HashCodeComparer interfaceComparer = new HashCodeComparer();
private Type baseType;
private Type targetType;
private List<Type> interfaceTypes;
private bool proxyTargetAttributes;
public ProxyTypeCacheKey(Type baseType, Type targetType, IList<Type> interfaceTypes, bool proxyTargetAttributes)
{
this.baseType = baseType;
this.targetType = targetType;
this.interfaceTypes = new List<Type>(interfaceTypes);
this.interfaceTypes.Sort(interfaceComparer); // sort by GetHashcode()? to have a defined order
this.proxyTargetAttributes = proxyTargetAttributes;
}
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
ProxyTypeCacheKey proxyTypeCacheKey = obj as ProxyTypeCacheKey;
if (proxyTypeCacheKey == null)
{
return false;
}
if (!Equals(targetType, proxyTypeCacheKey.targetType))
{
return false;
}
if (!Equals(baseType, proxyTypeCacheKey.baseType))
{
return false;
}
for (int i = 0; i < interfaceTypes.Count; i++)
{
if (!Equals(interfaceTypes[i], proxyTypeCacheKey.interfaceTypes[i]))
{
return false;
}
}
if (proxyTargetAttributes != proxyTypeCacheKey.proxyTargetAttributes)
{
return false;
}
return true;
}
public override int GetHashCode()
ProxyTypeCacheKey proxyTypeCacheKey = obj as ProxyTypeCacheKey;
if (proxyTypeCacheKey == null)
{
int result = baseType.GetHashCode();
result = 29*result + targetType.GetHashCode();
for (int i = 0; i < interfaceTypes.Count; i++)
{
result = 29 * result + interfaceTypes[i].GetHashCode();
}
result = 29 * result + proxyTargetAttributes.GetHashCode();
return result;
return false;
}
public override string ToString()
if (!Equals(targetType, proxyTypeCacheKey.targetType))
{
StringBuilder buffer = new StringBuilder();
buffer.Append("baseType=" + baseType + "; ");
buffer.Append("targetType=" + targetType + "; ");
buffer.Append("interfaceTypes=[");
foreach (Type intf in interfaceTypes)
{
buffer.Append(intf + ";");
}
buffer.Append("]; ");
buffer.Append("proxyTargetAttributes=" + proxyTargetAttributes + "; ");
return buffer.ToString();
return false;
}
if (!Equals(baseType, proxyTypeCacheKey.baseType))
{
return false;
}
for (int i = 0; i < interfaceTypes.Count; i++)
{
if (!Equals(interfaceTypes[i], proxyTypeCacheKey.interfaceTypes[i]))
{
return false;
}
}
if (proxyTargetAttributes != proxyTypeCacheKey.proxyTargetAttributes)
{
return false;
}
return true;
}
#endregion
public override int GetHashCode()
{
int result = baseType.GetHashCode();
result = 29 * result + targetType.GetHashCode();
for (int i = 0; i < interfaceTypes.Count; i++)
{
result = 29 * result + interfaceTypes[i].GetHashCode();
}
result = 29 * result + proxyTargetAttributes.GetHashCode();
return result;
}
public override string ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("baseType=" + baseType + "; ");
buffer.Append("targetType=" + targetType + "; ");
buffer.Append("interfaceTypes=[");
foreach (Type intf in interfaceTypes)
{
buffer.Append(intf + ";");
}
buffer.Append("]; ");
buffer.Append("proxyTargetAttributes=" + proxyTargetAttributes + "; ");
return buffer.ToString();
}
}
#endregion
}

View File

@@ -21,161 +21,159 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
using Spring.Util;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Builds an AOP proxy type using composition.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public class CompositionAopProxyTypeBuilder : AbstractAopProxyTypeBuilder
{
/// <summary>
/// Builds an AOP proxy type using composition.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public class CompositionAopProxyTypeBuilder : AbstractAopProxyTypeBuilder
private const string PROXY_TYPE_NAME = "CompositionAopProxy";
private readonly IAdvised advised;
/// <summary>
/// Creates a new instance of the
/// <see cref="CompositionAopProxyTypeBuilder"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public CompositionAopProxyTypeBuilder(IAdvised advised)
{
private const string PROXY_TYPE_NAME = "CompositionAopProxy";
this.advised = advised;
private readonly IAdvised advised;
Name = PROXY_TYPE_NAME;
BaseType = typeof(BaseCompositionAopProxy);
TargetType = advised.TargetSource.TargetType.IsInterface ? typeof(object) : advised.TargetSource.TargetType;
Interfaces = GetProxiableInterfaces(advised.Interfaces);
ProxyTargetAttributes = advised.ProxyTargetAttributes;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="CompositionAopProxyTypeBuilder"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public CompositionAopProxyTypeBuilder(IAdvised advised)
/// <summary>
/// Creates the proxy type.
/// </summary>
/// <returns>The generated proxy type.</returns>
public override Type BuildProxyType()
{
Dictionary<string, MethodInfo> targetMethods = new Dictionary<string, MethodInfo>();
TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
// apply custom attributes to the proxy type.
ApplyTypeAttributes(typeBuilder, TargetType);
if (advised.IsSerializable)
{
this.advised = advised;
Name = PROXY_TYPE_NAME;
BaseType = typeof(BaseCompositionAopProxy);
TargetType = advised.TargetSource.TargetType.IsInterface ? typeof(object) : advised.TargetSource.TargetType;
Interfaces = GetProxiableInterfaces(advised.Interfaces);
ProxyTargetAttributes = advised.ProxyTargetAttributes;
typeBuilder.SetCustomAttribute(
ReflectionUtils.CreateCustomAttribute(typeof(SerializableAttribute)));
ImplementSerializationConstructor(typeBuilder);
}
/// <summary>
/// Creates the proxy type.
/// </summary>
/// <returns>The generated proxy type.</returns>
public override Type BuildProxyType()
{
Dictionary<string, MethodInfo> targetMethods = new Dictionary<string, MethodInfo>();
// create constructors
ImplementConstructors(typeBuilder);
TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
// apply custom attributes to the proxy type.
ApplyTypeAttributes(typeBuilder, TargetType);
if (advised.IsSerializable)
// implement interfaces
IDictionary<Type, object> interfaceMap = advised.InterfaceMap;
foreach (Type intf in Interfaces)
{
interfaceMap.TryGetValue(intf, out var target);
if (target is null)
{
typeBuilder.SetCustomAttribute(
ReflectionUtils.CreateCustomAttribute(typeof(SerializableAttribute)));
ImplementSerializationConstructor(typeBuilder);
// implement interface
ImplementInterface(typeBuilder,
new TargetAopProxyMethodBuilder(typeBuilder, this, false, targetMethods),
intf, TargetType);
}
else if (target is IIntroductionAdvisor)
{
// implement introduction
ImplementInterface(typeBuilder,
new IntroductionProxyMethodBuilder(typeBuilder, this, targetMethods, advised.IndexOf((IIntroductionAdvisor) target)),
intf, TargetType);
}
// create constructors
ImplementConstructors(typeBuilder);
// implement interfaces
IDictionary<Type, object> interfaceMap = advised.InterfaceMap;
foreach (Type intf in Interfaces)
{
interfaceMap.TryGetValue(intf, out var target);
if (target is null)
{
// implement interface
ImplementInterface(typeBuilder,
new TargetAopProxyMethodBuilder(typeBuilder, this, false, targetMethods),
intf, TargetType);
}
else if (target is IIntroductionAdvisor)
{
// implement introduction
ImplementInterface(typeBuilder,
new IntroductionProxyMethodBuilder(typeBuilder, this, targetMethods, advised.IndexOf((IIntroductionAdvisor) target)),
intf, TargetType);
}
}
Type proxyType = typeBuilder.CreateTypeInfo();
// set target method references
foreach (KeyValuePair<string, MethodInfo> entry in targetMethods)
{
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, entry.Value);
}
return proxyType;
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushAdvisedProxy(ILGenerator il)
{
il.Emit(OpCodes.Ldarg_0);
}
/// <summary>
/// Implements serialization constructor.
/// </summary>
/// <param name="typeBuilder">Type builder to use.</param>
private void ImplementSerializationConstructor(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(MethodAttributes.Family,
CallingConventions.Standard,
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
Type proxyType = typeBuilder.CreateTypeInfo();
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Call, References.BaseCompositionAopProxySerializationConstructor);
il.Emit(OpCodes.Ret);
// set target method references
foreach (KeyValuePair<string, MethodInfo> entry in targetMethods)
{
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, entry.Value);
}
/// <summary>
/// Implements constructors for the proxy class.
/// </summary>
/// <remarks>
/// <p>
/// This implementation calls the base constructor.
/// </p>
/// </remarks>
/// <param name="typeBuilder">
/// The <see cref="System.Type"/> builder to use.
/// </param>
protected override void ImplementConstructors(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(References.BaseCompositionAopProxyConstructor.Attributes,
References.BaseCompositionAopProxyConstructor.CallingConvention,
new Type[] { typeof(IAdvised) });
return proxyType;
}
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, References.BaseCompositionAopProxyConstructor);
il.Emit(OpCodes.Ret);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushAdvisedProxy(ILGenerator il)
{
il.Emit(OpCodes.Ldarg_0);
}
/// <summary>
/// Determines if the specified <paramref name="type"/>
/// is one of those generated by this builder.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>
/// <see langword="true"/> if the type is a composition-based proxy;
/// otherwise <see langword="false"/>.
/// </returns>
public static bool IsCompositionProxy(Type type)
{
return type.FullName.StartsWith(PROXY_TYPE_NAME);
}
/// <summary>
/// Implements serialization constructor.
/// </summary>
/// <param name="typeBuilder">Type builder to use.</param>
private void ImplementSerializationConstructor(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(MethodAttributes.Family,
CallingConventions.Standard,
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Call, References.BaseCompositionAopProxySerializationConstructor);
il.Emit(OpCodes.Ret);
}
/// <summary>
/// Implements constructors for the proxy class.
/// </summary>
/// <remarks>
/// <p>
/// This implementation calls the base constructor.
/// </p>
/// </remarks>
/// <param name="typeBuilder">
/// The <see cref="System.Type"/> builder to use.
/// </param>
protected override void ImplementConstructors(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(References.BaseCompositionAopProxyConstructor.Attributes,
References.BaseCompositionAopProxyConstructor.CallingConvention,
new Type[] { typeof(IAdvised) });
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, References.BaseCompositionAopProxyConstructor);
il.Emit(OpCodes.Ret);
}
/// <summary>
/// Determines if the specified <paramref name="type"/>
/// is one of those generated by this builder.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>
/// <see langword="true"/> if the type is a composition-based proxy;
/// otherwise <see langword="false"/>.
/// </returns>
public static bool IsCompositionProxy(Type type)
{
return type.FullName.StartsWith(PROXY_TYPE_NAME);
}
}

View File

@@ -21,265 +21,264 @@
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
using Spring.Util;
using Spring.Proxy;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Builds an AOP proxy type using the decorator pattern.
/// </summary>
/// <author>Bruno Baia</author>
public class DecoratorAopProxyTypeBuilder : AbstractAopProxyTypeBuilder
{
private const string PROXY_TYPE_NAME = "DecoratorAopProxy";
private IAdvised advised;
/// <summary>
/// Builds an AOP proxy type using the decorator pattern.
/// AdvisedProxy instance calls should be delegated to.
/// </summary>
/// <author>Bruno Baia</author>
public class DecoratorAopProxyTypeBuilder : AbstractAopProxyTypeBuilder
protected FieldBuilder advisedProxyField;
/// <summary>
/// Creates a new instance of the
/// <see cref="DecoratorAopProxyTypeBuilder"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public DecoratorAopProxyTypeBuilder(IAdvised advised)
{
private const string PROXY_TYPE_NAME = "DecoratorAopProxy";
private IAdvised advised;
/// <summary>
/// AdvisedProxy instance calls should be delegated to.
/// </summary>
protected FieldBuilder advisedProxyField;
/// <summary>
/// Creates a new instance of the
/// <see cref="DecoratorAopProxyTypeBuilder"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public DecoratorAopProxyTypeBuilder(IAdvised advised)
if (!ReflectionUtils.IsTypeVisible(advised.TargetSource.TargetType, DynamicProxyManager.ASSEMBLY_NAME))
{
if (!ReflectionUtils.IsTypeVisible(advised.TargetSource.TargetType, DynamicProxyManager.ASSEMBLY_NAME))
throw new AopConfigException(String.Format(
"Cannot create decorator-based IAopProxy for a non visible class [{0}]",
advised.TargetSource.TargetType.FullName));
}
if (advised.TargetSource.TargetType.IsSealed)
{
throw new AopConfigException(String.Format(
"Cannot create decorator-based IAopProxy for a sealed class [{0}]",
advised.TargetSource.TargetType.FullName));
}
this.advised = advised;
Name = PROXY_TYPE_NAME;
TargetType = advised.TargetSource.TargetType.IsInterface ? typeof(object) : advised.TargetSource.TargetType;
BaseType = TargetType;
Interfaces = GetProxiableInterfaces(advised.Interfaces);
ProxyTargetAttributes = advised.ProxyTargetAttributes;
}
/// <summary>
/// Creates the proxy type.
/// </summary>
/// <returns>The generated proxy class.</returns>
public override Type BuildProxyType()
{
var targetMethods = new Dictionary<string, MethodInfo>();
TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
// apply custom attributes to the proxy type.
ApplyTypeAttributes(typeBuilder, TargetType);
// declare fields
DeclareAdvisedProxyInstanceField(typeBuilder);
// implement ISerializable if possible
if (advised.IsSerializable)
{
typeBuilder.SetCustomAttribute(
ReflectionUtils.CreateCustomAttribute(typeof(SerializableAttribute)));
ImplementSerializationConstructor(typeBuilder);
ImplementGetObjectDataMethod(typeBuilder);
}
// create constructors
ImplementConstructors(typeBuilder);
// implement interfaces
var interfaceMap = advised.InterfaceMap;
foreach (Type intf in Interfaces)
{
interfaceMap.TryGetValue(intf, out var target);
if (target is null)
{
throw new AopConfigException(String.Format(
"Cannot create decorator-based IAopProxy for a non visible class [{0}]",
advised.TargetSource.TargetType.FullName));
// implement interface (proxy only final methods)
ImplementInterface(typeBuilder,
new TargetAopProxyMethodBuilder(typeBuilder, this, true, targetMethods),
intf, TargetType, false);
}
if (advised.TargetSource.TargetType.IsSealed)
else if (target is IIntroductionAdvisor)
{
throw new AopConfigException(String.Format(
"Cannot create decorator-based IAopProxy for a sealed class [{0}]",
advised.TargetSource.TargetType.FullName));
// implement introduction
ImplementInterface(typeBuilder,
new IntroductionProxyMethodBuilder(typeBuilder, this, targetMethods, advised.IndexOf((IIntroductionAdvisor) target)),
intf, TargetType);
}
this.advised = advised;
Name = PROXY_TYPE_NAME;
TargetType = advised.TargetSource.TargetType.IsInterface ? typeof(object) : advised.TargetSource.TargetType;
BaseType = TargetType;
Interfaces = GetProxiableInterfaces(advised.Interfaces);
ProxyTargetAttributes = advised.ProxyTargetAttributes;
}
/// <summary>
/// Creates the proxy type.
/// </summary>
/// <returns>The generated proxy class.</returns>
public override Type BuildProxyType()
// inherit from target type
InheritType(typeBuilder,
new TargetAopProxyMethodBuilder(typeBuilder, this, false, targetMethods),
TargetType);
// implement IAdvised interface
ImplementInterface(typeBuilder,
new IAdvisedProxyMethodBuilder(typeBuilder, this),
typeof(IAdvised), TargetType);
// implement IAopProxy interface
ImplementIAopProxy(typeBuilder);
Type proxyType = typeBuilder.CreateTypeInfo();
// set target method references
foreach (var entry in targetMethods)
{
var targetMethods = new Dictionary<string, MethodInfo>();
TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
// apply custom attributes to the proxy type.
ApplyTypeAttributes(typeBuilder, TargetType);
// declare fields
DeclareAdvisedProxyInstanceField(typeBuilder);
// implement ISerializable if possible
if (advised.IsSerializable)
{
typeBuilder.SetCustomAttribute(
ReflectionUtils.CreateCustomAttribute(typeof(SerializableAttribute)));
ImplementSerializationConstructor(typeBuilder);
ImplementGetObjectDataMethod(typeBuilder);
}
// create constructors
ImplementConstructors(typeBuilder);
// implement interfaces
var interfaceMap = advised.InterfaceMap;
foreach (Type intf in Interfaces)
{
interfaceMap.TryGetValue(intf, out var target);
if (target is null)
{
// implement interface (proxy only final methods)
ImplementInterface(typeBuilder,
new TargetAopProxyMethodBuilder(typeBuilder, this, true, targetMethods),
intf, TargetType, false);
}
else if (target is IIntroductionAdvisor)
{
// implement introduction
ImplementInterface(typeBuilder,
new IntroductionProxyMethodBuilder(typeBuilder, this, targetMethods, advised.IndexOf((IIntroductionAdvisor)target)),
intf, TargetType);
}
}
// inherit from target type
InheritType(typeBuilder,
new TargetAopProxyMethodBuilder(typeBuilder, this, false, targetMethods),
TargetType);
// implement IAdvised interface
ImplementInterface(typeBuilder,
new IAdvisedProxyMethodBuilder(typeBuilder, this),
typeof(IAdvised), TargetType);
// implement IAopProxy interface
ImplementIAopProxy(typeBuilder);
Type proxyType = typeBuilder.CreateTypeInfo();
// set target method references
foreach (var entry in targetMethods)
{
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, entry.Value);
}
return proxyType;
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, entry.Value);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushAdvisedProxy(ILGenerator il)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
}
return proxyType;
}
/// <summary>
/// Declares field that holds the <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance used by the proxy.
/// </summary>
/// <param name="builder">
/// The <see cref="System.Type"/> builder to use for code generation.
/// </param>
protected virtual void DeclareAdvisedProxyInstanceField(TypeBuilder builder)
{
advisedProxyField = builder.DefineField("__advisedProxy", typeof(AdvisedProxy), FieldAttributes.Private);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushAdvisedProxy(ILGenerator il)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
}
/// <summary>
/// Implements serialization method.
/// </summary>
/// <param name="typeBuilder"></param>
private void ImplementGetObjectDataMethod(TypeBuilder typeBuilder)
{
typeBuilder.AddInterfaceImplementation(typeof(ISerializable));
/// <summary>
/// Declares field that holds the <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance used by the proxy.
/// </summary>
/// <param name="builder">
/// The <see cref="System.Type"/> builder to use for code generation.
/// </param>
protected virtual void DeclareAdvisedProxyInstanceField(TypeBuilder builder)
{
advisedProxyField = builder.DefineField("__advisedProxy", typeof(AdvisedProxy), FieldAttributes.Private);
}
MethodBuilder mb =
typeBuilder.DefineMethod("GetObjectData",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual,
typeof (void),
new Type[] {typeof (SerializationInfo), typeof (StreamingContext)});
/// <summary>
/// Implements serialization method.
/// </summary>
/// <param name="typeBuilder"></param>
private void ImplementGetObjectDataMethod(TypeBuilder typeBuilder)
{
typeBuilder.AddInterfaceImplementation(typeof(ISerializable));
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
il.EmitCall(OpCodes.Callvirt, References.AddSerializationValue, null);
il.Emit(OpCodes.Ret);
MethodBuilder mb =
typeBuilder.DefineMethod("GetObjectData",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual,
typeof(void),
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
//typeBuilder.DefineMethodOverride(mb, typeof(ISerializable).GetMethod("GetObjectData"));
}
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
il.EmitCall(OpCodes.Callvirt, References.AddSerializationValue, null);
il.Emit(OpCodes.Ret);
//typeBuilder.DefineMethodOverride(mb, typeof(ISerializable).GetMethod("GetObjectData"));
}
/// <summary>
/// Implements serialization constructor.
/// </summary>
/// <param name="typeBuilder">Type builder to use.</param>
private void ImplementSerializationConstructor(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(MethodAttributes.Family,
CallingConventions.Standard,
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
/// <summary>
/// Implements serialization constructor.
/// </summary>
/// <param name="typeBuilder">Type builder to use.</param>
private void ImplementSerializationConstructor(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(MethodAttributes.Family,
CallingConventions.Standard,
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldtoken, typeof(AdvisedProxy));
il.EmitCall(OpCodes.Call, References.GetTypeFromHandle, null);
il.EmitCall(OpCodes.Callvirt, References.GetSerializationValue, null);
il.Emit(OpCodes.Castclass, typeof(AdvisedProxy));
il.Emit(OpCodes.Stfld, advisedProxyField);
il.Emit(OpCodes.Ret);
}
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldtoken, typeof(AdvisedProxy));
il.EmitCall(OpCodes.Call, References.GetTypeFromHandle, null);
il.EmitCall(OpCodes.Callvirt, References.GetSerializationValue, null);
il.Emit(OpCodes.Castclass, typeof(AdvisedProxy));
il.Emit(OpCodes.Stfld, advisedProxyField);
il.Emit(OpCodes.Ret);
}
/// <summary>
/// Implements constructors for the proxy class.
/// </summary>
/// <remarks>
/// <p>
/// This implementation creates a new instance
/// of the <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/> class.
/// </p>
/// </remarks>
/// <param name="typeBuilder">
/// The <see cref="System.Type"/> builder to use.
/// </param>
protected override void ImplementConstructors(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(References.ObjectConstructor.Attributes,
References.ObjectConstructor.CallingConvention,
new Type[] { typeof(IAdvised) });
/// <summary>
/// Implements constructors for the proxy class.
/// </summary>
/// <remarks>
/// <p>
/// This implementation creates a new instance
/// of the <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/> class.
/// </p>
/// </remarks>
/// <param name="typeBuilder">
/// The <see cref="System.Type"/> builder to use.
/// </param>
protected override void ImplementConstructors(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(References.ObjectConstructor.Attributes,
References.ObjectConstructor.CallingConvention,
new Type[] { typeof(IAdvised) });
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, References.AdvisedProxyConstructor);
il.Emit(OpCodes.Stfld, advisedProxyField);
il.Emit(OpCodes.Ret);
}
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, References.AdvisedProxyConstructor);
il.Emit(OpCodes.Stfld, advisedProxyField);
il.Emit(OpCodes.Ret);
}
/// <summary>
/// Implements <see cref="Spring.Aop.Framework.IAopProxy"/> interface.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
protected virtual void ImplementIAopProxy(TypeBuilder typeBuilder)
{
Type intf = typeof(IAopProxy);
MethodInfo getProxyMethod = intf.GetMethod("GetProxy", Type.EmptyTypes);
/// <summary>
/// Implements <see cref="Spring.Aop.Framework.IAopProxy"/> interface.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
protected virtual void ImplementIAopProxy(TypeBuilder typeBuilder)
{
Type intf = typeof(IAopProxy);
MethodInfo getProxyMethod = intf.GetMethod("GetProxy", Type.EmptyTypes);
typeBuilder.AddInterfaceImplementation(intf);
typeBuilder.AddInterfaceImplementation(intf);
MethodBuilder mb = typeBuilder.DefineMethod(typeof(IAdvised).FullName + "." + getProxyMethod.Name,
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
getProxyMethod.CallingConvention, getProxyMethod.ReturnType, Type.EmptyTypes);
MethodBuilder mb = typeBuilder.DefineMethod(typeof(IAdvised).FullName + "." + getProxyMethod.Name,
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
getProxyMethod.CallingConvention, getProxyMethod.ReturnType, Type.EmptyTypes);
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(mb, getProxyMethod);
}
typeBuilder.DefineMethodOverride(mb, getProxyMethod);
}
/// <summary>
/// Determines if the specified <paramref name="type"/>
/// is one of those generated by this builder.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>
/// <see langword="true"/> if the type is a decorator-based proxy;
/// otherwise <see langword="false"/>.
/// </returns>
public static bool IsDecoratorProxy(Type type)
{
return type.FullName.StartsWith(PROXY_TYPE_NAME);
}
/// <summary>
/// Determines if the specified <paramref name="type"/>
/// is one of those generated by this builder.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>
/// <see langword="true"/> if the type is a decorator-based proxy;
/// otherwise <see langword="false"/>.
/// </returns>
public static bool IsDecoratorProxy(Type type)
{
return type.FullName.StartsWith(PROXY_TYPE_NAME);
}
}

View File

@@ -22,76 +22,77 @@ using System.Reflection;
using Spring.Proxy;
using Spring.Util;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Default implementation of the
/// <see cref="Spring.Aop.Framework.IAopProxyFactory"/> interface,
/// either creating a decorator-based dynamic proxy or
/// a composition-based dynamic proxy.
/// </summary>
/// <remarks>
/// <p>
/// Creates a decorator-base proxy if one the following is true :
/// - the "ProxyTargetType" property is set
/// - no interfaces have been specified
/// </p>
/// <p>
/// In general, specify "ProxyTargetType" to enforce a decorator-based proxy,
/// or specify one or more interfaces to use a composition-based proxy.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Bruno Baia (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
/// <seealso cref="Spring.Aop.Framework.IAopProxyFactory"/>
[Serializable]
public class DefaultAopProxyFactory : AbstractAopProxyFactory
{
/// <summary>
/// Default implementation of the
/// <see cref="Spring.Aop.Framework.IAopProxyFactory"/> interface,
/// either creating a decorator-based dynamic proxy or
/// a composition-based dynamic proxy.
/// Force transient assemblies to be resolvable by <see cref="Assembly.Load(string)"/>.
/// </summary>
/// <remarks>
/// <p>
/// Creates a decorator-base proxy if one the following is true :
/// - the "ProxyTargetType" property is set
/// - no interfaces have been specified
/// </p>
/// <p>
/// In general, specify "ProxyTargetType" to enforce a decorator-based proxy,
/// or specify one or more interfaces to use a composition-based proxy.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Bruno Baia (.NET)</author>
/// <author>Erich Eichinger (.NET)</author>
/// <seealso cref="Spring.Aop.Framework.IAopProxyFactory"/>
[Serializable]
public class DefaultAopProxyFactory : AbstractAopProxyFactory
static DefaultAopProxyFactory()
{
/// <summary>
/// Force transient assemblies to be resolvable by <see cref="Assembly.Load(string)"/>.
/// </summary>
static DefaultAopProxyFactory()
{
SystemUtils.RegisterLoadedAssemblyResolver();
}
SystemUtils.RegisterLoadedAssemblyResolver();
}
/// <summary>
/// Creates an actual proxy instance based on the supplied <paramref name="advisedSupport"/>
/// </summary>
/// <param name="advisedSupport"></param>
/// <returns></returns>
protected override IAopProxy DoCreateAopProxyInstance(AdvisedSupport advisedSupport)
/// <summary>
/// Creates an actual proxy instance based on the supplied <paramref name="advisedSupport"/>
/// </summary>
/// <param name="advisedSupport"></param>
/// <returns></returns>
protected override IAopProxy DoCreateAopProxyInstance(AdvisedSupport advisedSupport)
{
if (advisedSupport.ProxyType == null)
{
if (advisedSupport.ProxyType == null)
IProxyTypeBuilder typeBuilder;
if ((advisedSupport.ProxyTargetType) ||
(advisedSupport.Interfaces.Count == 0))
{
IProxyTypeBuilder typeBuilder;
if ((advisedSupport.ProxyTargetType) ||
(advisedSupport.Interfaces.Count == 0))
{
typeBuilder = new DecoratorAopProxyTypeBuilder(advisedSupport);
}
else
{
typeBuilder = new CompositionAopProxyTypeBuilder(advisedSupport);
}
advisedSupport.ProxyType = BuildProxyType(typeBuilder);
advisedSupport.ProxyConstructor = advisedSupport.ProxyType.GetConstructor(new Type[] { typeof(IAdvised) });
typeBuilder = new DecoratorAopProxyTypeBuilder(advisedSupport);
}
return (IAopProxy)advisedSupport.ProxyConstructor.Invoke(new object[] { advisedSupport });
else
{
typeBuilder = new CompositionAopProxyTypeBuilder(advisedSupport);
}
advisedSupport.ProxyType = BuildProxyType(typeBuilder);
advisedSupport.ProxyConstructor = advisedSupport.ProxyType.GetConstructor(new Type[] { typeof(IAdvised) });
}
/// <summary>
/// Generates the proxy type.
/// </summary>
/// <param name="typeBuilder">
/// The <see cref="Spring.Proxy.IProxyTypeBuilder"/> to use
/// </param>
/// <returns>The generated proxy class.</returns>
protected virtual Type BuildProxyType(IProxyTypeBuilder typeBuilder)
{
return typeBuilder.BuildProxyType();
}
return (IAopProxy) advisedSupport.ProxyConstructor.Invoke(new object[] { advisedSupport });
}
/// <summary>
/// Generates the proxy type.
/// </summary>
/// <param name="typeBuilder">
/// The <see cref="Spring.Proxy.IProxyTypeBuilder"/> to use
/// </param>
/// <returns>The generated proxy class.</returns>
protected virtual Type BuildProxyType(IProxyTypeBuilder typeBuilder)
{
return typeBuilder.BuildProxyType();
}
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -21,59 +21,57 @@
#region Imports
using System.Reflection.Emit;
using Spring.Proxy;
#endregion
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation that delegates
/// method calls to an <see cref="Spring.Aop.Framework.IAdvised"/> instance.
/// </summary>
/// <author>Bruno Baia</author>
public class IAdvisedProxyMethodBuilder : TargetProxyMethodBuilder
{
#region Fields
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation that delegates
/// method calls to an <see cref="Spring.Aop.Framework.IAdvised"/> instance.
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </summary>
/// <author>Bruno Baia</author>
public class IAdvisedProxyMethodBuilder : TargetProxyMethodBuilder
private IAopProxyTypeGenerator _aopProxyGenerator;
#endregion
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
public IAdvisedProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator)
: base(typeBuilder, aopProxyGenerator, true)
{
#region Fields
/// <summary>
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </summary>
private IAopProxyTypeGenerator _aopProxyGenerator;
#endregion
#region Constructor(s) / Destructor
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
public IAdvisedProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator)
: base(typeBuilder, aopProxyGenerator, true)
{
this._aopProxyGenerator = aopProxyGenerator;
}
#endregion
#region Protected Methods
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTarget(ILGenerator il)
{
_aopProxyGenerator.PushAdvisedProxy(il);
}
#endregion
this._aopProxyGenerator = aopProxyGenerator;
}
#endregion
#region Protected Methods
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTarget(ILGenerator il)
{
_aopProxyGenerator.PushAdvisedProxy(il);
}
#endregion
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -21,26 +21,24 @@
#region Imports
using System.Reflection.Emit;
using Spring.Proxy;
#endregion
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Describes the operations that generates IL instructions
/// used to build the Aop proxy type.
/// </summary>
/// <author>Bruno Baia</author>
public interface IAopProxyTypeGenerator : IProxyTypeGenerator
{
/// <summary>
/// Describes the operations that generates IL instructions
/// used to build the Aop proxy type.
/// </summary>
/// <author>Bruno Baia</author>
public interface IAopProxyTypeGenerator : IProxyTypeGenerator
{
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
void PushAdvisedProxy(ILGenerator il);
}
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
void PushAdvisedProxy(ILGenerator il);
}

View File

@@ -21,315 +21,316 @@
using System.Runtime.Serialization;
using System.Reflection;
using System.Reflection.Emit;
using Spring.Proxy;
using Spring.Util;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// Builds an AOP proxy type using inheritance.
/// </summary>
/// <author>Bruno Baia</author>
public class InheritanceAopProxyTypeBuilder : AbstractAopProxyTypeBuilder
{
private const string PROXY_TYPE_NAME = "InheritanceAopProxy";
private IAdvised advised;
private bool proxyDeclaredMembersOnly = true;
/// <summary>
/// Builds an AOP proxy type using inheritance.
/// AdvisedProxy instance calls should be delegated to.
/// </summary>
/// <author>Bruno Baia</author>
public class InheritanceAopProxyTypeBuilder : AbstractAopProxyTypeBuilder
protected FieldBuilder advisedProxyField;
/// <summary>
/// Gets or sets a value indicating whether inherited members should be proxied.
/// </summary>
/// <value>
/// <see langword="true"/> if inherited members should be proxied;
/// otherwise, <see langword="false"/>.
/// </value>
public bool ProxyDeclaredMembersOnly
{
private const string PROXY_TYPE_NAME = "InheritanceAopProxy";
get { return proxyDeclaredMembersOnly; }
set { proxyDeclaredMembersOnly = value; }
}
private IAdvised advised;
private bool proxyDeclaredMembersOnly = true;
/// <summary>
/// AdvisedProxy instance calls should be delegated to.
/// </summary>
protected FieldBuilder advisedProxyField;
/// <summary>
/// Gets or sets a value indicating whether inherited members should be proxied.
/// </summary>
/// <value>
/// <see langword="true"/> if inherited members should be proxied;
/// otherwise, <see langword="false"/>.
/// </value>
public bool ProxyDeclaredMembersOnly
/// <summary>
/// Creates a new instance of the
/// <see cref="CompositionAopProxyTypeBuilder"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public InheritanceAopProxyTypeBuilder(IAdvised advised)
{
if (!ReflectionUtils.IsTypeVisible(advised.TargetSource.TargetType, DynamicProxyManager.ASSEMBLY_NAME))
{
get { return proxyDeclaredMembersOnly; }
set { proxyDeclaredMembersOnly = value; }
throw new AopConfigException(String.Format(
"Cannot create inheritance-based IAopProxy for a non visible class [{0}]",
advised.TargetSource.TargetType.FullName));
}
/// <summary>
/// Creates a new instance of the
/// <see cref="CompositionAopProxyTypeBuilder"/> class.
/// </summary>
/// <param name="advised">The proxy configuration.</param>
public InheritanceAopProxyTypeBuilder(IAdvised advised)
if (advised.TargetSource.TargetType.IsSealed)
{
if (!ReflectionUtils.IsTypeVisible(advised.TargetSource.TargetType, DynamicProxyManager.ASSEMBLY_NAME))
throw new AopConfigException(String.Format(
"Cannot create inheritance-based IAopProxy for a sealed class [{0}]",
advised.TargetSource.TargetType.FullName));
}
this.advised = advised;
Name = PROXY_TYPE_NAME;
TargetType = advised.TargetSource.TargetType;
BaseType = TargetType;
Interfaces = GetProxiableInterfaces(advised.Interfaces);
ProxyTargetAttributes = advised.ProxyTargetAttributes;
}
/// <summary>
/// Creates the proxy type.
/// </summary>
/// <returns>The generated proxy class.</returns>
public override Type BuildProxyType()
{
var targetMethods = new Dictionary<string, MethodInfo>();
var proxyMethods = new Dictionary<string, MethodInfo>();
TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
// apply custom attributes to the proxy type.
ApplyTypeAttributes(typeBuilder, TargetType);
// declare fields
DeclareAdvisedProxyInstanceField(typeBuilder);
// implement ISerializable if possible
if (advised.IsSerializable)
{
typeBuilder.SetCustomAttribute(
ReflectionUtils.CreateCustomAttribute(typeof(SerializableAttribute)));
ImplementSerializationConstructor(typeBuilder);
ImplementGetObjectDataMethod(typeBuilder);
}
// create constructors
ImplementConstructors(typeBuilder);
// implement interfaces
var interfaceMap = advised.InterfaceMap;
foreach (Type intf in Interfaces)
{
object target = interfaceMap[intf];
if (target == null)
{
throw new AopConfigException(String.Format(
"Cannot create inheritance-based IAopProxy for a non visible class [{0}]",
advised.TargetSource.TargetType.FullName));
// implement interface (proxy only final methods)
ImplementInterface(typeBuilder,
new BaseAopProxyMethodBuilder(typeBuilder, this, targetMethods, proxyMethods),
intf, TargetType, false);
}
if (advised.TargetSource.TargetType.IsSealed)
else if (target is IIntroductionAdvisor)
{
throw new AopConfigException(String.Format(
"Cannot create inheritance-based IAopProxy for a sealed class [{0}]",
advised.TargetSource.TargetType.FullName));
// implement introduction
ImplementInterface(typeBuilder,
new IntroductionProxyMethodBuilder(typeBuilder, this, targetMethods, advised.IndexOf((IIntroductionAdvisor) target)),
intf, TargetType);
}
this.advised = advised;
Name = PROXY_TYPE_NAME;
TargetType = advised.TargetSource.TargetType;
BaseType = TargetType;
Interfaces = GetProxiableInterfaces(advised.Interfaces);
ProxyTargetAttributes = advised.ProxyTargetAttributes;
}
/// <summary>
/// Creates the proxy type.
/// </summary>
/// <returns>The generated proxy class.</returns>
public override Type BuildProxyType()
// inherit from target type
InheritType(typeBuilder,
new BaseAopProxyMethodBuilder(typeBuilder, this, targetMethods, proxyMethods),
TargetType, ProxyDeclaredMembersOnly);
// implement IAdvised interface
ImplementInterface(typeBuilder,
new IAdvisedProxyMethodBuilder(typeBuilder, this),
typeof(IAdvised), TargetType);
// implement IAopProxy interface
ImplementIAopProxy(typeBuilder);
Type proxyType;
proxyType = typeBuilder.CreateTypeInfo();
// set target method references
foreach (var entry in targetMethods)
{
var targetMethods = new Dictionary<string, MethodInfo>();
var proxyMethods = new Dictionary<string, MethodInfo>();
TypeBuilder typeBuilder = CreateTypeBuilder(Name, BaseType);
// apply custom attributes to the proxy type.
ApplyTypeAttributes(typeBuilder, TargetType);
// declare fields
DeclareAdvisedProxyInstanceField(typeBuilder);
// implement ISerializable if possible
if (advised.IsSerializable)
{
typeBuilder.SetCustomAttribute(
ReflectionUtils.CreateCustomAttribute(typeof(SerializableAttribute)));
ImplementSerializationConstructor(typeBuilder);
ImplementGetObjectDataMethod(typeBuilder);
}
// create constructors
ImplementConstructors(typeBuilder);
// implement interfaces
var interfaceMap = advised.InterfaceMap;
foreach (Type intf in Interfaces)
{
object target = interfaceMap[intf];
if (target == null)
{
// implement interface (proxy only final methods)
ImplementInterface(typeBuilder,
new BaseAopProxyMethodBuilder(typeBuilder, this, targetMethods, proxyMethods),
intf, TargetType, false);
}
else if (target is IIntroductionAdvisor)
{
// implement introduction
ImplementInterface(typeBuilder,
new IntroductionProxyMethodBuilder(typeBuilder, this, targetMethods, advised.IndexOf((IIntroductionAdvisor)target)),
intf, TargetType);
}
}
// inherit from target type
InheritType(typeBuilder,
new BaseAopProxyMethodBuilder(typeBuilder, this, targetMethods, proxyMethods),
TargetType, ProxyDeclaredMembersOnly);
// implement IAdvised interface
ImplementInterface(typeBuilder,
new IAdvisedProxyMethodBuilder(typeBuilder, this),
typeof(IAdvised), TargetType);
// implement IAopProxy interface
ImplementIAopProxy(typeBuilder);
Type proxyType;
proxyType = typeBuilder.CreateTypeInfo();
// set target method references
foreach (var entry in targetMethods)
{
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, entry.Value);
}
// set proxy method references
foreach (var entry in proxyMethods)
{
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
MethodInfo proxyMethod = proxyType.GetMethod("proxy_" + entry.Key, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
field.SetValue(proxyType, proxyMethod);
}
return proxyType;
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
field.SetValue(proxyType, entry.Value);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushTarget(ILGenerator il)
// set proxy method references
foreach (var entry in proxyMethods)
{
il.Emit(OpCodes.Ldarg_0);
FieldInfo field = proxyType.GetField(entry.Key, BindingFlags.NonPublic | BindingFlags.Static);
MethodInfo proxyMethod = proxyType.GetMethod("proxy_" + entry.Key, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
field.SetValue(proxyType, proxyMethod);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushAdvisedProxy(ILGenerator il)
return proxyType;
}
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushTarget(ILGenerator il)
{
il.Emit(OpCodes.Ldarg_0);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the current <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
public override void PushAdvisedProxy(ILGenerator il)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
}
/// <summary>
/// Declares field that holds the <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance used by the proxy.
/// </summary>
/// <param name="builder">
/// The <see cref="System.Type"/> builder to use for code generation.
/// </param>
protected virtual void DeclareAdvisedProxyInstanceField(TypeBuilder builder)
{
advisedProxyField = builder.DefineField("__advisedProxy", typeof(AdvisedProxy), FieldAttributes.Private);
}
/// <summary>
/// Implements serialization method.
/// </summary>
/// <param name="typeBuilder"></param>
private void ImplementGetObjectDataMethod(TypeBuilder typeBuilder)
{
typeBuilder.AddInterfaceImplementation(typeof(ISerializable));
MethodBuilder mb =
typeBuilder.DefineMethod("GetObjectData",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual,
typeof(void),
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
il.EmitCall(OpCodes.Callvirt, References.AddSerializationValue, null);
il.Emit(OpCodes.Ret);
//typeBuilder.DefineMethodOverride(mb, typeof(ISerializable).GetMethod("GetObjectData"));
}
/// <summary>
/// Implements serialization constructor.
/// </summary>
/// <param name="typeBuilder">Type builder to use.</param>
private void ImplementSerializationConstructor(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(MethodAttributes.Family,
CallingConventions.Standard,
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldtoken, typeof(AdvisedProxy));
il.EmitCall(OpCodes.Call, References.GetTypeFromHandle, null);
il.EmitCall(OpCodes.Callvirt, References.GetSerializationValue, null);
il.Emit(OpCodes.Castclass, typeof(AdvisedProxy));
il.Emit(OpCodes.Stfld, advisedProxyField);
il.Emit(OpCodes.Ret);
}
/// <summary>
/// Defines the types of the parameters for the specified constructor.
/// </summary>
/// <param name="constructor">The constructor to use.</param>
/// <returns>The types for constructor's parameters.</returns>
protected override Type[] DefineConstructorParameters(ConstructorInfo constructor)
{
Type[] currentParams = ReflectionUtils.GetParameterTypes(constructor.GetParameters());
Type[] newParams = new Type[currentParams.Length + 1];
newParams[currentParams.Length] = typeof(IAdvised);
currentParams.CopyTo(newParams, 0);
return newParams;
}
/// <summary>
/// Generates the proxy constructor.
/// </summary>
/// <remarks>
/// <p>
/// This implementation creates instance of the AdvisedProxy object.
/// </p>
/// </remarks>
/// <param name="builder">The constructor builder to use.</param>
/// <param name="il">The IL generator to use.</param>
/// <param name="constructor">The constructor to delegate the creation to.</param>
protected override void GenerateConstructor(
ConstructorBuilder builder, ILGenerator il, ConstructorInfo constructor)
{
int paramCount = constructor.GetParameters().Length;
il.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < paramCount; i++)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
il.Emit(OpCodes.Ldarg_S, i + 1);
}
/// <summary>
/// Declares field that holds the <see cref="Spring.Aop.Framework.DynamicProxy.AdvisedProxy"/>
/// instance used by the proxy.
/// </summary>
/// <param name="builder">
/// The <see cref="System.Type"/> builder to use for code generation.
/// </param>
protected virtual void DeclareAdvisedProxyInstanceField(TypeBuilder builder)
{
advisedProxyField = builder.DefineField("__advisedProxy", typeof(AdvisedProxy), FieldAttributes.Private);
}
il.Emit(OpCodes.Call, constructor);
/// <summary>
/// Implements serialization method.
/// </summary>
/// <param name="typeBuilder"></param>
private void ImplementGetObjectDataMethod(TypeBuilder typeBuilder)
{
typeBuilder.AddInterfaceImplementation(typeof(ISerializable));
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_S, paramCount + 1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, References.AdvisedProxyConstructor);
il.Emit(OpCodes.Stfld, advisedProxyField);
}
MethodBuilder mb =
typeBuilder.DefineMethod("GetObjectData",
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.NewSlot | MethodAttributes.Virtual,
typeof(void),
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
/// <summary>
/// Implements <see cref="Spring.Aop.Framework.IAopProxy"/> interface.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
protected virtual void ImplementIAopProxy(TypeBuilder typeBuilder)
{
Type intf = typeof(IAopProxy);
MethodInfo getProxyMethod = intf.GetMethod("GetProxy", Type.EmptyTypes);
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, advisedProxyField);
il.EmitCall(OpCodes.Callvirt, References.AddSerializationValue, null);
il.Emit(OpCodes.Ret);
typeBuilder.AddInterfaceImplementation(intf);
//typeBuilder.DefineMethodOverride(mb, typeof(ISerializable).GetMethod("GetObjectData"));
}
MethodBuilder mb = typeBuilder.DefineMethod(typeof(IAdvised).FullName + "." + getProxyMethod.Name,
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
getProxyMethod.CallingConvention, getProxyMethod.ReturnType, Type.EmptyTypes);
/// <summary>
/// Implements serialization constructor.
/// </summary>
/// <param name="typeBuilder">Type builder to use.</param>
private void ImplementSerializationConstructor(TypeBuilder typeBuilder)
{
ConstructorBuilder cb =
typeBuilder.DefineConstructor(MethodAttributes.Family,
CallingConventions.Standard,
new Type[] { typeof(SerializationInfo), typeof(StreamingContext) });
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldstr, "advisedProxy");
il.Emit(OpCodes.Ldtoken, typeof(AdvisedProxy));
il.EmitCall(OpCodes.Call, References.GetTypeFromHandle, null);
il.EmitCall(OpCodes.Callvirt, References.GetSerializationValue, null);
il.Emit(OpCodes.Castclass, typeof(AdvisedProxy));
il.Emit(OpCodes.Stfld, advisedProxyField);
il.Emit(OpCodes.Ret);
}
typeBuilder.DefineMethodOverride(mb, getProxyMethod);
}
/// <summary>
/// Defines the types of the parameters for the specified constructor.
/// </summary>
/// <param name="constructor">The constructor to use.</param>
/// <returns>The types for constructor's parameters.</returns>
protected override Type[] DefineConstructorParameters(ConstructorInfo constructor)
{
Type[] currentParams = ReflectionUtils.GetParameterTypes(constructor.GetParameters());
Type[] newParams = new Type[currentParams.Length + 1];
newParams[currentParams.Length] = typeof(IAdvised);
currentParams.CopyTo(newParams, 0);
return newParams;
}
/// <summary>
/// Generates the proxy constructor.
/// </summary>
/// <remarks>
/// <p>
/// This implementation creates instance of the AdvisedProxy object.
/// </p>
/// </remarks>
/// <param name="builder">The constructor builder to use.</param>
/// <param name="il">The IL generator to use.</param>
/// <param name="constructor">The constructor to delegate the creation to.</param>
protected override void GenerateConstructor(
ConstructorBuilder builder, ILGenerator il, ConstructorInfo constructor)
{
int paramCount = constructor.GetParameters().Length;
il.Emit(OpCodes.Ldarg_0);
for (int i = 0; i < paramCount; i++)
{
il.Emit(OpCodes.Ldarg_S, i + 1);
}
il.Emit(OpCodes.Call, constructor);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_S, paramCount + 1);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Newobj, References.AdvisedProxyConstructor);
il.Emit(OpCodes.Stfld, advisedProxyField);
}
/// <summary>
/// Implements <see cref="Spring.Aop.Framework.IAopProxy"/> interface.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
protected virtual void ImplementIAopProxy(TypeBuilder typeBuilder)
{
Type intf = typeof(IAopProxy);
MethodInfo getProxyMethod = intf.GetMethod("GetProxy", Type.EmptyTypes);
typeBuilder.AddInterfaceImplementation(intf);
MethodBuilder mb = typeBuilder.DefineMethod(typeof(IAdvised).FullName + "." + getProxyMethod.Name,
MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
getProxyMethod.CallingConvention, getProxyMethod.ReturnType, Type.EmptyTypes);
ILGenerator il = mb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
typeBuilder.DefineMethodOverride(mb, getProxyMethod);
}
/// <summary>
/// Determines if the specified <paramref name="type"/>
/// is one of those generated by this builder.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>
/// <see langword="true"/> if the type is a inheritance-based proxy;
/// otherwise <see langword="false"/>.
/// </returns>
public static bool IsInheritanceProxy(Type type)
{
return type.FullName.StartsWith(PROXY_TYPE_NAME);
}
/// <summary>
/// Determines if the specified <paramref name="type"/>
/// is one of those generated by this builder.
/// </summary>
/// <param name="type">The type to check.</param>
/// <returns>
/// <see langword="true"/> if the type is a inheritance-based proxy;
/// otherwise <see langword="false"/>.
/// </returns>
public static bool IsInheritanceProxy(Type type)
{
return type.FullName.StartsWith(PROXY_TYPE_NAME);
}
}

View File

@@ -21,76 +21,75 @@
using System.Reflection;
using System.Reflection.Emit;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation
/// that delegates method calls to introduction object.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public class IntroductionProxyMethodBuilder : AbstractAopProxyMethodBuilder
{
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation
/// that delegates method calls to introduction object.
/// The index of the introduction to delegate call to.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public class IntroductionProxyMethodBuilder : AbstractAopProxyMethodBuilder
protected int index;
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="targetMethods">
///
/// </param>
/// <param name="index">index of the introduction to delegate call to</param>
public IntroductionProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator,
IDictionary<string, MethodInfo> targetMethods, int index)
: base(typeBuilder, aopProxyGenerator, true, targetMethods)
{
/// <summary>
/// The index of the introduction to delegate call to.
/// </summary>
protected int index;
this.index = index;
}
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="targetMethods">
///
/// </param>
/// <param name="index">index of the introduction to delegate call to</param>
public IntroductionProxyMethodBuilder(
TypeBuilder typeBuilder, IAopProxyTypeGenerator aopProxyGenerator,
IDictionary<string, MethodInfo> targetMethods, int index)
: base(typeBuilder, aopProxyGenerator, true, targetMethods)
{
this.index = index;
}
/// <summary>
/// Generates the IL instructions that pushes
/// the introduction type on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTargetType(ILGenerator il)
{
PushTarget(il);
il.EmitCall(OpCodes.Call, References.GetTypeMethod, null);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the introduction type on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTargetType(ILGenerator il)
{
PushTarget(il);
il.EmitCall(OpCodes.Call, References.GetTypeMethod, null);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the introduction instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTarget(ILGenerator il)
{
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.IntroductionsField);
il.Emit(OpCodes.Ldc_I4, index);
il.Emit(OpCodes.Ldelem_Ref);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the introduction instance on stack.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTarget(ILGenerator il)
{
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.IntroductionsField);
il.Emit(OpCodes.Ldc_I4, index);
il.Emit(OpCodes.Ldelem_Ref);
}
/// <summary>
/// Calls proxied method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
CallDirectTargetMethod(il, interfaceMethod);
}
/// <summary>
/// Calls proxied method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
CallDirectTargetMethod(il, interfaceMethod);
}
}

View File

@@ -21,106 +21,105 @@
using System.Reflection;
using System.Reflection.Emit;
namespace Spring.Aop.Framework.DynamicProxy
namespace Spring.Aop.Framework.DynamicProxy;
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation
/// that delegates method calls to target object.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public class TargetAopProxyMethodBuilder : AbstractAopProxyMethodBuilder
{
/// <summary>
/// <see cref="Spring.Proxy.IProxyMethodBuilder"/> implementation
/// that delegates method calls to target object.
/// The local variable to store the target instance.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Bruno Baia</author>
public class TargetAopProxyMethodBuilder : AbstractAopProxyMethodBuilder
protected LocalBuilder target;
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="explicitImplementation">
/// <see langword="true"/> if the interface is to be
/// implemented explicitly; otherwise <see langword="false"/>.
/// </param>
/// <param name="targetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </param>
public TargetAopProxyMethodBuilder(TypeBuilder typeBuilder,
IAopProxyTypeGenerator aopProxyGenerator, bool explicitImplementation, IDictionary<string, MethodInfo> targetMethods)
: base(typeBuilder, aopProxyGenerator, explicitImplementation, targetMethods)
{
/// <summary>
/// The local variable to store the target instance.
/// </summary>
protected LocalBuilder target;
}
/// <summary>
/// Creates a new instance of the method builder.
/// </summary>
/// <param name="typeBuilder">The type builder to use.</param>
/// <param name="aopProxyGenerator">
/// The <see cref="IAopProxyTypeGenerator"/> implementation to use.
/// </param>
/// <param name="explicitImplementation">
/// <see langword="true"/> if the interface is to be
/// implemented explicitly; otherwise <see langword="false"/>.
/// </param>
/// <param name="targetMethods">
/// The dictionary to cache the list of target
/// <see cref="System.Reflection.MethodInfo"/>s.
/// </param>
public TargetAopProxyMethodBuilder(TypeBuilder typeBuilder,
IAopProxyTypeGenerator aopProxyGenerator, bool explicitImplementation, IDictionary<string, MethodInfo> targetMethods)
: base(typeBuilder, aopProxyGenerator, explicitImplementation, targetMethods)
{
}
/// <summary>
/// Creates local variable declarations.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected override void DeclareLocals(ILGenerator il, MethodInfo method)
{
base.DeclareLocals(il, method);
target = il.DeclareLocal(typeof(object));
/// <summary>
/// Creates local variable declarations.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
protected override void DeclareLocals(ILGenerator il, MethodInfo method)
{
base.DeclareLocals(il, method);
target = il.DeclareLocal(typeof(object));
#if DEBUG && !NETSTANDARD
target.SetLocalSymInfo("target");
target.SetLocalSymInfo("target");
#endif
}
}
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTarget(ILGenerator il)
{
il.Emit(OpCodes.Ldloc, target);
}
/// <summary>
/// Generates the IL instructions that pushes
/// the target instance on which calls should be delegated to.
/// </summary>
/// <param name="il">The IL generator to use.</param>
protected override void PushTarget(ILGenerator il)
{
il.Emit(OpCodes.Ldloc, target);
}
/// <summary>
/// Generates method logic.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void GenerateMethodLogic(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
il.EmitCall(OpCodes.Callvirt, References.GetTargetMethod, null);
il.Emit(OpCodes.Stloc, target);
/// <summary>
/// Generates method logic.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void GenerateMethodLogic(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
il.EmitCall(OpCodes.Callvirt, References.GetTargetMethod, null);
il.Emit(OpCodes.Stloc, target);
base.GenerateMethodLogic(il, method, interfaceMethod);
base.GenerateMethodLogic(il, method, interfaceMethod);
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
PushTarget(il);
il.EmitCall(OpCodes.Callvirt, References.GetReleaseTargetMethod, null);
}
PushAdvisedProxy(il);
il.Emit(OpCodes.Ldfld, References.TargetSourceField);
PushTarget(il);
il.EmitCall(OpCodes.Callvirt, References.GetReleaseTargetMethod, null);
}
/// <summary>
/// Calls proxied method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
if (interfaceMethod != null)
CallDirectTargetMethod(il, interfaceMethod);
else
CallDirectTargetMethod(il, method);
}
/// <summary>
/// Calls proxied method directly.
/// </summary>
/// <param name="il">The IL generator to use.</param>
/// <param name="method">The method to proxy.</param>
/// <param name="interfaceMethod">
/// The interface definition of the method, if applicable.
/// </param>
protected override void CallDirectProxiedMethod(
ILGenerator il, MethodInfo method, MethodInfo interfaceMethod)
{
if (interfaceMethod != null)
CallDirectTargetMethod(il, interfaceMethod);
else
CallDirectTargetMethod(il, method);
}
}

View File

@@ -21,89 +21,88 @@
using System.Reflection;
using System.Runtime.Serialization;
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/> implementation
/// that caches advisor chains on a per-advised-method basis.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class HashtableCachingAdvisorChainFactory : IAdvisorChainFactory
{
/// <summary>
/// <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/> implementation
/// that caches advisor chains on a per-advised-method basis.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public sealed class HashtableCachingAdvisorChainFactory : IAdvisorChainFactory
[NonSerialized] private Dictionary<MethodInfo, IList<object>> methodCache = new Dictionary<MethodInfo, IList<object>>();
[OnDeserializing]
private void OnDeserializing(StreamingContext c)
{
[NonSerialized]
private Dictionary<MethodInfo, IList<object>> methodCache = new Dictionary<MethodInfo, IList<object>>();
methodCache = new Dictionary<MethodInfo, IList<object>>();
}
[OnDeserializing]
private void OnDeserializing(StreamingContext c)
/// <summary>
/// Gets the list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </summary>
/// <param name="advised">The proxy configuration object.</param>
/// <param name="proxy">The object proxy.</param>
/// <param name="method">
/// The method for which the interceptors are to be evaluated.
/// </param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.
/// </param>
/// <returns>
/// The list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </returns>
public IList<object> GetInterceptors(IAdvised advised, object proxy, MethodInfo method, Type targetType)
{
if (!methodCache.TryGetValue(method, out var interceptors))
{
methodCache = new Dictionary<MethodInfo, IList<object>>();
}
/// <summary>
/// Gets the list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </summary>
/// <param name="advised">The proxy configuration object.</param>
/// <param name="proxy">The object proxy.</param>
/// <param name="method">
/// The method for which the interceptors are to be evaluated.
/// </param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.
/// </param>
/// <returns>
/// The list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </returns>
public IList<object> GetInterceptors(IAdvised advised, object proxy, MethodInfo method, Type targetType)
{
if (!methodCache.TryGetValue(method, out var interceptors))
lock (methodCache)
{
lock (methodCache)
if (!methodCache.TryGetValue(method, out interceptors))
{
if (!methodCache.TryGetValue(method, out interceptors))
{
interceptors = AdvisorChainFactoryUtils.CalculateInterceptors(advised, proxy, method, targetType);
methodCache[method] = interceptors;
}
interceptors = AdvisorChainFactoryUtils.CalculateInterceptors(advised, proxy, method, targetType);
methodCache[method] = interceptors;
}
}
return interceptors;
}
/// <summary>
/// Invoked when the first proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
public void Activated(AdvisedSupport source)
{
}
return interceptors;
}
/// <summary>
/// Invoked when advice is changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
public void AdviceChanged(AdvisedSupport source)
{
methodCache.Clear();
}
/// <summary>
/// Invoked when the first proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
public void Activated(AdvisedSupport source)
{
}
/// <summary>
/// Invoked when interfaces are changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
public void InterfacesChanged(AdvisedSupport source)
{
}
/// <summary>
/// Invoked when advice is changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
public void AdviceChanged(AdvisedSupport source)
{
methodCache.Clear();
}
/// <summary>
/// Invoked when interfaces are changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
public void InterfacesChanged(AdvisedSupport source)
{
}
}

View File

@@ -19,474 +19,472 @@
#endregion
using AopAlliance.Aop;
using Spring.Proxy;
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Configuration data for an AOP proxy factory.
/// </summary>
/// <remarks>
/// <p>
/// This configuration includes the
/// <see cref="AopAlliance.Intercept.IInterceptor"/>s,
/// <see cref="Spring.Aop.IAdvisor"/>s, and (any) proxied interfaces.
/// </p>
/// <p>
/// Any AOP proxy obtained from Spring.NET can be cast to this interface to
/// allow the manipulation of said proxy's AOP advice.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.Framework.AdvisedSupport"/>
[ProxyIgnore]
public interface IAdvised
{
/// <summary>
/// Configuration data for an AOP proxy factory.
/// Should proxies obtained from this configuration expose
/// the AOP proxy to the
/// <see cref="Spring.Aop.Framework.AopContext"/> class?
/// </summary>
/// <remarks>
/// <p>
/// This configuration includes the
/// <see cref="AopAlliance.Intercept.IInterceptor"/>s,
/// <see cref="Spring.Aop.IAdvisor"/>s, and (any) proxied interfaces.
/// </p>
/// <p>
/// Any AOP proxy obtained from Spring.NET can be cast to this interface to
/// allow the manipulation of said proxy's AOP advice.
/// This is useful if an advised object needs to call another advised
/// method on itself. (If it uses the <c>this</c> reference (<c>Me</c>
/// in Visual Basic.NET), the invocation will <b>not</b> be advised).
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.Framework.AdvisedSupport"/>
[ProxyIgnore]
public interface IAdvised
{
/// <summary>
/// Should proxies obtained from this configuration expose
/// the AOP proxy to the
/// <see cref="Spring.Aop.Framework.AopContext"/> class?
/// </summary>
/// <remarks>
/// <p>
/// This is useful if an advised object needs to call another advised
/// method on itself. (If it uses the <c>this</c> reference (<c>Me</c>
/// in Visual Basic.NET), the invocation will <b>not</b> be advised).
/// </p>
/// </remarks>
bool ExposeProxy { get; }
bool ExposeProxy { get; }
/// <summary>
/// Gets the
/// <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/>
/// implementation that will be used to get the interceptor
/// chains for the advised
/// <see cref="Spring.Aop.Framework.AdvisedSupport.Target"/>.
/// </summary>
/// <value>
/// The <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/>
/// implementation that will be used to get the interceptor
/// chains for the advised
/// <see cref="Spring.Aop.Framework.AdvisedSupport.Target"/>.
/// </value>
IAdvisorChainFactory AdvisorChainFactory { get; }
/// <summary>
/// Gets the
/// <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/>
/// implementation that will be used to get the interceptor
/// chains for the advised
/// <see cref="Spring.Aop.Framework.AdvisedSupport.Target"/>.
/// </summary>
/// <value>
/// The <see cref="Spring.Aop.Framework.IAdvisorChainFactory"/>
/// implementation that will be used to get the interceptor
/// chains for the advised
/// <see cref="Spring.Aop.Framework.AdvisedSupport.Target"/>.
/// </value>
IAdvisorChainFactory AdvisorChainFactory { get; }
/// <summary>
/// Is the target <see cref="System.Type"/> to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
bool ProxyTargetType { get; }
/// <summary>
/// Is the target <see cref="System.Type"/> to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
bool ProxyTargetType { get; }
/// <summary>
/// Is target type attributes, method attributes, method's return type attributes
/// and method's parameter attributes to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
bool ProxyTargetAttributes { get; }
/// <summary>
/// Is target type attributes, method attributes, method's return type attributes
/// and method's parameter attributes to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
bool ProxyTargetAttributes { get; }
/// <summary>
/// Returns the collection of <see cref="Spring.Aop.IAdvisor"/>
/// instances that have been applied to this proxy.
/// </summary>
/// <remarks>
/// <p>
/// Will never return <cref lang="null"/>, but may return an
/// empty array (in the case where no
/// <see cref="Spring.Aop.IAdvisor"/> instances have been applied to
/// this proxy).
/// </p>
/// </remarks>
/// <value>
/// The collection of <see cref="Spring.Aop.IAdvisor"/>
/// instances that have been applied to this proxy.
/// </value>
IList<IAdvisor> Advisors { get; }
/// <summary>
/// Returns the collection of <see cref="Spring.Aop.IAdvisor"/>
/// instances that have been applied to this proxy.
/// </summary>
/// <remarks>
/// <p>
/// Will never return <cref lang="null"/>, but may return an
/// empty array (in the case where no
/// <see cref="Spring.Aop.IAdvisor"/> instances have been applied to
/// this proxy).
/// </p>
/// </remarks>
/// <value>
/// The collection of <see cref="Spring.Aop.IAdvisor"/>
/// instances that have been applied to this proxy.
/// </value>
IList<IAdvisor> Advisors { get; }
/// <summary>
/// Returns the collection of <see cref="Spring.Aop.IIntroductionAdvisor"/>
/// instances that have been applied to this proxy.
/// </summary>
/// <remarks>
/// <p>
/// Will never return <cref lang="null"/>, but may return an
/// empty array (in the case where no
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> instances have been
/// applied to this proxy).
/// </p>
/// </remarks>
/// <value>
/// The collection of <see cref="Spring.Aop.IIntroductionAdvisor"/>
/// instances that have been applied to this proxy.
/// </value>
IList<IIntroductionAdvisor> Introductions { get; }
/// <summary>
/// Returns the collection of <see cref="Spring.Aop.IIntroductionAdvisor"/>
/// instances that have been applied to this proxy.
/// </summary>
/// <remarks>
/// <p>
/// Will never return <cref lang="null"/>, but may return an
/// empty array (in the case where no
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> instances have been
/// applied to this proxy).
/// </p>
/// </remarks>
/// <value>
/// The collection of <see cref="Spring.Aop.IIntroductionAdvisor"/>
/// instances that have been applied to this proxy.
/// </value>
IList<IIntroductionAdvisor> Introductions { get; }
/// <summary>
/// Returns the collection of interface <see cref="System.Type"/>s
/// to be (or that are being) proxied by this proxy.
/// </summary>
/// <value>
/// The collection of interface <see cref="System.Type"/>s
/// to be (or that are being) proxied by this proxy.
/// </value>
IList<Type> Interfaces { get; }
/// <summary>
/// Returns the collection of interface <see cref="System.Type"/>s
/// to be (or that are being) proxied by this proxy.
/// </summary>
/// <value>
/// The collection of interface <see cref="System.Type"/>s
/// to be (or that are being) proxied by this proxy.
/// </value>
IList<Type> Interfaces { get; }
/// <summary>
/// Returns the mapping of the proxied interface
/// <see cref="System.Type"/>s to their delegates.
/// </summary>
/// <value>
/// The mapping of the proxied interface
/// <see cref="System.Type"/>s to their delegates.
/// </value>
IDictionary<Type, object> InterfaceMap { get; }
/// <summary>
/// Returns the mapping of the proxied interface
/// <see cref="System.Type"/>s to their delegates.
/// </summary>
/// <value>
/// The mapping of the proxied interface
/// <see cref="System.Type"/>s to their delegates.
/// </value>
IDictionary<Type, object> InterfaceMap { get; }
/// <summary>
/// Is this configuration frozen?
/// </summary>
/// <remarks>
/// <p>
/// When a config is frozen, no advice changes can be made. This is
/// useful for optimization, and useful when we don't want callers
/// to be able to manipulate configuration after casting to
/// <see cref="Spring.Aop.Framework.IAdvised"/>.
/// </p>
/// </remarks>
bool IsFrozen { get; }
/// <summary>
/// Is this configuration frozen?
/// </summary>
/// <remarks>
/// <p>
/// When a config is frozen, no advice changes can be made. This is
/// useful for optimization, and useful when we don't want callers
/// to be able to manipulate configuration after casting to
/// <see cref="Spring.Aop.Framework.IAdvised"/>.
/// </p>
/// </remarks>
bool IsFrozen { get; }
/// <summary>
/// Returns the <see cref="Spring.Aop.ITargetSource"/> used by this
/// <see cref="Spring.Aop.Framework.IAdvised"/> object.
/// </summary>
/// <value>
/// The <see cref="Spring.Aop.ITargetSource"/> used by this
/// <see cref="Spring.Aop.Framework.IAdvised"/> object.
/// </value>
ITargetSource TargetSource { get; }
/// <summary>
/// Returns the <see cref="Spring.Aop.ITargetSource"/> used by this
/// <see cref="Spring.Aop.Framework.IAdvised"/> object.
/// </summary>
/// <value>
/// The <see cref="Spring.Aop.ITargetSource"/> used by this
/// <see cref="Spring.Aop.Framework.IAdvised"/> object.
/// </value>
ITargetSource TargetSource { get; }
/// <summary>
/// Returns a boolean specifying if this <see cref="IAdvised"/>
/// instance can be serialized.
/// </summary>
/// <value>
/// <c>true</c> if this instance can be serialized, <c>false</c> otherwise.
/// </value>
bool IsSerializable { get; }
/// <summary>
/// Returns a boolean specifying if this <see cref="IAdvised"/>
/// instance can be serialized.
/// </summary>
/// <value>
/// <c>true</c> if this instance can be serialized, <c>false</c> otherwise.
/// </value>
bool IsSerializable { get; }
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the end (or tail)
/// of the advice (interceptor) chain.
/// </summary>
/// <remarks>
/// <p>
/// Please be aware that Spring.NET's AOP implementation only supports
/// method advice (as encapsulated by the
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> interface).
/// </p>
/// </remarks>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(int,IAdvice)"/>
void AddAdvice(IAdvice advice);
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the end (or tail)
/// of the advice (interceptor) chain.
/// </summary>
/// <remarks>
/// <p>
/// Please be aware that Spring.NET's AOP implementation only supports
/// method advice (as encapsulated by the
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> interface).
/// </p>
/// </remarks>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(int,IAdvice)"/>
void AddAdvice(IAdvice advice);
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the supplied
/// <paramref name="position"/> in the advice (interceptor) chain.
/// </summary>
/// <remarks>
/// <p>
/// Please be aware that Spring.NET's AOP implementation only supports
/// method advice (as encapsulated by the
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> interface).
/// </p>
/// </remarks>
/// <param name="position">
/// The zero (0) indexed position (from the head) at which the
/// supplied <paramref name="advice"/> is to be inserted into the
/// advice (interceptor) chain.
/// </param>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(IAdvice)"/>
void AddAdvice(int position, IAdvice advice);
/// <summary>
/// Adds the supplied <paramref name="advice"/> to the supplied
/// <paramref name="position"/> in the advice (interceptor) chain.
/// </summary>
/// <remarks>
/// <p>
/// Please be aware that Spring.NET's AOP implementation only supports
/// method advice (as encapsulated by the
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> interface).
/// </p>
/// </remarks>
/// <param name="position">
/// The zero (0) indexed position (from the head) at which the
/// supplied <paramref name="advice"/> is to be inserted into the
/// advice (interceptor) chain.
/// </param>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to be added.
/// </param>
/// <seealso cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// <seealso cref="Spring.Aop.Framework.IAdvised.AddAdvice(IAdvice)"/>
void AddAdvice(int position, IAdvice advice);
/// <summary>
/// Is the supplied <paramref name="intf"/> (interface)
/// <see cref="System.Type"/> proxied?
/// </summary>
/// <param name="intf">
/// The interface <see cref="System.Type"/> to test.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="intf"/>
/// (interface) <see cref="System.Type"/> is proxied;
/// <see langword="false"/> if not or the supplied
/// <paramref name="intf"/> is <cref lang="null"/>.
/// </returns>
bool IsInterfaceProxied(Type intf);
/// <summary>
/// Is the supplied <paramref name="intf"/> (interface)
/// <see cref="System.Type"/> proxied?
/// </summary>
/// <param name="intf">
/// The interface <see cref="System.Type"/> to test.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="intf"/>
/// (interface) <see cref="System.Type"/> is proxied;
/// <see langword="false"/> if not or the supplied
/// <paramref name="intf"/> is <cref lang="null"/>.
/// </returns>
bool IsInterfaceProxied(Type intf);
/// <summary>
/// Adds the advisors from the supplied <paramref name="advisors"/>
/// to the list of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="advisors">
/// The <see cref="IAdvisors"/> to add advisors from.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisors"/> cannot be added.
/// </exception>
void AddAdvisors(IAdvisors advisors);
/// <summary>
/// Adds the advisors from the supplied <paramref name="advisors"/>
/// to the list of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="advisors">
/// The <see cref="IAdvisors"/> to add advisors from.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisors"/> cannot be added.
/// </exception>
void AddAdvisors(IAdvisors advisors);
/// <summary>
/// Adds the supplied <paramref name="advisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisor"/> cannot be added.
/// </exception>
void AddAdvisor(IAdvisor advisor);
/// <summary>
/// Adds the supplied <paramref name="advisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisor"/> cannot be added.
/// </exception>
void AddAdvisor(IAdvisor advisor);
/// <summary>
/// Adds the supplied <paramref name="advisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="index">
/// The index in the <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>
/// list at which the supplied <paramref name="advisor"/>
/// is to be inserted.
/// </param>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisor"/> cannot be added.
/// </exception>
void AddAdvisor(int index, IAdvisor advisor);
/// <summary>
/// Adds the supplied <paramref name="advisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="index">
/// The index in the <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>
/// list at which the supplied <paramref name="advisor"/>
/// is to be inserted.
/// </param>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisor"/> cannot be added.
/// </exception>
void AddAdvisor(int index, IAdvisor advisor);
/// <summary>
/// Adds the supplied <paramref name="introductionAdvisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>.
/// </summary>
/// <param name="introductionAdvisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="introductionAdvisor"/> cannot be added.
/// </exception>
void AddIntroduction(IIntroductionAdvisor introductionAdvisor);
/// <summary>
/// Adds the supplied <paramref name="introductionAdvisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>.
/// </summary>
/// <param name="introductionAdvisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="introductionAdvisor"/> cannot be added.
/// </exception>
void AddIntroduction(IIntroductionAdvisor introductionAdvisor);
/// <summary>
/// Adds the supplied <paramref name="introductionAdvisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>.
/// </summary>
/// <param name="index">
/// The index in the <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// list at which the supplied <paramref name="introductionAdvisor"/>
/// is to be inserted.
/// </param>
/// <param name="introductionAdvisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="introductionAdvisor"/> cannot be added.
/// </exception>
void AddIntroduction(int index, IIntroductionAdvisor introductionAdvisor);
/// <summary>
/// Adds the supplied <paramref name="introductionAdvisor"/> to the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>.
/// </summary>
/// <param name="index">
/// The index in the <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// list at which the supplied <paramref name="introductionAdvisor"/>
/// is to be inserted.
/// </param>
/// <param name="introductionAdvisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to add.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="introductionAdvisor"/> cannot be added.
/// </exception>
void AddIntroduction(int index, IIntroductionAdvisor introductionAdvisor);
/// <summary>
/// Return the index (0 based) of the supplied
/// <see cref="Spring.Aop.IAdvisor"/> in the interceptor
/// (advice) chain for this proxy.
/// </summary>
/// <remarks>
/// <p>
/// The return value of this method can be used to index into
/// the <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>
/// list.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IAdvisor"/> to search for.
/// </param>
/// <returns>
/// The zero (0) based index of this advisor, or -1 if the
/// supplied <paramref name="advisor"/> is not an advisor for this
/// proxy.
/// </returns>
int IndexOf(IAdvisor advisor);
/// <summary>
/// Return the index (0 based) of the supplied
/// <see cref="Spring.Aop.IAdvisor"/> in the interceptor
/// (advice) chain for this proxy.
/// </summary>
/// <remarks>
/// <p>
/// The return value of this method can be used to index into
/// the <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>
/// list.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IAdvisor"/> to search for.
/// </param>
/// <returns>
/// The zero (0) based index of this advisor, or -1 if the
/// supplied <paramref name="advisor"/> is not an advisor for this
/// proxy.
/// </returns>
int IndexOf(IAdvisor advisor);
/// <summary>
/// Return the index (0 based) of the supplied
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> in the introductions
/// for this proxy.
/// </summary>
/// <remarks>
/// <p>
/// The return value of this method can be used to index into
/// the <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// list.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to search for.
/// </param>
/// <returns>
/// The zero (0) based index of this advisor, or -1 if the
/// supplied <paramref name="advisor"/> is not an introduction advisor
/// for this proxy.
/// </returns>
int IndexOf(IIntroductionAdvisor advisor);
/// <summary>
/// Return the index (0 based) of the supplied
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> in the introductions
/// for this proxy.
/// </summary>
/// <remarks>
/// <p>
/// The return value of this method can be used to index into
/// the <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// list.
/// </p>
/// </remarks>
/// <param name="advisor">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to search for.
/// </param>
/// <returns>
/// The zero (0) based index of this advisor, or -1 if the
/// supplied <paramref name="advisor"/> is not an introduction advisor
/// for this proxy.
/// </returns>
int IndexOf(IIntroductionAdvisor advisor);
/// <summary>
/// Removes the supplied <paramref name="advisor"/> the list of advisors
/// for this proxy.
/// </summary>
/// <param name="advisor">The advisor to remove.</param>
/// <returns>
/// <see langword="true"/> if advisor was found in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Advisors"/> for this
/// proxy and was successfully removed; <see langword="false"/> if not
/// or if the supplied <paramref name="advisor"/> is <cref lang="null"/>.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisor"/> cannot be removed.
/// </exception>
bool RemoveAdvisor(IAdvisor advisor);
/// <summary>
/// Removes the supplied <paramref name="advisor"/> the list of advisors
/// for this proxy.
/// </summary>
/// <param name="advisor">The advisor to remove.</param>
/// <returns>
/// <see langword="true"/> if advisor was found in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Advisors"/> for this
/// proxy and was successfully removed; <see langword="false"/> if not
/// or if the supplied <paramref name="advisor"/> is <cref lang="null"/>.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="advisor"/> cannot be removed.
/// </exception>
bool RemoveAdvisor(IAdvisor advisor);
/// <summary>
/// Removes the <see cref="Spring.Aop.IAdvisor"/> at the supplied
/// <paramref name="index"/> in the
/// <see cref="Spring.Aop.Framework.IAdvised.Advisors"/> list
/// from the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Advisors"/> for this proxy.
/// </summary>
/// <param name="index">
/// The index of the <see cref="Spring.Aop.IAdvisor"/> to remove.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="Spring.Aop.IAdvisor"/> at the supplied <paramref name="index"/>
/// cannot be removed; or if the supplied <paramref name="index"/> is out of
/// range.
/// </exception>
void RemoveAdvisor(int index);
/// <summary>
/// Removes the <see cref="Spring.Aop.IAdvisor"/> at the supplied
/// <paramref name="index"/> in the
/// <see cref="Spring.Aop.Framework.IAdvised.Advisors"/> list
/// from the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Advisors"/> for this proxy.
/// </summary>
/// <param name="index">
/// The index of the <see cref="Spring.Aop.IAdvisor"/> to remove.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="Spring.Aop.IAdvisor"/> at the supplied <paramref name="index"/>
/// cannot be removed; or if the supplied <paramref name="index"/> is out of
/// range.
/// </exception>
void RemoveAdvisor(int index);
/// <summary>
/// Removes the supplied <paramref name="advice"/> from the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to remove.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> was
/// found in the list of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>
/// and successfully removed.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="AopAlliance.Aop.IAdvice"/> cannot be removed.
/// </exception>
bool RemoveAdvice(IAdvice advice);
/// <summary>
/// Removes the supplied <paramref name="advice"/> from the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>.
/// </summary>
/// <param name="advice">
/// The <see cref="AopAlliance.Aop.IAdvice"/> to remove.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="advice"/> was
/// found in the list of <see cref="Spring.Aop.Framework.IAdvised.Advisors"/>
/// and successfully removed.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="AopAlliance.Aop.IAdvice"/> cannot be removed.
/// </exception>
bool RemoveAdvice(IAdvice advice);
/// <summary>
/// Removes the supplied <paramref name="introduction"/> from the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>.
/// </summary>
/// <param name="introduction">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to remove.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="introduction"/> was
/// found in the list of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// and successfully removed.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> cannot be removed.
/// </exception>
bool RemoveIntroduction(IIntroductionAdvisor introduction);
/// <summary>
/// Removes the supplied <paramref name="introduction"/> from the list
/// of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>.
/// </summary>
/// <param name="introduction">
/// The <see cref="Spring.Aop.IIntroductionAdvisor"/> to remove.
/// </param>
/// <returns>
/// <see langword="true"/> if the supplied <paramref name="introduction"/> was
/// found in the list of <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// and successfully removed.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> cannot be removed.
/// </exception>
bool RemoveIntroduction(IIntroductionAdvisor introduction);
/// <summary>
/// Removes the <see cref="Spring.Aop.IIntroductionAdvisor"/> at the supplied
/// <paramref name="index"/> in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Introductions"/> for this proxy.
/// </summary>
/// <param name="index">The index of the advisor to remove.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> at the supplied
/// <paramref name="index"/> cannot be removed; or if the supplied
/// <paramref name="index"/> is out of range.
/// </exception>
void RemoveIntroduction(int index);
/// <summary>
/// Removes the <see cref="Spring.Aop.IIntroductionAdvisor"/> at the supplied
/// <paramref name="index"/> in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Introductions"/> for this proxy.
/// </summary>
/// <param name="index">The index of the advisor to remove.
/// </param>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <see cref="Spring.Aop.IIntroductionAdvisor"/> at the supplied
/// <paramref name="index"/> cannot be removed; or if the supplied
/// <paramref name="index"/> is out of range.
/// </exception>
void RemoveIntroduction(int index);
/// <summary>
/// Replaces the <see cref="Spring.Aop.IIntroductionAdvisor"/> that
/// exists at the supplied <paramref name="index"/> in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// with the supplied <paramref name="introduction"/>.
/// </summary>
/// <param name="index">
/// The index of the <see cref="Spring.Aop.IIntroductionAdvisor"/>
/// in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// that is to be replaced.
/// </param>
/// <param name="introduction">
/// The new (replacement) <see cref="Spring.Aop.IIntroductionAdvisor"/>.
/// </param>
/// <exception cref="AopConfigException">
/// If the supplied <paramref name="index"/> is out of range.
/// </exception>
void ReplaceIntroduction(int index, IIntroductionAdvisor introduction);
/// <summary>
/// Replaces the <see cref="Spring.Aop.IIntroductionAdvisor"/> that
/// exists at the supplied <paramref name="index"/> in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// with the supplied <paramref name="introduction"/>.
/// </summary>
/// <param name="index">
/// The index of the <see cref="Spring.Aop.IIntroductionAdvisor"/>
/// in the list of
/// <see cref="Spring.Aop.Framework.IAdvised.Introductions"/>
/// that is to be replaced.
/// </param>
/// <param name="introduction">
/// The new (replacement) <see cref="Spring.Aop.IIntroductionAdvisor"/>.
/// </param>
/// <exception cref="AopConfigException">
/// If the supplied <paramref name="index"/> is out of range.
/// </exception>
void ReplaceIntroduction(int index, IIntroductionAdvisor introduction);
/// <summary>
/// Replaces the <paramref name="oldAdvisor"/> with the
/// <paramref name="newAdvisor"/>.
/// </summary>
/// <param name="oldAdvisor">
/// The original (old) advisor to be replaced.
/// </param>
/// <param name="newAdvisor">
/// The new advisor to replace the <paramref name="oldAdvisor"/> with.
/// </param>
/// <returns>
/// <see langword="true"/> if the <paramref name="oldAdvisor"/> was
/// replaced; if the <paramref name="oldAdvisor"/> was not found in the
/// advisors collection, this method returns <see langword="false"/>
/// and (effectively) does nothing.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="oldAdvisor"/> cannot be replaced.
/// </exception>
/// <seealso cref="Spring.Aop.Framework.ProxyConfig.IsFrozen"/>
bool ReplaceAdvisor(IAdvisor oldAdvisor, IAdvisor newAdvisor);
/// <summary>
/// Replaces the <paramref name="oldAdvisor"/> with the
/// <paramref name="newAdvisor"/>.
/// </summary>
/// <param name="oldAdvisor">
/// The original (old) advisor to be replaced.
/// </param>
/// <param name="newAdvisor">
/// The new advisor to replace the <paramref name="oldAdvisor"/> with.
/// </param>
/// <returns>
/// <see langword="true"/> if the <paramref name="oldAdvisor"/> was
/// replaced; if the <paramref name="oldAdvisor"/> was not found in the
/// advisors collection, this method returns <see langword="false"/>
/// and (effectively) does nothing.
/// </returns>
/// <exception cref="AopConfigException">
/// If this proxy configuration is frozen and the
/// <paramref name="oldAdvisor"/> cannot be replaced.
/// </exception>
/// <seealso cref="Spring.Aop.Framework.ProxyConfig.IsFrozen"/>
bool ReplaceAdvisor(IAdvisor oldAdvisor, IAdvisor newAdvisor);
/// <summary>
/// As <see cref="System.Object.ToString()"/> will normally be passed
/// straight through to the advised target, this method returns the
/// <see cref="System.Object.ToString()"/> equivalent for the AOP
/// proxy itself.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> description of the proxy configuration.
/// </returns>
string ToProxyConfigString();
}
/// <summary>
/// As <see cref="System.Object.ToString()"/> will normally be passed
/// straight through to the advised target, this method returns the
/// <see cref="System.Object.ToString()"/> equivalent for the AOP
/// proxy itself.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> description of the proxy configuration.
/// </returns>
string ToProxyConfigString();
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -18,46 +18,45 @@
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Callback interface for
/// <see cref="Spring.Aop.Framework.AdvisedSupport"/> listeners.
/// </summary>
/// <remarks>
/// <p>
/// Allows <see cref="Spring.Aop.Framework.IAdvisedSupportListener"/>
/// implementations to be notified of notable lifecycle events relating
/// to the creation of a proxy, and changes to the configuration data of a
/// proxy.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisedSupportListener
{
/// <summary>
/// Callback interface for
/// <see cref="Spring.Aop.Framework.AdvisedSupport"/> listeners.
/// </summary>
/// <remarks>
/// <p>
/// Allows <see cref="Spring.Aop.Framework.IAdvisedSupportListener"/>
/// implementations to be notified of notable lifecycle events relating
/// to the creation of a proxy, and changes to the configuration data of a
/// proxy.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisedSupportListener
{
/// <summary>
/// Invoked when the first proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
void Activated(AdvisedSupport source);
/// <summary>
/// Invoked when the first proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
void Activated(AdvisedSupport source);
/// <summary>
/// Invoked when advice is changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
void AdviceChanged(AdvisedSupport source);
/// <summary>
/// Invoked when advice is changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
void AdviceChanged(AdvisedSupport source);
/// <summary>
/// Invoked when interfaces are changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
void InterfacesChanged(AdvisedSupport source);
}
}
/// <summary>
/// Invoked when interfaces are changed after a proxy is created.
/// </summary>
/// <param name="source">
/// The relevant <see cref="Spring.Aop.Framework.AdvisedSupport"/> source.
/// </param>
void InterfacesChanged(AdvisedSupport source);
}

View File

@@ -24,33 +24,32 @@ using System.Reflection;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Factory interface for advisor chains.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisorChainFactory : IAdvisedSupportListener
{
/// <summary>
/// Factory interface for advisor chains.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisorChainFactory : IAdvisedSupportListener
{
/// <summary>
/// Gets the list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </summary>
/// <param name="advised">The proxy configuration object.</param>
/// <param name="proxy">The object proxy.</param>
/// <param name="method">
/// The method for which the interceptors are to be evaluated.
/// </param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.
/// </param>
/// <returns>
/// The list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </returns>
IList<object> GetInterceptors(IAdvised advised, object proxy, MethodInfo method, Type targetType);
}
/// <summary>
/// Gets the list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </summary>
/// <param name="advised">The proxy configuration object.</param>
/// <param name="proxy">The object proxy.</param>
/// <param name="method">
/// The method for which the interceptors are to be evaluated.
/// </param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.
/// </param>
/// <returns>
/// The list of <see cref="AopAlliance.Intercept.IInterceptor"/> and
/// <see cref="Spring.Aop.Framework.InterceptorAndDynamicMethodMatcher"/>
/// instances for the supplied <paramref name="proxy"/>.
/// </returns>
IList<object> GetInterceptors(IAdvised advised, object proxy, MethodInfo method, Type targetType);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -24,19 +24,18 @@ using Spring.Proxy;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// The central interface for Spring.NET based AOP proxies.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[ProxyIgnore]
public interface IAopProxy
{
/// <summary>
/// The central interface for Spring.NET based AOP proxies.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[ProxyIgnore]
public interface IAopProxy
{
/// <summary>
/// Creates a new proxy object.
/// </summary>
object GetProxy();
}
}
/// <summary>
/// Creates a new proxy object.
/// </summary>
object GetProxy();
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -18,27 +18,26 @@
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Factory interface for the creation of AOP proxies based on
/// <see cref="Spring.Aop.Framework.AdvisedSupport"/> configuration
/// objects.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAopProxyFactory
{
/// <summary>
/// Factory interface for the creation of AOP proxies based on
/// <see cref="Spring.Aop.Framework.AdvisedSupport"/> configuration
/// objects.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAopProxyFactory
{
/// <summary>
/// Creates an <see cref="Spring.Aop.Framework.IAopProxy"/> for the
/// supplied <paramref name="advisedSupport"/> configuration.
/// </summary>
/// <param name="advisedSupport">The AOP configuration.</param>
/// <returns>An <see cref="Spring.Aop.Framework.IAopProxy"/>.</returns>
/// <exception cref="AopConfigException">
/// If the supplied <paramref name="advisedSupport"/> configuration is
/// invalid.
/// </exception>
IAopProxy CreateAopProxy(AdvisedSupport advisedSupport);
}
}
/// <summary>
/// Creates an <see cref="Spring.Aop.Framework.IAopProxy"/> for the
/// supplied <paramref name="advisedSupport"/> configuration.
/// </summary>
/// <param name="advisedSupport">The AOP configuration.</param>
/// <returns>An <see cref="Spring.Aop.Framework.IAopProxy"/>.</returns>
/// <exception cref="AopConfigException">
/// If the supplied <paramref name="advisedSupport"/> configuration is
/// invalid.
/// </exception>
IAopProxy CreateAopProxy(AdvisedSupport advisedSupport);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -18,26 +18,25 @@
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Provides access to the target object of an AOP proxy.
/// </summary>
/// <remarks>
/// <p>
/// To be implemented by introduction aspects in order to obtain access to
/// the target object.
/// </p>
/// </remarks>
/// <author>Aleksandar Seovic</author>
public interface ITargetAware
{
/// <summary>
/// Provides access to the target object of an AOP proxy.
/// Sets the <see cref="Spring.Aop.Framework.IAopProxy"/> target object.
/// </summary>
/// <remarks>
/// <p>
/// To be implemented by introduction aspects in order to obtain access to
/// the target object.
/// </p>
/// </remarks>
/// <author>Aleksandar Seovic</author>
public interface ITargetAware
IAopProxy TargetProxy
{
/// <summary>
/// Sets the <see cref="Spring.Aop.Framework.IAopProxy"/> target object.
/// </summary>
IAopProxy TargetProxy
{
set;
}
set;
}
}
}

View File

@@ -20,26 +20,24 @@
using AopAlliance.Intercept;
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary> Internal framework class.
/// This class is required because if we put an interceptor that implements IInterceptionAdvice
/// in the interceptor list passed to MethodInvocation, it may be mistaken for an
/// advice that requires dynamic method matching.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.Net)</author>
[Serializable]
internal class InterceptorAndDynamicMethodMatcher
{
/// <summary> Internal framework class.
/// This class is required because if we put an interceptor that implements IInterceptionAdvice
/// in the interceptor list passed to MethodInvocation, it may be mistaken for an
/// advice that requires dynamic method matching.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.Net)</author>
[Serializable]
internal class InterceptorAndDynamicMethodMatcher
{
internal IMethodMatcher MethodMatcher;
internal IMethodInterceptor Interceptor;
public InterceptorAndDynamicMethodMatcher(IMethodInterceptor interceptor, IMethodMatcher methodMatcher)
{
this.Interceptor = interceptor;
this.MethodMatcher = methodMatcher;
}
}
internal IMethodMatcher MethodMatcher;
internal IMethodInterceptor Interceptor;
public InterceptorAndDynamicMethodMatcher(IMethodInterceptor interceptor, IMethodMatcher methodMatcher)
{
this.Interceptor = interceptor;
this.MethodMatcher = methodMatcher;
}
}

View File

@@ -16,222 +16,220 @@
using System.Runtime.Serialization;
using System.Text;
using Spring.Util;
using Spring.Reflection.Dynamic;
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Convenience superclass for configuration used in creating proxies,
/// to ensure that all proxy creators have consistent properties.
/// </summary>
/// <remarks>
/// <p>
/// Note that it is no longer possible to configure subclasses to
/// expose the <see cref="AopAlliance.Intercept.IMethodInvocation"/>.
/// Interceptors should normally manage their own thread locals if they
/// need to make resources available to advised objects. If it is
/// absolutely necessary to expose the
/// <see cref="AopAlliance.Intercept.IMethodInvocation"/>, use an
/// interceptor to do so.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class ProxyConfig : ISerializable
{
/// <summary>
/// Convenience superclass for configuration used in creating proxies,
/// to ensure that all proxy creators have consistent properties.
/// </summary>
/// <remarks>
/// <p>
/// Note that it is no longer possible to configure subclasses to
/// expose the <see cref="AopAlliance.Intercept.IMethodInvocation"/>.
/// Interceptors should normally manage their own thread locals if they
/// need to make resources available to advised objects. If it is
/// absolutely necessary to expose the
/// <see cref="AopAlliance.Intercept.IMethodInvocation"/>, use an
/// interceptor to do so.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class ProxyConfig : ISerializable
private static readonly IDynamicConstructor cachedAopProxyFactoryDynCtor =
new SafeConstructor(typeof(ProxyConfig).Assembly.GetType("Spring.Aop.Framework.DynamicProxy.CachedAopProxyFactory", false, false).GetConstructor(Type.EmptyTypes));
private bool proxyTargetType;
private bool proxyTargetAttributes = true;
private bool optimize;
private bool frozen;
private IAopProxyFactory aopProxyFactory = cachedAopProxyFactoryDynCtor.Invoke(ObjectUtils.EmptyObjects) as IAopProxyFactory;
private bool exposeProxy;
private readonly object syncRoot = new object();
/// <inheritdoc />
public ProxyConfig()
{
private static readonly IDynamicConstructor cachedAopProxyFactoryDynCtor =
new SafeConstructor(typeof(ProxyConfig).Assembly.GetType("Spring.Aop.Framework.DynamicProxy.CachedAopProxyFactory", false, false).GetConstructor(Type.EmptyTypes));
}
private bool proxyTargetType;
private bool proxyTargetAttributes = true;
private bool optimize;
private bool frozen;
/// <inheritdoc />
protected ProxyConfig(SerializationInfo info, StreamingContext context)
{
proxyTargetType = info.GetBoolean("proxyTargetType");
proxyTargetAttributes = info.GetBoolean("proxyTargetAttributes");
optimize = info.GetBoolean("optimize");
frozen = info.GetBoolean("frozen");
exposeProxy = info.GetBoolean("exposeProxy");
syncRoot = info.GetValue("syncRoot", typeof(object));
}
private IAopProxyFactory aopProxyFactory = cachedAopProxyFactoryDynCtor.Invoke(ObjectUtils.EmptyObjects) as IAopProxyFactory;
/// <inheritdoc />
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("proxyTargetType", proxyTargetType);
info.AddValue("proxyTargetAttributes", proxyTargetAttributes);
info.AddValue("optimize", optimize);
info.AddValue("frozen", frozen);
info.AddValue("exposeProxy", exposeProxy);
info.AddValue("syncRoot", syncRoot);
}
private bool exposeProxy;
private readonly object syncRoot = new object();
/// <summary>
/// Use to synchronize access to this ProxyConfig instance
/// </summary>
public object SyncRoot
{
get { return syncRoot; }
}
/// <inheritdoc />
public ProxyConfig()
{
}
/// <summary>
/// Is the target <see cref="System.Type"/> to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
public virtual bool ProxyTargetType
{
get { return this.proxyTargetType; }
set { this.proxyTargetType = value; }
}
/// <inheritdoc />
protected ProxyConfig(SerializationInfo info, StreamingContext context)
{
proxyTargetType = info.GetBoolean("proxyTargetType");
proxyTargetAttributes = info.GetBoolean("proxyTargetAttributes");
optimize = info.GetBoolean("optimize");
frozen = info.GetBoolean("frozen");
exposeProxy = info.GetBoolean("exposeProxy");
syncRoot = info.GetValue("syncRoot", typeof(object));
}
/// <summary>
/// Is target type attributes, method attributes, method's return type attributes
/// and method's parameter attributes to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
public virtual bool ProxyTargetAttributes
{
get { return this.proxyTargetAttributes; }
set { this.proxyTargetAttributes = value; }
}
/// <inheritdoc />
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("proxyTargetType", proxyTargetType);
info.AddValue("proxyTargetAttributes", proxyTargetAttributes);
info.AddValue("optimize", optimize);
info.AddValue("frozen", frozen);
info.AddValue("exposeProxy", exposeProxy);
info.AddValue("syncRoot", syncRoot);
}
/// <summary>
/// Are any <i>agressive optimizations</i> to be performed?
/// </summary>
/// <remarks>
/// <p>
/// The exact meaning of <i>agressive optimizations</i> will differ
/// between proxies, but there is usually some tradeoff.
/// </p>
/// <p>
/// For example, optimization will usually mean that advice changes
/// won't take effect after a proxy has been created. For this reason,
/// optimization is disabled by default. An optimize value of
/// <see langword="true"/> may be ignored if other settings preclude
/// optimization: for example, if the
/// <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// is set to <see langword="true"/> and such a value is not compatible
/// with the optimization.
/// </p>
/// <p>
/// The default is <see langword="false"/>.
/// </p>
/// </remarks>
public virtual bool Optimize
{
get { return this.optimize; }
set { this.optimize = value; }
}
/// <summary>
/// Use to synchronize access to this ProxyConfig instance
/// </summary>
public object SyncRoot
{
get { return syncRoot; }
}
/// <summary>
/// Should proxies obtained from this configuration expose
/// the AOP proxy to the
/// <see cref="Spring.Aop.Framework.AopContext"/> class?
/// </summary>
/// <remarks>
/// <p>
/// The default is <see langword="false"/>, as enabling this property
/// may impair performance.
/// </p>
/// </remarks>
public bool ExposeProxy
{
get { return this.exposeProxy; }
set { this.exposeProxy = value; }
}
/// <summary>
/// Is the target <see cref="System.Type"/> to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
public virtual bool ProxyTargetType
{
get { return this.proxyTargetType; }
set { this.proxyTargetType = value; }
}
/// <summary>
/// Gets and set the factory to be used to create AOP proxies.
/// </summary>
/// <remarks>
/// <p>
/// This obviously allows one to customise the
/// <see cref="Spring.Aop.Framework.IAopProxyFactory"/> implementation,
/// allowing different strategies to be dropped in without changing the
/// core framework. For example, an
/// <see cref="Spring.Aop.Framework.IAopProxyFactory"/> implementation
/// could return an <see cref="Spring.Aop.Framework.IAopProxy"/>
/// using remoting proxies, <c>Reflection.Emit</c> or a code generation
/// strategy.
/// </p>
/// </remarks>
public virtual IAopProxyFactory AopProxyFactory
{
get { return this.aopProxyFactory; }
set { this.aopProxyFactory = value; }
}
/// <summary>
/// Is target type attributes, method attributes, method's return type attributes
/// and method's parameter attributes to be proxied in addition
/// to any interfaces declared on the proxied <see cref="System.Type"/>?
/// </summary>
public virtual bool ProxyTargetAttributes
{
get { return this.proxyTargetAttributes; }
set { this.proxyTargetAttributes = value; }
}
/// <summary>
/// Is this configuration frozen?
/// </summary>
/// <remarks>
/// <p>
/// The default is not frozen.
/// </p>
/// </remarks>
public virtual bool IsFrozen
{
get { return this.frozen; }
set { this.frozen = value; }
}
/// <summary>
/// Are any <i>agressive optimizations</i> to be performed?
/// </summary>
/// <remarks>
/// <p>
/// The exact meaning of <i>agressive optimizations</i> will differ
/// between proxies, but there is usually some tradeoff.
/// </p>
/// <p>
/// For example, optimization will usually mean that advice changes
/// won't take effect after a proxy has been created. For this reason,
/// optimization is disabled by default. An optimize value of
/// <see langword="true"/> may be ignored if other settings preclude
/// optimization: for example, if the
/// <see cref="Spring.Aop.Framework.ProxyConfig.ExposeProxy"/> property
/// is set to <see langword="true"/> and such a value is not compatible
/// with the optimization.
/// </p>
/// <p>
/// The default is <see langword="false"/>.
/// </p>
/// </remarks>
public virtual bool Optimize
{
get { return this.optimize; }
set { this.optimize = value; }
}
/// <summary>
/// Copies the configuration from the supplied
/// <paramref name="otherConfiguration"/> into this instance.
/// </summary>
/// <param name="otherConfiguration">
/// The configuration to be copied.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="otherConfiguration"/> is
/// <see langword="null"/>.
/// </exception>
public virtual void CopyFrom(ProxyConfig otherConfiguration)
{
AssertUtils.ArgumentNotNull(otherConfiguration, "otherConfiguration");
/// <summary>
/// Should proxies obtained from this configuration expose
/// the AOP proxy to the
/// <see cref="Spring.Aop.Framework.AopContext"/> class?
/// </summary>
/// <remarks>
/// <p>
/// The default is <see langword="false"/>, as enabling this property
/// may impair performance.
/// </p>
/// </remarks>
public bool ExposeProxy
{
get { return this.exposeProxy; }
set { this.exposeProxy = value; }
}
this.optimize = otherConfiguration.optimize;
this.proxyTargetType = otherConfiguration.proxyTargetType;
this.proxyTargetAttributes = otherConfiguration.proxyTargetAttributes;
this.exposeProxy = otherConfiguration.exposeProxy;
this.frozen = otherConfiguration.frozen;
this.aopProxyFactory = otherConfiguration.aopProxyFactory;
}
/// <summary>
/// Gets and set the factory to be used to create AOP proxies.
/// </summary>
/// <remarks>
/// <p>
/// This obviously allows one to customise the
/// <see cref="Spring.Aop.Framework.IAopProxyFactory"/> implementation,
/// allowing different strategies to be dropped in without changing the
/// core framework. For example, an
/// <see cref="Spring.Aop.Framework.IAopProxyFactory"/> implementation
/// could return an <see cref="Spring.Aop.Framework.IAopProxy"/>
/// using remoting proxies, <c>Reflection.Emit</c> or a code generation
/// strategy.
/// </p>
/// </remarks>
public virtual IAopProxyFactory AopProxyFactory
{
get { return this.aopProxyFactory; }
set { this.aopProxyFactory = value; }
}
/// <summary>
/// Is this configuration frozen?
/// </summary>
/// <remarks>
/// <p>
/// The default is not frozen.
/// </p>
/// </remarks>
public virtual bool IsFrozen
{
get { return this.frozen; }
set { this.frozen = value; }
}
/// <summary>
/// Copies the configuration from the supplied
/// <paramref name="otherConfiguration"/> into this instance.
/// </summary>
/// <param name="otherConfiguration">
/// The configuration to be copied.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="otherConfiguration"/> is
/// <see langword="null"/>.
/// </exception>
public virtual void CopyFrom(ProxyConfig otherConfiguration)
{
AssertUtils.ArgumentNotNull(otherConfiguration, "otherConfiguration");
this.optimize = otherConfiguration.optimize;
this.proxyTargetType = otherConfiguration.proxyTargetType;
this.proxyTargetAttributes = otherConfiguration.proxyTargetAttributes;
this.exposeProxy = otherConfiguration.exposeProxy;
this.frozen = otherConfiguration.frozen;
this.aopProxyFactory = otherConfiguration.aopProxyFactory;
}
/// <summary>
/// A <see cref="System.String"/> that represents the current
/// <see cref="Spring.Aop.Framework.ProxyConfig"/> configuration.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents the current
/// <see cref="Spring.Aop.Framework.ProxyConfig"/> configuration.
/// </returns>
public override string ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("proxyTargetType=" + ProxyTargetType + "; ");
buffer.Append("proxyTargetAttributes=" + ProxyTargetAttributes + "; ");
buffer.Append("exposeProxy=" + ExposeProxy + "; ");
buffer.Append("isFrozen=" + IsFrozen + "; ");
buffer.Append("optimize=" + Optimize + "; ");
buffer.Append("aopProxyFactory=" + AopProxyFactory.GetType().FullName + "; ");
return buffer.ToString();
}
}
/// <summary>
/// A <see cref="System.String"/> that represents the current
/// <see cref="Spring.Aop.Framework.ProxyConfig"/> configuration.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> that represents the current
/// <see cref="Spring.Aop.Framework.ProxyConfig"/> configuration.
/// </returns>
public override string ToString()
{
StringBuilder buffer = new StringBuilder();
buffer.Append("proxyTargetType=" + ProxyTargetType + "; ");
buffer.Append("proxyTargetAttributes=" + ProxyTargetAttributes + "; ");
buffer.Append("exposeProxy=" + ExposeProxy + "; ");
buffer.Append("isFrozen=" + IsFrozen + "; ");
buffer.Append("optimize=" + Optimize + "; ");
buffer.Append("aopProxyFactory=" + AopProxyFactory.GetType().FullName + "; ");
return buffer.ToString();
}
}

View File

@@ -19,144 +19,141 @@
#endregion
using System.Runtime.Serialization;
using AopAlliance.Intercept;
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Factory for AOP proxies for programmatic use, rather than via a
/// Spring.NET IoC container.
/// </summary>
/// <remarks>
/// <p>
/// This class provides a simple way of obtaining and configuring AOP
/// proxies in code.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class ProxyFactory : AdvisedSupport
{
/// <summary>
/// Factory for AOP proxies for programmatic use, rather than via a
/// Spring.NET IoC container.
/// </summary>
/// <remarks>
/// <p>
/// This class provides a simple way of obtaining and configuring AOP
/// proxies in code.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class ProxyFactory : AdvisedSupport
{
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class.
/// </summary>
public ProxyFactory()
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class.
/// </summary>
public ProxyFactory()
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class that proxys all of the interfaces exposed by the supplied
/// <paramref name="target"/>.
/// </summary>
/// <param name="target">The object to proxy.</param>
/// <exception cref="AopConfigException">
/// If the <paramref name="target"/> is <cref lang="null"/>.
/// </exception>
public ProxyFactory(object target) : base(target)
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class that proxys all of the interfaces exposed by the supplied
/// <paramref name="target"/>.
/// </summary>
/// <param name="target">The object to proxy.</param>
/// <exception cref="AopConfigException">
/// If the <paramref name="target"/> is <cref lang="null"/>.
/// </exception>
public ProxyFactory(object target) : base(target)
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class that has no target object, only interfaces.
/// </summary>
/// <remarks>
/// <p>
/// Interceptors must be added if this factory is to do anything useful.
/// </p>
/// </remarks>
/// <param name="interfaces">The interfaces to implement.</param>
public ProxyFactory(Type[] interfaces) : base(interfaces)
{
}
/// <summary>
/// Creates a new instance of the <see cref="Spring.Aop.Framework.ProxyFactory"/>
/// class that has no target object, only interfaces.
/// </summary>
/// <remarks>
/// <p>
/// Interceptors must be added if this factory is to do anything useful.
/// </p>
/// </remarks>
/// <param name="interfaces">The interfaces to implement.</param>
public ProxyFactory(Type[] interfaces) : base(interfaces)
{
}
/// <summary>
/// Creates a new instance of the <see cref="ProxyFactory"/> class for the
/// given interface and interceptor.
/// </summary>
/// <remarks>Convenience method for creating a proxy for a single interceptor
/// , assuming that the interceptor handles all calls itself rather than delegating
/// to a target, like in the case of remoting proxies.</remarks>
/// <param name="proxyInterface">The interface that the proxy should implement.</param>
/// <param name="interceptor">The interceptor that the proxy should invoke.</param>
public ProxyFactory(Type proxyInterface, IInterceptor interceptor)
{
AddInterface(proxyInterface);
AddAdvice(interceptor);
}
/// <summary>
/// Creates a new instance of the <see cref="ProxyFactory"/> class for the
/// given interface and interceptor.
/// </summary>
/// <remarks>Convenience method for creating a proxy for a single interceptor
/// , assuming that the interceptor handles all calls itself rather than delegating
/// to a target, like in the case of remoting proxies.</remarks>
/// <param name="proxyInterface">The interface that the proxy should implement.</param>
/// <param name="interceptor">The interceptor that the proxy should invoke.</param>
public ProxyFactory(Type proxyInterface, IInterceptor interceptor)
{
AddInterface(proxyInterface);
AddAdvice(interceptor);
}
/// <summary>
/// Create a new instance of the <see cref="ProxyFactory"/> class for the specified
/// <see cref="ITargetSource"/> making the proxy implement the specified interface.
/// </summary>
/// <remarks></remarks>
/// <param name="proxyInterface">The interface that the proxy should implement.</param>
/// <param name="targetSource">The target source that the proxy should invoek.</param>
public ProxyFactory(Type proxyInterface, ITargetSource targetSource)
{
AddInterface(proxyInterface);
TargetSource = targetSource;
}
/// <summary>
/// Create a new instance of the <see cref="ProxyFactory"/> class for the specified
/// <see cref="ITargetSource"/> making the proxy implement the specified interface.
/// </summary>
/// <remarks></remarks>
/// <param name="proxyInterface">The interface that the proxy should implement.</param>
/// <param name="targetSource">The target source that the proxy should invoek.</param>
public ProxyFactory(Type proxyInterface, ITargetSource targetSource)
{
AddInterface(proxyInterface);
TargetSource = targetSource;
}
/// <inheritdoc />
protected ProxyFactory(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <inheritdoc />
protected ProxyFactory(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
/// <inheritdoc />
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
/// <inheritdoc />
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
}
/// <summary>
/// Creates a new proxy according to the settings in this factory.
/// </summary>
/// <remarks>
/// <p>
/// Can be called repeatedly; the effect of repeated invocations will
/// (of course) vary if interfaces have been added or removed.
/// </p>
/// </remarks>
/// <returns>An AOP proxy for target object.</returns>
public virtual object GetProxy()
{
IAopProxy proxy = CreateAopProxy();
return proxy.GetProxy();
}
/// <summary>
/// Creates a new proxy according to the settings in this factory.
/// </summary>
/// <remarks>
/// <p>
/// Can be called repeatedly; the effect of repeated invocations will
/// (of course) vary if interfaces have been added or removed.
/// </p>
/// </remarks>
/// <returns>An AOP proxy for target object.</returns>
public virtual object GetProxy()
{
IAopProxy proxy = CreateAopProxy();
return proxy.GetProxy();
}
/// <summary>
/// Creates a new proxy for the supplied <paramref name="proxyInterface"/>
/// and <paramref name="interceptor"/>.
/// </summary>
/// <remarks>
/// <p>
/// This is a convenience method for creating a proxy for a single
/// interceptor.
/// </p>
/// </remarks>
/// <param name="proxyInterface">
/// The interface that the proxy must implement.
/// </param>
/// <param name="interceptor">
/// The interceptor that the proxy must invoke.
/// </param>
/// <returns>
/// A new AOP proxy for the supplied <paramref name="proxyInterface"/>
/// and <paramref name="interceptor"/>.
/// </returns>
public static object GetProxy(Type proxyInterface, IInterceptor interceptor)
{
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.AddInterface(proxyInterface);
proxyFactory.AddAdvice(interceptor);
return proxyFactory.GetProxy();
}
}
/// <summary>
/// Creates a new proxy for the supplied <paramref name="proxyInterface"/>
/// and <paramref name="interceptor"/>.
/// </summary>
/// <remarks>
/// <p>
/// This is a convenience method for creating a proxy for a single
/// interceptor.
/// </p>
/// </remarks>
/// <param name="proxyInterface">
/// The interface that the proxy must implement.
/// </param>
/// <param name="interceptor">
/// The interceptor that the proxy must invoke.
/// </param>
/// <returns>
/// A new AOP proxy for the supplied <paramref name="proxyInterface"/>
/// and <paramref name="interceptor"/>.
/// </returns>
public static object GetProxy(Type proxyInterface, IInterceptor interceptor)
{
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.AddInterface(proxyInterface);
proxyFactory.AddAdvice(interceptor);
return proxyFactory.GetProxy();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,112 +22,110 @@
using System.Collections;
using System.Reflection;
using Spring.Util;
using AopAlliance.Intercept;
#endregion
namespace Spring.Aop.Framework
namespace Spring.Aop.Framework;
/// <summary>
/// Invokes a target method using standard reflection.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Rick Evans (.NET)</author>
/// <author>Bruno Baia (.NET)</author>
[Serializable]
public class ReflectiveMethodInvocation : AbstractMethodInvocation
{
/// <summary>
/// Invokes a target method using standard reflection.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <author>Rick Evans (.NET)</author>
/// <author>Bruno Baia (.NET)</author>
[Serializable]
public class ReflectiveMethodInvocation : AbstractMethodInvocation
{
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
private MethodInfo proxyMethod;
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
private MethodInfo proxyMethod;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation"/> class.
/// </summary>
/// <param name="proxy">The AOP proxy.</param>
/// <param name="target">The target object.</param>
/// <param name="method">The target method proxied.</param>
/// <param name="proxyMethod">The method to invoke on proxy.</param>
/// <param name="arguments">The target method's arguments.</param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.</param>
/// <param name="interceptors">
/// The list of interceptors that are to be applied. May be
/// <cref lang="null"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If any of the <paramref name="target"/> or <paramref name="method"/>
/// parameters is <see langword="null"/>.
/// </exception>
public ReflectiveMethodInvocation(
object proxy, object target, MethodInfo method, MethodInfo proxyMethod,
object[] arguments, Type targetType, IList interceptors)
: base(proxy, target, method, arguments, targetType, interceptors)
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation"/> class.
/// </summary>
/// <param name="proxy">The AOP proxy.</param>
/// <param name="target">The target object.</param>
/// <param name="method">The target method proxied.</param>
/// <param name="proxyMethod">The method to invoke on proxy.</param>
/// <param name="arguments">The target method's arguments.</param>
/// <param name="targetType">
/// The <see cref="System.Type"/> of the target object.</param>
/// <param name="interceptors">
/// The list of interceptors that are to be applied. May be
/// <cref lang="null"/>.
/// </param>
/// <exception cref="System.ArgumentNullException">
/// If any of the <paramref name="target"/> or <paramref name="method"/>
/// parameters is <see langword="null"/>.
/// </exception>
public ReflectiveMethodInvocation(
object proxy, object target, MethodInfo method, MethodInfo proxyMethod,
object[] arguments, Type targetType, IList interceptors)
: base(proxy, target, method, arguments, targetType, interceptors)
{
this.proxyMethod = proxyMethod;
}
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
protected MethodInfo ProxyMethod
{
get { return proxyMethod; }
set { proxyMethod = value; }
}
/// <summary>
/// Invokes the joinpoint using standard reflection.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override this to use custom invocation.
/// </p>
/// </remarks>
/// <returns>
/// The return value of the invocation of the joinpoint.
/// </returns>
/// <exception cref="System.Exception">
/// If invoking the joinpoint resulted in an exception.
/// </exception>
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint"/>
protected override object InvokeJoinpoint()
{
try
{
this.proxyMethod = proxyMethod;
MethodInfo targetMethodInfo = ProxyMethod ?? Method;
AssertUtils.Understands(Target, "target", targetMethodInfo);
return targetMethodInfo.Invoke(Target, Arguments);
}
/// <summary>
/// The method invocation that is to be invoked on the proxy.
/// </summary>
protected MethodInfo ProxyMethod
{
get { return proxyMethod; }
set { proxyMethod = value; }
}
/// <summary>
/// Invokes the joinpoint using standard reflection.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses can override this to use custom invocation.
/// </p>
/// </remarks>
/// <returns>
/// The return value of the invocation of the joinpoint.
/// </returns>
/// <exception cref="System.Exception">
/// If invoking the joinpoint resulted in an exception.
/// </exception>
/// <see cref="Spring.Aop.Framework.AbstractMethodInvocation.InvokeJoinpoint"/>
protected override object InvokeJoinpoint()
catch (TargetInvocationException ex)
{
try
{
MethodInfo targetMethodInfo = ProxyMethod ?? Method;
AssertUtils.Understands(Target, "target", targetMethodInfo);
return targetMethodInfo.Invoke(Target, Arguments);
}
catch (TargetInvocationException ex)
{
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
}
throw ReflectionUtils.UnwrapTargetInvocationException(ex);
}
}
/// <summary>
/// Creates a new <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation"/> instance
/// from the specified <see cref="AopAlliance.Intercept.IMethodInvocation"/> and
/// increments the interceptor index.
/// </summary>
/// <param name="invocation">
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
/// </param>
/// <returns>
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
/// </returns>
protected override IMethodInvocation PrepareMethodInvocationForProceed(IMethodInvocation invocation)
{
var rmi = new ReflectiveMethodInvocation(Proxy, Target, Method, ProxyMethod, Arguments, TargetType, Interceptors);
rmi.CurrentInterceptorIndex = CurrentInterceptorIndex + 1;
/// <summary>
/// Creates a new <see cref="Spring.Aop.Framework.ReflectiveMethodInvocation"/> instance
/// from the specified <see cref="AopAlliance.Intercept.IMethodInvocation"/> and
/// increments the interceptor index.
/// </summary>
/// <param name="invocation">
/// The current <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance.
/// </param>
/// <returns>
/// The new <see cref="AopAlliance.Intercept.IMethodInvocation"/> instance to use.
/// </returns>
protected override IMethodInvocation PrepareMethodInvocationForProceed(IMethodInvocation invocation)
{
var rmi = new ReflectiveMethodInvocation(Proxy, Target, Method, ProxyMethod, Arguments, TargetType, Interceptors);
rmi.CurrentInterceptorIndex = CurrentInterceptorIndex + 1;
return rmi;
}
}
return rmi;
}
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -24,71 +24,70 @@ using AopAlliance.Aop;
#endregion
namespace Spring.Aop
{
/// <summary>
/// Base interface holding AOP advice and a filter determining the
/// applicability of the advice (such as a pointcut).
/// </summary>
/// <remarks>
/// <note>
/// This interface is not for use by Spring.NET users, but exists rather to
/// allow for commonality in the support for different types of advice
/// within the framework.
/// </note>
/// <p>
/// Spring.NET AOP is centered on <b>around advice</b> delivered via method
/// <b>interception</b>, compliant with the AOP Alliance interception API.
/// The <see cref="Spring.Aop.IAdvisor"/> interface allows support for
/// different types of advice, such as <b>before</b> and <b>after</b>
/// advice, which need not be implemented using interception.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IAdvisor
{
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// An advisor that was creating a mixin would be a per instance
/// operation and would thus return <see langword="true"/>. If the
/// advisor is not per instance, it is shared with all instances of the
/// advised class obtained from the same Spring.NET IoC container.
/// </p>
/// <p>
/// Use <c>singleton</c> and <c>prototype</c> object definitions or
/// appropriate programmatic proxy creation to ensure that
/// <see cref="Spring.Aop.IAdvisor"/>s have the correct lifecycle model.
/// </p>
/// <note>
/// This method is not currently used by the framework.
/// </note>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
bool IsPerInstance { get; }
namespace Spring.Aop;
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <remarks>
/// <p>
/// An advice may be an interceptor, a throws advice, before advice,
/// introduction etc.
/// </p>
/// </remarks>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
IAdvice Advice { get; }
}
}
/// <summary>
/// Base interface holding AOP advice and a filter determining the
/// applicability of the advice (such as a pointcut).
/// </summary>
/// <remarks>
/// <note>
/// This interface is not for use by Spring.NET users, but exists rather to
/// allow for commonality in the support for different types of advice
/// within the framework.
/// </note>
/// <p>
/// Spring.NET AOP is centered on <b>around advice</b> delivered via method
/// <b>interception</b>, compliant with the AOP Alliance interception API.
/// The <see cref="Spring.Aop.IAdvisor"/> interface allows support for
/// different types of advice, such as <b>before</b> and <b>after</b>
/// advice, which need not be implemented using interception.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IAdvisor
{
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// An advisor that was creating a mixin would be a per instance
/// operation and would thus return <see langword="true"/>. If the
/// advisor is not per instance, it is shared with all instances of the
/// advised class obtained from the same Spring.NET IoC container.
/// </p>
/// <p>
/// Use <c>singleton</c> and <c>prototype</c> object definitions or
/// appropriate programmatic proxy creation to ensure that
/// <see cref="Spring.Aop.IAdvisor"/>s have the correct lifecycle model.
/// </p>
/// <note>
/// This method is not currently used by the framework.
/// </note>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
bool IsPerInstance { get; }
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <remarks>
/// <p>
/// An advice may be an interceptor, a throws advice, before advice,
/// introduction etc.
/// </p>
/// </remarks>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
IAdvice Advice { get; }
}

View File

@@ -22,21 +22,20 @@
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// AOP Aspect abstraction, holding a list of <see cref="Spring.Aop.IAdvisor"/>s
/// </summary>
/// <seealso cref="IAdvisor"/>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisors
{
/// <summary>
/// AOP Aspect abstraction, holding a list of <see cref="Spring.Aop.IAdvisor"/>s
/// </summary>
/// <seealso cref="IAdvisor"/>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IAdvisors
{
/// <summary>
/// Gets or sets a list of advisors.
/// </summary>
/// <value>
/// A list of advisors.
/// </value>
IList<IAdvisor> Advisors { get; set; }
}
/// <summary>
/// Gets or sets a list of advisors.
/// </summary>
/// <value>
/// A list of advisors.
/// </value>
IList<IAdvisor> Advisors { get; set; }
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -21,57 +21,55 @@
#region Imports
using System.Reflection;
using AopAlliance.Aop;
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Advice that executes after a method returns <b>successfully</b>.
/// </summary>
/// <remarks>
/// <p>
/// <i>After</i> returning advice is invoked only on a normal method
/// return, but <b>not</b> if an exception is thrown. Such advice can see
/// the return value of the advised method invocation, but cannot change it.
/// </p>
/// <p>
/// Possible uses for this type of advice would include performing access
/// control checks on the return value of an advised method invocation, the
/// ubiquitous logging of method invocation return values (useful during
/// development), etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IAfterReturningAdvice : IAdvice
{
/// <summary>
/// Advice that executes after a method returns <b>successfully</b>.
/// </summary>
/// <remarks>
/// <p>
/// <i>After</i> returning advice is invoked only on a normal method
/// return, but <b>not</b> if an exception is thrown. Such advice can see
/// the return value of the advised method invocation, but cannot change it.
/// </p>
/// <p>
/// Possible uses for this type of advice would include performing access
/// control checks on the return value of an advised method invocation, the
/// ubiquitous logging of method invocation return values (useful during
/// development), etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IAfterReturningAdvice : IAdvice
{
/// <summary>
/// Executes after <paramref name="target"/> <paramref name="method"/>
/// returns <b>successfully</b>.
/// </summary>
/// <remarks>
/// <p>
/// Note that the supplied <paramref name="returnValue"/> <b>cannot</b>
/// be changed by this type of advice... use the around advice type
/// (<see cref="AopAlliance.Intercept.IMethodInterceptor"/>) if you
/// need to change the return value of an advised method invocation.
/// The data encapsulated by the supplied <paramref name="returnValue"/>
/// can of course be modified though.
/// </p>
/// </remarks>
/// <param name="returnValue">
/// The value returned by the <paramref name="target"/>.
/// </param>
/// <param name="method">The intecepted method.</param>
/// <param name="args">The intercepted method's arguments.</param>
/// <param name="target">The target object.</param>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor.Invoke"/>
void AfterReturning(object returnValue, MethodInfo method, object[] args, object target);
}
}
/// <summary>
/// Executes after <paramref name="target"/> <paramref name="method"/>
/// returns <b>successfully</b>.
/// </summary>
/// <remarks>
/// <p>
/// Note that the supplied <paramref name="returnValue"/> <b>cannot</b>
/// be changed by this type of advice... use the around advice type
/// (<see cref="AopAlliance.Intercept.IMethodInterceptor"/>) if you
/// need to change the return value of an advised method invocation.
/// The data encapsulated by the supplied <paramref name="returnValue"/>
/// can of course be modified though.
/// </p>
/// </remarks>
/// <param name="returnValue">
/// The value returned by the <paramref name="target"/>.
/// </param>
/// <param name="method">The intecepted method.</param>
/// <param name="args">The intercepted method's arguments.</param>
/// <param name="target">The target object.</param>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor.Invoke"/>
void AfterReturning(object returnValue, MethodInfo method, object[] args, object target);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -24,30 +24,29 @@ using AopAlliance.Aop;
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Superinterface for all before advice.
/// </summary>
/// <remarks>
/// <p>
/// <i>Before</i> advice is advice that executes before a joinpoint, but
/// which does not have the ability to prevent execution flow proceeding to
/// the joinpoint (unless it throws an <see cref="System.Exception"/>).
/// </p>
/// <p>
/// Spring.NET only supports <i>method</i> before advice. Although this
/// is unlikely to change, this API is designed to allow <i>field</i>
/// before advice in future if desired.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IBeforeAdvice : IAdvice
{
/// <summary>
/// Superinterface for all before advice.
/// </summary>
/// <remarks>
/// <p>
/// <i>Before</i> advice is advice that executes before a joinpoint, but
/// which does not have the ability to prevent execution flow proceeding to
/// the joinpoint (unless it throws an <see cref="System.Exception"/>).
/// </p>
/// <p>
/// Spring.NET only supports <i>method</i> before advice. Although this
/// is unlikely to change, this API is designed to allow <i>field</i>
/// before advice in future if desired.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IBeforeAdvice : IAdvice
{
}
}
}

View File

@@ -22,69 +22,68 @@
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Superinterface for advisors that perform one or more AOP
/// <b>introductions</b>.
/// </summary>
/// <remarks>
/// <p>
/// This interface cannot be implemented directly; subinterfaces must
/// provide the advice type implementing the introduction.
/// </p>
/// <p>
/// Introduction is the implementation of additional interfaces (not
/// implemented by a target) via AOP advice.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Aop.IIntroductionInterceptor"/>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IIntroductionAdvisor : IAdvisor
{
/// <summary>
/// Superinterface for advisors that perform one or more AOP
/// <b>introductions</b>.
/// </summary>
/// <remarks>
/// <p>
/// This interface cannot be implemented directly; subinterfaces must
/// provide the advice type implementing the introduction.
/// </p>
/// <p>
/// Introduction is the implementation of additional interfaces (not
/// implemented by a target) via AOP advice.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Aop.IIntroductionInterceptor"/>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IIntroductionAdvisor : IAdvisor
{
/// <summary>
/// Returns the filter determining which target classes this
/// introduction should apply to.
/// </summary>
/// <remarks>
/// <p>
/// This is the <see cref="System.Type"/> part of a pointcut.
/// Be advised that method matching doesn't make sense in the context
/// of introductions.
/// </p>
/// </remarks>
/// <value>
/// The filter determining which target classes this introduction
/// should apply to.
/// </value>
ITypeFilter TypeFilter { get; }
/// <summary>
/// Returns the filter determining which target classes this
/// introduction should apply to.
/// </summary>
/// <remarks>
/// <p>
/// This is the <see cref="System.Type"/> part of a pointcut.
/// Be advised that method matching doesn't make sense in the context
/// of introductions.
/// </p>
/// </remarks>
/// <value>
/// The filter determining which target classes this introduction
/// should apply to.
/// </value>
ITypeFilter TypeFilter { get; }
/// <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>
Type[] Interfaces { get; }
/// <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>
Type[] Interfaces { get; }
/// <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"/>
void ValidateInterfaces();
}
/// <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"/>
void ValidateInterfaces();
}

View File

@@ -24,37 +24,36 @@ using AopAlliance.Intercept;
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Subinterface of the AOP Alliance
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> interface that
/// allows additional interfaces to be implemented by the interceptor, and
/// available via a proxy using that interceptor.
/// </summary>
/// <remarks>
/// <p>
/// This is a fundamental AOP concept called <b>introduction</b>.
/// </p>
/// <p>
/// Introductions are often <b>mixins</b>, enabling the building of composite
/// objects that can achieve many of the goals of multiple inheritance.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IIntroductionInterceptor : IMethodInterceptor
{
/// <summary>
/// Subinterface of the AOP Alliance
/// <see cref="AopAlliance.Intercept.IMethodInterceptor"/> interface that
/// allows additional interfaces to be implemented by the interceptor, and
/// available via a proxy using that interceptor.
/// </summary>
/// <remarks>
/// <p>
/// This is a fundamental AOP concept called <b>introduction</b>.
/// </p>
/// <p>
/// Introductions are often <b>mixins</b>, enabling the building of composite
/// objects that can achieve many of the goals of multiple inheritance.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IIntroductionInterceptor : IMethodInterceptor
{
/// <summary>
/// Does this <see cref="Spring.Aop.IIntroductionInterceptor"/>
/// implement the given interface?
/// </summary>
/// <param name="intf">The interface to check.</param>
/// <returns>
/// <see langword="true"/> if this
/// <see cref="Spring.Aop.IIntroductionInterceptor"/>
/// implements the given interface.
/// </returns>
bool ImplementsInterface(Type intf);
}
/// <summary>
/// Does this <see cref="Spring.Aop.IIntroductionInterceptor"/>
/// implement the given interface?
/// </summary>
/// <param name="intf">The interface to check.</param>
/// <returns>
/// <see langword="true"/> if this
/// <see cref="Spring.Aop.IIntroductionInterceptor"/>
/// implements the given interface.
/// </returns>
bool ImplementsInterface(Type intf);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -24,48 +24,47 @@ using System.Reflection;
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Advice executed before a method is invoked.
/// </summary>
/// <remarks>
/// <p>
/// Such advice cannot prevent the method call proceeding, short of
/// throwing an <see cref="System.Exception"/>.
/// </p>
/// <p>
/// The main advantage of <c>before</c> advice is that there is no
/// possibility of inadvertently failing to proceed down the interceptor
/// chain, since there is no need (and indeed means) to invoke the next
/// interceptor in the call chain.
/// </p>
/// <p>
/// Possible uses for this type of advice would include performing class
/// invariant checks prior to the actual method invocation, the ubiquitous
/// logging of method invocations (useful during development), etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IMethodBeforeAdvice : IBeforeAdvice
{
/// <summary>
/// Advice executed before a method is invoked.
/// </summary>
/// <remarks>
/// <p>
/// Such advice cannot prevent the method call proceeding, short of
/// throwing an <see cref="System.Exception"/>.
/// </p>
/// <p>
/// The main advantage of <c>before</c> advice is that there is no
/// possibility of inadvertently failing to proceed down the interceptor
/// chain, since there is no need (and indeed means) to invoke the next
/// interceptor in the call chain.
/// </p>
/// <p>
/// Possible uses for this type of advice would include performing class
/// invariant checks prior to the actual method invocation, the ubiquitous
/// logging of method invocations (useful during development), etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="Spring.Aop.IThrowsAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IMethodBeforeAdvice : IBeforeAdvice
{
/// <summary>
/// The callback before a given method is invoked.
/// </summary>
/// <param name="method">The method being invoked.</param>
/// <param name="args">The arguments to the method.</param>
/// <param name="target">
/// The target of the method invocation. May be <see langword="null"/>.
/// </param>
/// <exception cref="System.Exception">
/// Thrown when and if this object wishes to abort the call. Any
/// exception so thrown will be propagated to the caller.
/// </exception>
void Before(MethodInfo method, object[] args, object target);
}
}
/// <summary>
/// The callback before a given method is invoked.
/// </summary>
/// <param name="method">The method being invoked.</param>
/// <param name="args">The arguments to the method.</param>
/// <param name="target">
/// The target of the method invocation. May be <see langword="null"/>.
/// </param>
/// <exception cref="System.Exception">
/// Thrown when and if this object wishes to abort the call. Any
/// exception so thrown will be propagated to the caller.
/// </exception>
void Before(MethodInfo method, object[] args, object target);
}

View File

@@ -24,126 +24,125 @@ using System.Reflection;
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// That part of an <see cref="Spring.Aop.IPointcut"/> that checks whether a
/// target method is eligible for advice.
/// </summary>
/// <remarks>
/// <p>
/// An <see cref="Spring.Aop.IMethodMatcher"/> may be evaluated
/// <b>statically</b> or at runtime (<b>dynamically</b>). Static
/// matching involves only the method signature and (possibly) any
/// <see cref="System.Attribute"/>s that have been applied to a method.
/// Dynamic matching additionally takes into account the actual argument
/// values passed to a method invocation.
/// </p>
/// <p>
/// If the value of the <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/>
/// property of an implementation instance returns <see langword="false"/>,
/// evaluation can be performed statically, and the result will be the same
/// for all invocations of this method, whatever their arguments. This
/// means that if the value of the
/// <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> is
/// <see langword="false"/>, the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will never be invoked for the lifetime of the
/// <see cref="Spring.Aop.IMethodMatcher"/>.
/// </p>
/// <p>
/// If an implementation returns <see langword="true"/> in its two argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
/// method, and the value of it's
/// <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> property is
/// <see langword="true"/>, the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will be invoked <i>immediately before each and every potential
/// execution of the related advice</i>, to decide whether the advice
/// should run. All previous advice, such as earlier interceptors in an
/// interceptor chain, will have run, so any state changes they have
/// produced in parameters or thread local storage, will be available at
/// the time of evaluation.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="TrueMethodMatcher"/>
public interface IMethodMatcher
{
/// <summary>
/// That part of an <see cref="Spring.Aop.IPointcut"/> that checks whether a
/// target method is eligible for advice.
/// </summary>
/// <remarks>
/// <p>
/// An <see cref="Spring.Aop.IMethodMatcher"/> may be evaluated
/// <b>statically</b> or at runtime (<b>dynamically</b>). Static
/// matching involves only the method signature and (possibly) any
/// <see cref="System.Attribute"/>s that have been applied to a method.
/// Dynamic matching additionally takes into account the actual argument
/// values passed to a method invocation.
/// </p>
/// <p>
/// If the value of the <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/>
/// property of an implementation instance returns <see langword="false"/>,
/// evaluation can be performed statically, and the result will be the same
/// for all invocations of this method, whatever their arguments. This
/// means that if the value of the
/// <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> is
/// <see langword="false"/>, the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will never be invoked for the lifetime of the
/// <see cref="Spring.Aop.IMethodMatcher"/>.
/// </p>
/// <p>
/// If an implementation returns <see langword="true"/> in its two argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
/// method, and the value of it's
/// <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> property is
/// <see langword="true"/>, the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will be invoked <i>immediately before each and every potential
/// execution of the related advice</i>, to decide whether the advice
/// should run. All previous advice, such as earlier interceptors in an
/// interceptor chain, will have run, so any state changes they have
/// produced in parameters or thread local storage, will be available at
/// the time of evaluation.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="TrueMethodMatcher"/>
public interface IMethodMatcher
{
/// <summary>
/// Is this <see cref="Spring.Aop.IMethodMatcher"/> dynamic?
/// </summary>
/// <remarks>
/// <p>
/// If <see langword="true"/>, the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will be invoked if the two argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
/// method returns <see langword="true"/>.
/// </p>
/// <p>
/// Note that this property can be checked when an AOP proxy is created,
/// and implementations need not check the value of this property again
/// before each method invocation.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this
/// <see cref="Spring.Aop.IMethodMatcher"/> is dynamic.
/// </value>
bool IsRuntime { get; }
/// <summary>
/// Is this <see cref="Spring.Aop.IMethodMatcher"/> dynamic?
/// </summary>
/// <remarks>
/// <p>
/// If <see langword="true"/>, the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will be invoked if the two argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
/// method returns <see langword="true"/>.
/// </p>
/// <p>
/// Note that this property can be checked when an AOP proxy is created,
/// and implementations need not check the value of this property again
/// before each method invocation.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this
/// <see cref="Spring.Aop.IMethodMatcher"/> is dynamic.
/// </value>
bool IsRuntime { get; }
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <remarks>
/// <p>
/// This is a static check. If this method invocation returns
/// <see langword="false"/>,or if the
/// <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> property is
/// <see langword="false"/>, then no runtime check will be made.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
bool Matches(MethodInfo method, Type targetType);
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <remarks>
/// <p>
/// This is a static check. If this method invocation returns
/// <see langword="false"/>,or if the
/// <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> property is
/// <see langword="false"/>, then no runtime check will be made.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
bool Matches(MethodInfo method, Type targetType);
/// <summary>
/// Is there a runtime (dynamic) match for the supplied
/// <paramref name="method"/>?
/// </summary>
/// <remarks>
/// <p>
/// In order for this method to have even been invoked, the supplied
/// <paramref name="method"/> must have matched
/// statically. This method is invoked only if the two argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
/// method returns <see langword="true"/> for the supplied
/// <paramref name="method"/> and <paramref name="targetType"/>, and
/// if the <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> property
/// is <see langword="true"/>.
/// </p>
/// <p>
/// Invoked immediately <b>before</b> any potential running of the
/// advice, and <b>after</b> any advice earlier in the advice chain has
/// run.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/>.
/// </param>
/// <param name="args">The arguments to the method</param>
/// <returns>
/// <see langword="true"/> if there is a runtime match.</returns>
bool Matches(MethodInfo method, Type targetType, object[] args);
}
/// <summary>
/// Is there a runtime (dynamic) match for the supplied
/// <paramref name="method"/>?
/// </summary>
/// <remarks>
/// <p>
/// In order for this method to have even been invoked, the supplied
/// <paramref name="method"/> must have matched
/// statically. This method is invoked only if the two argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
/// method returns <see langword="true"/> for the supplied
/// <paramref name="method"/> and <paramref name="targetType"/>, and
/// if the <see cref="Spring.Aop.IMethodMatcher.IsRuntime"/> property
/// is <see langword="true"/>.
/// </p>
/// <p>
/// Invoked immediately <b>before</b> any potential running of the
/// advice, and <b>after</b> any advice earlier in the advice chain has
/// run.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/>.
/// </param>
/// <param name="args">The arguments to the method</param>
/// <returns>
/// <see langword="true"/> if there is a runtime match.</returns>
bool Matches(MethodInfo method, Type targetType, object[] args);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -18,37 +18,36 @@
#endregion
namespace Spring.Aop
{
/// <summary>
/// Spring.NET's core pointcut abstraction.
/// </summary>
/// <remarks>
/// <p>
/// A pointcut is composed of <see cref="Spring.Aop.ITypeFilter"/>s and
/// <see cref="Spring.Aop.IMethodMatcher"/>s. Both these basic terms and an
/// <see cref="Spring.Aop.IPointcut"/> itself can be combined to build up
/// sophisticated combinations.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IPointcut
{
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
ITypeFilter TypeFilter { get; }
namespace Spring.Aop;
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
IMethodMatcher MethodMatcher { get; }
}
}
/// <summary>
/// Spring.NET's core pointcut abstraction.
/// </summary>
/// <remarks>
/// <p>
/// A pointcut is composed of <see cref="Spring.Aop.ITypeFilter"/>s and
/// <see cref="Spring.Aop.IMethodMatcher"/>s. Both these basic terms and an
/// <see cref="Spring.Aop.IPointcut"/> itself can be combined to build up
/// sophisticated combinations.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface IPointcut
{
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
ITypeFilter TypeFilter { get; }
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
IMethodMatcher MethodMatcher { get; }
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -18,26 +18,25 @@
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Superinterface for all <see cref="Spring.Aop.IAdvisor"/>s that are
/// driven by a pointcut.
/// </summary>
/// <remarks>
/// <p>
/// This covers nearly all advisors except introduction advisors, for which
/// method-level matching does not apply.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IIntroductionAdvisor"/>
public interface IPointcutAdvisor : IAdvisor
{
/// <summary>
/// Superinterface for all <see cref="Spring.Aop.IAdvisor"/>s that are
/// driven by a pointcut.
/// </summary>
/// <remarks>
/// <p>
/// This covers nearly all advisors except introduction advisors, for which
/// method-level matching does not apply.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IIntroductionAdvisor"/>
public interface IPointcutAdvisor : IAdvisor
{
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
IPointcut Pointcut { get; }
}
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
IPointcut Pointcut { get; }
}

View File

@@ -22,56 +22,55 @@
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Used to obtain the current "target" of an AOP invocation
/// </summary>
/// <remarks>
/// <p>
/// This target will be invoked via reflection if no around advice chooses
/// to end the interceptor chain itself.
/// </p>
/// <p>
/// If an <see cref="Spring.Aop.ITargetSource"/> is <c>"static"</c>, it
/// will always return the same target, allowing optimizations in the AOP
/// framework. Dynamic target sources can support pooling, hot swapping etc.
/// </p>
/// <p>
/// Application developers don't usually need to work with target sources
/// directly: this is an AOP framework interface.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface ITargetSource
{
/// <summary>
/// Used to obtain the current "target" of an AOP invocation
/// </summary>
/// <remarks>
/// <p>
/// This target will be invoked via reflection if no around advice chooses
/// to end the interceptor chain itself.
/// </p>
/// <p>
/// If an <see cref="Spring.Aop.ITargetSource"/> is <c>"static"</c>, it
/// will always return the same target, allowing optimizations in the AOP
/// framework. Dynamic target sources can support pooling, hot swapping etc.
/// </p>
/// <p>
/// Application developers don't usually need to work with target sources
/// directly: this is an AOP framework interface.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
public interface ITargetSource
{
/// <summary>
/// The <see cref="System.Type"/> of the target object.
/// </summary>
Type TargetType { get; }
/// <summary>
/// The <see cref="System.Type"/> of the target object.
/// </summary>
Type TargetType { get; }
/// <summary>
/// Is the target source static?
/// </summary>
/// <value>
/// <see langword="true"/> if the target source is static.
/// </value>
bool IsStatic { get; }
/// <summary>
/// Is the target source static?
/// </summary>
/// <value>
/// <see langword="true"/> if the target source is static.
/// </value>
bool IsStatic { get; }
/// <summary>
/// Returns the target object.
/// </summary>
/// <returns>The target object.</returns>
/// <exception cref="System.Exception">
/// If unable to obtain the target object.
/// </exception>
object GetTarget();
/// <summary>
/// Returns the target object.
/// </summary>
/// <returns>The target object.</returns>
/// <exception cref="System.Exception">
/// If unable to obtain the target object.
/// </exception>
object GetTarget();
/// <summary>
/// Releases the target object.
/// </summary>
/// <param name="target">The target object to release.</param>
void ReleaseTarget(object target);
}
/// <summary>
/// Releases the target object.
/// </summary>
/// <param name="target">The target object to release.</param>
void ReleaseTarget(object target);
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright © 2002-2011 the original author or authors.
* Copyright <EFBFBD> 2002-2011 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.
@@ -24,36 +24,35 @@ using AopAlliance.Aop;
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// Simple marker interface for throws advice.
/// </summary>
/// <remarks>
/// <p>
/// There are no methods on this interface, as methods are discovered and
/// invoked via reflection. Please do see read the API documentation for the
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/> class;
/// said documention describes in detail the signature of the methods that
/// implementations of the <see cref="Spring.Aop.IThrowsAdvice"/> interface
/// must adhere to in the specific case of Spring.NET's implementation of
/// throws advice.
/// </p>
/// <p>
/// There are any number of possible uses for this type of advice. Some
/// examples would include the ubiquitous logging of any such exceptions,
/// monitoring the number and type of exceptions and sending emails to
/// a support desk once certain criteria have been met, wrapping generic
/// exceptions such as System.Data.SqlClient.SqlException in
/// exceptions that are more meaningful to your business logic, etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IThrowsAdvice : IAdvice
{
/// <summary>
/// Simple marker interface for throws advice.
/// </summary>
/// <remarks>
/// <p>
/// There are no methods on this interface, as methods are discovered and
/// invoked via reflection. Please do see read the API documentation for the
/// <see cref="Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor"/> class;
/// said documention describes in detail the signature of the methods that
/// implementations of the <see cref="Spring.Aop.IThrowsAdvice"/> interface
/// must adhere to in the specific case of Spring.NET's implementation of
/// throws advice.
/// </p>
/// <p>
/// There are any number of possible uses for this type of advice. Some
/// examples would include the ubiquitous logging of any such exceptions,
/// monitoring the number and type of exceptions and sending emails to
/// a support desk once certain criteria have been met, wrapping generic
/// exceptions such as System.Data.SqlClient.SqlException in
/// exceptions that are more meaningful to your business logic, etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IMethodBeforeAdvice"/>
/// <seealso cref="Spring.Aop.IAfterReturningAdvice"/>
/// <seealso cref="AopAlliance.Intercept.IMethodInterceptor"/>
public interface IThrowsAdvice : IAdvice
{
}
}
}

View File

@@ -22,35 +22,34 @@
#endregion
namespace Spring.Aop
namespace Spring.Aop;
/// <summary>
/// A filter that restricts the matching of a pointcut or introduction to
/// a given set of target types.
/// </summary>
/// <remarks>
/// <p>
/// Can be used as part of a pointcut, or for the entire targeting of an
/// introduction.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IPointcut"/>
/// <seealso cref="TrueTypeFilter.True"/>
public interface ITypeFilter
{
/// <summary>
/// A filter that restricts the matching of a pointcut or introduction to
/// a given set of target types.
/// </summary>
/// <remarks>
/// <p>
/// Can be used as part of a pointcut, or for the entire targeting of an
/// introduction.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
/// <seealso cref="Spring.Aop.IPointcut"/>
/// <seealso cref="TrueTypeFilter.True"/>
public interface ITypeFilter
{
/// <summary>
/// Should the pointcut apply to the supplied
/// <see cref="System.Type"/>?
/// </summary>
/// <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>
bool Matches(Type type);
}
}
/// <summary>
/// Should the pointcut apply to the supplied
/// <see cref="System.Type"/>?
/// </summary>
/// <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>
bool Matches(Type type);
}

View File

@@ -20,59 +20,58 @@
using AopAlliance.Aop;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Abstract PointcutAdvisor that allows for any Advice to be configured.
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public abstract class AbstractGenericPointcutAdvisor : AbstractPointcutAdvisor
{
private IAdvice advice;
/// <summary>
/// Abstract PointcutAdvisor that allows for any Advice to be configured.
/// Return the advice part of this advisor.
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public abstract class AbstractGenericPointcutAdvisor : AbstractPointcutAdvisor
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
/// <see cref="Spring.Aop.IAdvisor.Advice"/>
public override IAdvice Advice
{
private IAdvice advice;
get { return this.advice; }
set { this.advice = value; }
}
/// <summary>
/// Return the advice part of this advisor.
/// </summary>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
/// <see cref="Spring.Aop.IAdvisor.Advice"/>
public override IAdvice Advice
{
get { return this.advice; }
set { this.advice = value; }
}
///<summary>
/// 2 <see cref="AbstractGenericPointcutAdvisor"/>s are considered equals, if
/// a) their pointcuts are equal
/// b) their advices are equal
///</summary>
public override bool Equals(object obj)
{
return base.Equals(obj as AbstractGenericPointcutAdvisor);
}
///<summary>
/// 2 <see cref="AbstractGenericPointcutAdvisor"/>s are considered equals, if
/// a) their pointcuts are equal
/// b) their advices are equal
///</summary>
public override bool Equals(object obj)
{
return base.Equals(obj as AbstractGenericPointcutAdvisor);
}
/// <summary>
/// Calculates a unique hashcode based on advice + pointcut
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Calculates a unique hashcode based on advice + pointcut
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents the current
/// <see cref="System.Object"/>.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> representation of this advisor.
/// </returns>
public override string ToString()
{
return GetType().Name + ": advice=[" + Advice + "]";
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents the current
/// <see cref="System.Object"/>.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> representation of this advisor.
/// </returns>
public override string ToString()
{
return GetType().Name + ": advice=[" + Advice + "]";
}
}

View File

@@ -22,115 +22,114 @@ using AopAlliance.Aop;
using Spring.Objects.Factory;
using Spring.Util;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Abstract ObjectFactory-based IPointcutAdvisor that allows for any Advice to be
/// configured as reference to an Advice object in an ObjectFactory.
/// </summary>
/// <remarks>
/// specifying the name of an advice object instead of the advice object itself
/// (if running within an ObjectFactory/ApplicationContext increses loose coupling
/// at initialization time, in order not to initialize the advice object until the
/// pointcut actually matches.
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack</author>
public abstract class AbstractObjectFactoryPointcutAdvisor : AbstractPointcutAdvisor, IObjectFactoryAware
{
private string adviceObjectName;
private IObjectFactory objectFactory;
private IAdvice advice;
private object adviceMonitor = new object();
/// <summary>
/// Abstract ObjectFactory-based IPointcutAdvisor that allows for any Advice to be
/// configured as reference to an Advice object in an ObjectFactory.
/// Gets or sets the name of the advice object that this advisor should refer to.
/// </summary>
/// <remarks>An instance of the specified object will be obtained on first access of
/// this advisor's advice. This advisor will only ever obtain at most one
/// single instance of the advice object, caching the instance for the lifetime of
/// the advisor.</remarks>
/// <value>The name of the advice object.</value>
public string AdviceObjectName
{
get { return adviceObjectName; }
set { adviceObjectName = value; }
}
#region IObjectFactoryAware Members
/// <summary>
/// Callback that supplies the owning factory to an object instance.
/// </summary>
/// <value>
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// (may not be <see langword="null"/>). The object can immediately
/// call methods on the factory.
/// </value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of initialization errors.
/// </exception>
public IObjectFactory ObjectFactory
{
set { objectFactory = value; }
}
#endregion
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <remarks>
/// specifying the name of an advice object instead of the advice object itself
/// (if running within an ObjectFactory/ApplicationContext increses loose coupling
/// at initialization time, in order not to initialize the advice object until the
/// pointcut actually matches.
/// <p>
/// An advice may be an interceptor, a throws advice, before advice,
/// introduction etc.
/// </p>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack</author>
public abstract class AbstractObjectFactoryPointcutAdvisor : AbstractPointcutAdvisor, IObjectFactoryAware
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
public override IAdvice Advice
{
private string adviceObjectName;
private IObjectFactory objectFactory;
private IAdvice advice;
private object adviceMonitor = new object();
/// <summary>
/// Gets or sets the name of the advice object that this advisor should refer to.
/// </summary>
/// <remarks>An instance of the specified object will be obtained on first access of
/// this advisor's advice. This advisor will only ever obtain at most one
/// single instance of the advice object, caching the instance for the lifetime of
/// the advisor.</remarks>
/// <value>The name of the advice object.</value>
public string AdviceObjectName
get
{
get { return adviceObjectName; }
set { adviceObjectName = value; }
}
#region IObjectFactoryAware Members
/// <summary>
/// Callback that supplies the owning factory to an object instance.
/// </summary>
/// <value>
/// Owning <see cref="Spring.Objects.Factory.IObjectFactory"/>
/// (may not be <see langword="null"/>). The object can immediately
/// call methods on the factory.
/// </value>
/// <remarks>
/// <p>
/// Invoked after population of normal object properties but before an init
/// callback like <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// method or a custom init-method.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of initialization errors.
/// </exception>
public IObjectFactory ObjectFactory
{
set { objectFactory = value; }
}
#endregion
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <remarks>
/// <p>
/// An advice may be an interceptor, a throws advice, before advice,
/// introduction etc.
/// </p>
/// </remarks>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
public override IAdvice Advice
{
get
lock (adviceMonitor)
{
lock (adviceMonitor)
if (advice == null && adviceObjectName != null)
{
if (advice == null && adviceObjectName != null)
{
AssertUtils.State(objectFactory != null,
"ObjectFactory must be set to resolve 'adviceObjectName'");
advice = objectFactory.GetObject(adviceObjectName, typeof (IAdvice)) as IAdvice;
}
AssertUtils.State(objectFactory != null,
"ObjectFactory must be set to resolve 'adviceObjectName'");
advice = objectFactory.GetObject(adviceObjectName, typeof(IAdvice)) as IAdvice;
}
return advice;
}
set
{
advice = value;
}
}
/// <summary>
/// Describe this Advisor, showing name of advice object.
/// </summary>
/// <returns>
/// Type name and advice object name.
/// </returns>
public override string ToString()
return advice;
}
set
{
return GetType().Name + ": advice object '" + AdviceObjectName + "'";
advice = value;
}
}
}
/// <summary>
/// Describe this Advisor, showing name of advice object.
/// </summary>
/// <returns>
/// Type name and advice object name.
/// </returns>
public override string ToString()
{
return GetType().Name + ": advice object '" + AdviceObjectName + "'";
}
}

View File

@@ -17,136 +17,136 @@
using AopAlliance.Aop;
using Spring.Core;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Abstract base class for <see cref="IPointcutAdvisor"/> implementations.
/// </summary>
/// <remarks>
/// Can be subclassed for returning a specific pointcut/advice or a freely configurable pointcut/advice.
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public abstract class AbstractPointcutAdvisor : IPointcutAdvisor, IOrdered
{
private int _order = Int32.MaxValue;
/// <summary>
/// Abstract base class for <see cref="IPointcutAdvisor"/> implementations.
/// Returns this <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </summary>
/// <returns>
/// This <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </returns>
public virtual int Order
{
get { return this._order; }
set { this._order = value; }
}
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <remarks>
/// Can be subclassed for returning a specific pointcut/advice or a freely configurable pointcut/advice.
/// <p>
/// An advice may be an interceptor, a throws advice, before advice,
/// introduction etc.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public abstract class AbstractPointcutAdvisor : IPointcutAdvisor, IOrdered
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
public abstract IAdvice Advice { get; set; }
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// Not supported for dynamic advisors.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
/// <exception cref="System.NotSupportedException">Always.</exception>
/// <see cref="Spring.Aop.IAdvisor.IsPerInstance"/>
public virtual bool IsPerInstance
{
private int _order = Int32.MaxValue;
/// <summary>
/// Returns this <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </summary>
/// <returns>
/// This <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </returns>
public virtual int Order
get
{
get { return this._order; }
set { this._order = value; }
}
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <remarks>
/// <p>
/// An advice may be an interceptor, a throws advice, before advice,
/// introduction etc.
/// </p>
/// </remarks>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
public abstract IAdvice Advice { get; set; }
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// Not supported for dynamic advisors.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
/// <exception cref="System.NotSupportedException">Always.</exception>
/// <see cref="Spring.Aop.IAdvisor.IsPerInstance"/>
public virtual bool IsPerInstance
{
get
{
throw new NotSupportedException(
"The 'IsPerInstance' property of the IAdvisor interface " +
"is not yet supported in Spring.NET.");
}
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public abstract IPointcut Pointcut { get; set; }
/// <summary>
/// Determines whether the specified <see cref="System.Object"/>
/// is equal to the current <see cref="System.Object"/>.
/// </summary>
/// <param name="o">The advisor to compare with.</param>
/// <returns>
/// <see langword="true"/> if this instance is equal to the
/// specified <see cref="System.Object"/>.
/// </returns>
public override bool Equals(object o)
{
if (!(o is AbstractPointcutAdvisor))
{
return false;
}
if (ReferenceEquals(this, o))
{
return true;
}
AbstractPointcutAdvisor otherAdvisor = (AbstractPointcutAdvisor)o;
if (this.Order != otherAdvisor.Order)
{
return false;
}
if (otherAdvisor.Advice == null && otherAdvisor.Pointcut == null)
{
return (this.Advice == null && this.Pointcut == null);
}
else if (otherAdvisor.Advice == null)
{
return (Advice == null && otherAdvisor.Pointcut.Equals(this.Pointcut));
}
else if (otherAdvisor.Pointcut == null)
{
return (this.Pointcut == null && otherAdvisor.Advice.Equals(this.Advice));
}
else
{
return otherAdvisor.Advice.Equals(this.Advice) && otherAdvisor.Pointcut.Equals(this.Pointcut);
}
}
/// <summary>
/// Serves as a hash function for a particular type, suitable for use
/// in hashing algorithms and data structures like a hash table.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="System.Object"/>.
/// </returns>
public override int GetHashCode()
{
return 0 // (SPRNET-847) base.GetHashCode()
+ 13 * (Pointcut == null ? 0 : Pointcut.GetHashCode())
+ 27 * (Advice == null ? 0 : Advice.GetHashCode())
+ 31 * Order.GetHashCode();
throw new NotSupportedException(
"The 'IsPerInstance' property of the IAdvisor interface " +
"is not yet supported in Spring.NET.");
}
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public abstract IPointcut Pointcut { get; set; }
/// <summary>
/// Determines whether the specified <see cref="System.Object"/>
/// is equal to the current <see cref="System.Object"/>.
/// </summary>
/// <param name="o">The advisor to compare with.</param>
/// <returns>
/// <see langword="true"/> if this instance is equal to the
/// specified <see cref="System.Object"/>.
/// </returns>
public override bool Equals(object o)
{
if (!(o is AbstractPointcutAdvisor))
{
return false;
}
if (ReferenceEquals(this, o))
{
return true;
}
AbstractPointcutAdvisor otherAdvisor = (AbstractPointcutAdvisor) o;
if (this.Order != otherAdvisor.Order)
{
return false;
}
if (otherAdvisor.Advice == null && otherAdvisor.Pointcut == null)
{
return (this.Advice == null && this.Pointcut == null);
}
else if (otherAdvisor.Advice == null)
{
return (Advice == null && otherAdvisor.Pointcut.Equals(this.Pointcut));
}
else if (otherAdvisor.Pointcut == null)
{
return (this.Pointcut == null && otherAdvisor.Advice.Equals(this.Advice));
}
else
{
return otherAdvisor.Advice.Equals(this.Advice) && otherAdvisor.Pointcut.Equals(this.Pointcut);
}
}
/// <summary>
/// Serves as a hash function for a particular type, suitable for use
/// in hashing algorithms and data structures like a hash table.
/// </summary>
/// <returns>
/// A hash code for the current <see cref="System.Object"/>.
/// </returns>
public override int GetHashCode()
{
return 0 // (SPRNET-847) base.GetHashCode()
+ 13 * (Pointcut == null ? 0 : Pointcut.GetHashCode())
+ 27 * (Advice == null ? 0 : Advice.GetHashCode())
+ 31 * Order.GetHashCode();
}
}

View File

@@ -17,236 +17,233 @@
using System.Reflection;
using System.Runtime.Serialization;
using System.Security.Permissions;
using AopAlliance.Aop;
using Spring.Util;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Abstract base regular expression pointcut object.
/// </summary>
/// <remarks>
/// <p>
/// The regular expressions must be a match. For example, the
/// <code>.*Get.*</code> pattern will match <c>Com.Mycom.Foo.GetBar()</c>, and
/// <code>Get.*</code> will not.
/// </p>
/// <p>
/// This base class is serializable. Subclasses should decorate all
/// fields with the NonSerializedAttribute - the
/// <see cref="AbstractRegularExpressionMethodPointcut.InitPatternRepresentation"/>
/// method in this class will be invoked again on the client side on deserialization.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Simon White (.NET)</author>
[Serializable]
public abstract class AbstractRegularExpressionMethodPointcut
: StaticMethodMatcherPointcut, ITypeFilter, ISerializable
{
[NonSerialized] private object[] _patterns = ObjectUtils.EmptyObjects;
/// <summary>
/// Abstract base regular expression pointcut object.
/// Creates a new instance of the
/// <see cref="AbstractRegularExpressionMethodPointcut"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// The regular expressions must be a match. For example, the
/// <code>.*Get.*</code> pattern will match <c>Com.Mycom.Foo.GetBar()</c>, and
/// <code>Get.*</code> will not.
/// </p>
/// <p>
/// This base class is serializable. Subclasses should decorate all
/// fields with the NonSerializedAttribute - the
/// <see cref="AbstractRegularExpressionMethodPointcut.InitPatternRepresentation"/>
/// method in this class will be invoked again on the client side on deserialization.
/// This is an abstract class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Juergen Hoeller</author>
/// <author>Simon White (.NET)</author>
[Serializable]
public abstract class AbstractRegularExpressionMethodPointcut
: StaticMethodMatcherPointcut, ITypeFilter, ISerializable
protected AbstractRegularExpressionMethodPointcut()
{
[NonSerialized]
private object[] _patterns = ObjectUtils.EmptyObjects;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="AbstractRegularExpressionMethodPointcut"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
protected AbstractRegularExpressionMethodPointcut()
/// <inheritdoc />
protected AbstractRegularExpressionMethodPointcut(
SerializationInfo info, StreamingContext context)
{
_patterns = (object[]) info.GetValue("Patterns", typeof(object[]));
if (_patterns == null)
{
}
/// <inheritdoc />
protected AbstractRegularExpressionMethodPointcut(
SerializationInfo info, StreamingContext context)
{
_patterns = (object[])info.GetValue("Patterns", typeof(object[]));
if (_patterns == null)
{
_patterns = ObjectUtils.EmptyObjects;
}
}
/// <summary>
/// Overridden to ensure proper initialization
/// </summary>
protected override void OnDeserialization(object sender)
{
base.OnDeserialization(sender);
try
{
InitPatternRepresentation(_patterns);
}
catch (Exception ex)
{
throw new AspectException(
"Failed to deserialize AOP regular expression pointcut: " + ex.Message);
}
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public override ITypeFilter TypeFilter
{
get { return this; }
}
/// <summary>
/// Convenience property for setting a single pattern.
/// </summary>
/// <remarks>
/// Use this property or Patterns, not both.
/// </remarks>
public virtual object Pattern
{
get { return (_patterns.Length > 0 ? _patterns[0] : null); }
set
{
AssertUtils.ArgumentNotNull(value, "Pattern");
this.Patterns = new object[] { value };
}
}
/// <summary>
/// The regular expressions defining methods to match.
/// </summary>
/// <remarks>
/// Matching will be the union of all these; if any match,
/// the pointcut matches.
/// </remarks>
public virtual object[] Patterns
{
get { return _patterns; }
set
{
AssertUtils.ArgumentNotNull(value, "Patterns");
this._patterns = value;
InitPatternRepresentation(this.Patterns);
}
}
/// <inheritdoc />
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Patterns", _patterns);
}
/// <summary>
/// Subclasses must implement this to initialize regular expression pointcuts.
/// </summary>
/// <remarks>
/// <p>
/// Can be invoked multiple times.
/// </p>
/// <p>
/// This method will be invoked from the <see cref="Patterns"/> property,
/// and also on deserialization.
/// </p>
/// </remarks>
/// <param name="patterns">
/// The patterns to initialize.
/// </param>
/// <exception cref="System.ArgumentException">
/// In the case of an invalid pattern.
/// </exception>
protected abstract void InitPatternRepresentation(object[] patterns);
/// <summary>
/// Does the pattern at the supplied <paramref name="patternIndex"/>
/// match this <paramref name="pattern"/>?
/// </summary>
/// <param name="pattern">The pattern to match</param>
/// <param name="patternIndex">The index of pattern.</param>
/// <returns>
/// <see langword="true"/> if there is a match.
/// </returns>
protected abstract bool Matches(string pattern, int patternIndex);
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <remarks>
/// <p>
/// Try to match the regular expression against the fully qualified name
/// of the method's declaring <see cref="System.Type"/>, plus the name of
/// the supplied <paramref name="method"/>.
/// </p>
/// <p>
/// Note that the declaring <see cref="System.Type"/> is that
/// <see cref="System.Type"/> that originally declared
/// the method, not necessarily the <see cref="System.Type"/> that is
/// currently exposing it. For example, <see cref="System.Object.Equals(object)"/>
/// matches any subclass of <see cref="System.Object"/>'s
/// <see cref="System.Object.Equals(object)"/> method.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public override bool Matches(MethodInfo method, Type targetType)
{
string patt = string.Empty;
patt = String.Format("{0}.{1}", method.DeclaringType, method.Name);
if (method.DeclaringType.IsGenericType)
{
patt = String.Format("{0}.{1}", ReflectionUtils.GetTypeFriendlyName(method.DeclaringType), method.Name);
}
else
{
patt = String.Format("{0}.{1}", method.DeclaringType, method.Name);
}
for (int i = 0; i < this.Patterns.Length; ++i)
{
bool matched = Matches(patt, i);
if (matched)
{
return true;
}
}
return false;
}
/// <summary>
/// Should the pointcut apply to the supplied
/// <see cref="System.Type"/>?
/// </summary>
/// <remarks>
/// <p>
/// In this instance, simply 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 bool Matches(Type type)
{
return true;
_patterns = ObjectUtils.EmptyObjects;
}
}
/// <summary>
/// Overridden to ensure proper initialization
/// </summary>
protected override void OnDeserialization(object sender)
{
base.OnDeserialization(sender);
try
{
InitPatternRepresentation(_patterns);
}
catch (Exception ex)
{
throw new AspectException(
"Failed to deserialize AOP regular expression pointcut: " + ex.Message);
}
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public override ITypeFilter TypeFilter
{
get { return this; }
}
/// <summary>
/// Convenience property for setting a single pattern.
/// </summary>
/// <remarks>
/// Use this property or Patterns, not both.
/// </remarks>
public virtual object Pattern
{
get { return (_patterns.Length > 0 ? _patterns[0] : null); }
set
{
AssertUtils.ArgumentNotNull(value, "Pattern");
this.Patterns = new object[] { value };
}
}
/// <summary>
/// The regular expressions defining methods to match.
/// </summary>
/// <remarks>
/// Matching will be the union of all these; if any match,
/// the pointcut matches.
/// </remarks>
public virtual object[] Patterns
{
get { return _patterns; }
set
{
AssertUtils.ArgumentNotNull(value, "Patterns");
this._patterns = value;
InitPatternRepresentation(this.Patterns);
}
}
/// <inheritdoc />
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Patterns", _patterns);
}
/// <summary>
/// Subclasses must implement this to initialize regular expression pointcuts.
/// </summary>
/// <remarks>
/// <p>
/// Can be invoked multiple times.
/// </p>
/// <p>
/// This method will be invoked from the <see cref="Patterns"/> property,
/// and also on deserialization.
/// </p>
/// </remarks>
/// <param name="patterns">
/// The patterns to initialize.
/// </param>
/// <exception cref="System.ArgumentException">
/// In the case of an invalid pattern.
/// </exception>
protected abstract void InitPatternRepresentation(object[] patterns);
/// <summary>
/// Does the pattern at the supplied <paramref name="patternIndex"/>
/// match this <paramref name="pattern"/>?
/// </summary>
/// <param name="pattern">The pattern to match</param>
/// <param name="patternIndex">The index of pattern.</param>
/// <returns>
/// <see langword="true"/> if there is a match.
/// </returns>
protected abstract bool Matches(string pattern, int patternIndex);
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <remarks>
/// <p>
/// Try to match the regular expression against the fully qualified name
/// of the method's declaring <see cref="System.Type"/>, plus the name of
/// the supplied <paramref name="method"/>.
/// </p>
/// <p>
/// Note that the declaring <see cref="System.Type"/> is that
/// <see cref="System.Type"/> that originally declared
/// the method, not necessarily the <see cref="System.Type"/> that is
/// currently exposing it. For example, <see cref="System.Object.Equals(object)"/>
/// matches any subclass of <see cref="System.Object"/>'s
/// <see cref="System.Object.Equals(object)"/> method.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public override bool Matches(MethodInfo method, Type targetType)
{
string patt = string.Empty;
patt = String.Format("{0}.{1}", method.DeclaringType, method.Name);
if (method.DeclaringType.IsGenericType)
{
patt = String.Format("{0}.{1}", ReflectionUtils.GetTypeFriendlyName(method.DeclaringType), method.Name);
}
else
{
patt = String.Format("{0}.{1}", method.DeclaringType, method.Name);
}
for (int i = 0; i < this.Patterns.Length; ++i)
{
bool matched = Matches(patt, i);
if (matched)
{
return true;
}
}
return false;
}
/// <summary>
/// Should the pointcut apply to the supplied
/// <see cref="System.Type"/>?
/// </summary>
/// <remarks>
/// <p>
/// In this instance, simply 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 bool Matches(Type type)
{
return true;
}
}

View File

@@ -1,20 +1,20 @@
#region License
/*
* Copyright 2002-2010 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.
*/
* Copyright 2002-2010 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
@@ -22,210 +22,210 @@
using System.Reflection;
using System.Runtime.Serialization;
using Spring.Util;
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// <see cref="Spring.Aop.IPointcut"/> implementation that matches methods
/// that have been decorated with a specified <see cref="System.Attribute"/>.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Ronald Wildenberg</author>
[Serializable]
public class AttributeMatchMethodPointcut : StaticMethodMatcherPointcut, ISerializable
{
/// <summary>
/// <see cref="Spring.Aop.IPointcut"/> implementation that matches methods
/// that have been decorated with a specified <see cref="System.Attribute"/>.
/// </summary>
/// <author>Aleksandar Seovic</author>
/// <author>Ronald Wildenberg</author>
[Serializable]
public class AttributeMatchMethodPointcut : StaticMethodMatcherPointcut, ISerializable
{
private Type _attribute;
private bool _inherit = true;
private bool _checkInterfaces = false;
private Type _attribute;
private bool _inherit = true;
private bool _checkInterfaces = false;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/> class.
/// </summary>
public AttributeMatchMethodPointcut()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/> class.
/// </summary>
public AttributeMatchMethodPointcut()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/> class.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
public AttributeMatchMethodPointcut(Type attribute)
: this(attribute, true, false)
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/> class.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
public AttributeMatchMethodPointcut(Type attribute)
: this(attribute, true, false)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/>
/// class.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
/// <param name="inherit">
/// Flag that controls whether or not the inheritance tree of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
public AttributeMatchMethodPointcut(Type attribute, bool inherit)
: this(attribute, inherit, false)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/>
/// class.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
/// <param name="inherit">
/// Flag that controls whether or not the inheritance tree of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
/// <param name="checkInterfaces">
/// Flag that controls whether or not interfaces attributes of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
public AttributeMatchMethodPointcut(Type attribute, bool inherit, bool checkInterfaces)
{
Attribute = attribute;
Inherit = inherit;
CheckInterfaces = checkInterfaces;
}
/// <inheritdoc />
protected AttributeMatchMethodPointcut(SerializationInfo info, StreamingContext context)
{
Inherit = info.GetBoolean("Inherit");
CheckInterfaces = info.GetBoolean("CheckInterfaces");
var type = info.GetString("Attribute");
Attribute = type != null ? Type.GetType(type) : null;
}
/// <inheritdoc />
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Attribute", Attribute?.AssemblyQualifiedName);
info.AddValue("Inherit", Inherit);
info.AddValue("CheckInterfaces", CheckInterfaces);
}
/// <summary>
/// The <see cref="System.Attribute"/> to match.
/// </summary>
/// <exception cref="System.ArgumentException">
/// If the supplied value is not a <see cref="System.Type"/> that
/// derives from the <see cref="System.Attribute"/> class.
/// </exception>
public virtual Type Attribute
{
get { return _attribute; }
set
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/>
/// class.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
/// <param name="inherit">
/// Flag that controls whether or not the inheritance tree of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
public AttributeMatchMethodPointcut(Type attribute, bool inherit)
: this(attribute, inherit, false)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.AttributeMatchMethodPointcut"/>
/// class.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
/// <param name="inherit">
/// Flag that controls whether or not the inheritance tree of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
/// <param name="checkInterfaces">
/// Flag that controls whether or not interfaces attributes of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
public AttributeMatchMethodPointcut(Type attribute, bool inherit, bool checkInterfaces)
{
Attribute = attribute;
Inherit = inherit;
CheckInterfaces = checkInterfaces;
}
/// <inheritdoc />
protected AttributeMatchMethodPointcut(SerializationInfo info, StreamingContext context)
{
Inherit = info.GetBoolean("Inherit");
CheckInterfaces = info.GetBoolean("CheckInterfaces");
var type = info.GetString("Attribute");
Attribute = type != null ? Type.GetType(type) : null;
}
/// <inheritdoc />
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Attribute", Attribute?.AssemblyQualifiedName);
info.AddValue("Inherit", Inherit);
info.AddValue("CheckInterfaces", CheckInterfaces);
}
/// <summary>
/// The <see cref="System.Attribute"/> to match.
/// </summary>
/// <exception cref="System.ArgumentException">
/// If the supplied value is not a <see cref="System.Type"/> that
/// derives from the <see cref="System.Attribute"/> class.
/// </exception>
public virtual Type Attribute
{
get { return _attribute; }
set
{
if (value != null)
{
if (!typeof (Attribute).IsAssignableFrom(value))
{
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
value));
}
}
_attribute = value;
}
}
/// <summary>
/// Is the inheritance tree of the method to be included in the search for the
/// <see cref="Attribute"/>?
/// </summary>
/// <remarks>
/// <p>
/// The default is <see langword="true"/>.
/// </p>
/// </remarks>
public virtual bool Inherit
{
get { return _inherit; }
set { _inherit = value; }
}
/// <summary>
/// Is the interfaces attributes of the method to be included in the search for theg
/// <see cref="Attribute"/>?
/// </summary>
/// <remarks>
/// <p>
/// The default is <see langword="false"/>.
/// </p>
/// </remarks>
public virtual bool CheckInterfaces
{
get { return _checkInterfaces; }
set { _checkInterfaces = value; }
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public override bool Matches(MethodInfo method, Type targetType)
{
if (method.IsDefined(Attribute, Inherit))
if (value != null)
{
// Checks whether the attribute is defined on the method or a super definition of the method
// but does not check attributes on implemented interfaces.
return true;
}
else
{
if (CheckInterfaces)
if (!typeof(Attribute).IsAssignableFrom(value))
{
// Also check whether the attribute is defined on a method implemented from an interface.
// First find all interfaces for the type that contains the method.
// Next, check each interface for the presence of the attribute on the corresponding
// method from the interface.
Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method);
foreach (Type interfaceType in method.DeclaringType.GetInterfaces())
{
// The method may be implemented explicitly, so the method name
// will include the interface name also
string methodName = method.Name;
if (methodName.IndexOf('.') != -1)
{
if (methodName.StartsWith(interfaceType.FullName.Replace('+', '.')))
{
methodName = methodName.Remove(0, interfaceType.FullName.Length + 1);
}
}
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
value));
}
}
MethodInfo intfMethod = interfaceType.GetMethod(methodName, parameterTypes);
if (intfMethod != null && intfMethod.IsDefined(Attribute, Inherit))
_attribute = value;
}
}
/// <summary>
/// Is the inheritance tree of the method to be included in the search for the
/// <see cref="Attribute"/>?
/// </summary>
/// <remarks>
/// <p>
/// The default is <see langword="true"/>.
/// </p>
/// </remarks>
public virtual bool Inherit
{
get { return _inherit; }
set { _inherit = value; }
}
/// <summary>
/// Is the interfaces attributes of the method to be included in the search for theg
/// <see cref="Attribute"/>?
/// </summary>
/// <remarks>
/// <p>
/// The default is <see langword="false"/>.
/// </p>
/// </remarks>
public virtual bool CheckInterfaces
{
get { return _checkInterfaces; }
set { _checkInterfaces = value; }
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public override bool Matches(MethodInfo method, Type targetType)
{
if (method.IsDefined(Attribute, Inherit))
{
// Checks whether the attribute is defined on the method or a super definition of the method
// but does not check attributes on implemented interfaces.
return true;
}
else
{
if (CheckInterfaces)
{
// Also check whether the attribute is defined on a method implemented from an interface.
// First find all interfaces for the type that contains the method.
// Next, check each interface for the presence of the attribute on the corresponding
// method from the interface.
Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method);
foreach (Type interfaceType in method.DeclaringType.GetInterfaces())
{
// The method may be implemented explicitly, so the method name
// will include the interface name also
string methodName = method.Name;
if (methodName.IndexOf('.') != -1)
{
if (methodName.StartsWith(interfaceType.FullName.Replace('+', '.')))
{
return true;
methodName = methodName.Remove(0, interfaceType.FullName.Length + 1);
}
}
MethodInfo intfMethod = interfaceType.GetMethod(methodName, parameterTypes);
if (intfMethod != null && intfMethod.IsDefined(Attribute, Inherit))
{
return true;
}
}
return false;
}
}
}
return false;
}
}
}

View File

@@ -21,133 +21,131 @@
#region Imports
using System.Runtime.Serialization;
using AopAlliance.Aop;
using Spring.Core;
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Convenient class for attribute-match method pointcuts that hold an Interceptor,
/// making them an Advisor.
/// </summary>
/// <author>Bruno Baia</author>
[Serializable]
public class AttributeMatchMethodPointcutAdvisor
: AttributeMatchMethodPointcut, IPointcutAdvisor, IOrdered, ISerializable
{
/// <summary>
/// Convenient class for attribute-match method pointcuts that hold an Interceptor,
/// making them an Advisor.
/// </summary>
/// <author>Bruno Baia</author>
[Serializable]
public class AttributeMatchMethodPointcutAdvisor
: AttributeMatchMethodPointcut, IPointcutAdvisor, IOrdered, ISerializable
{
private int _order = Int32.MaxValue;
private IAdvice _advice;
private int _order = Int32.MaxValue;
private IAdvice _advice;
/// <summary>
/// Creates a new instance of the
/// <see cref="AttributeMatchMethodPointcutAdvisor"/> class.
/// </summary>
public AttributeMatchMethodPointcutAdvisor()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="AttributeMatchMethodPointcutAdvisor"/> class.
/// </summary>
public AttributeMatchMethodPointcutAdvisor()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="AttributeMatchMethodPointcutAdvisor"/> class
/// for the supplied <paramref name="advice"/>.
/// </summary>
/// <param name="advice">the advice to apply if the pointcut matches</param>
public AttributeMatchMethodPointcutAdvisor(IAdvice advice)
{
this._advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="AttributeMatchMethodPointcutAdvisor"/> class
/// for the supplied <paramref name="advice"/>.
/// </summary>
/// <param name="advice">the advice to apply if the pointcut matches</param>
public AttributeMatchMethodPointcutAdvisor(IAdvice advice)
{
this._advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="AttributeMatchMethodPointcutAdvisor"/> class
/// for the supplied <paramref name="advice"/>.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
/// <param name="inherit">
/// Flag that controls whether or not the inheritance tree of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
/// <param name="advice">the advice to apply if the pointcut matches</param>
public AttributeMatchMethodPointcutAdvisor(Type attribute, bool inherit, IAdvice advice)
:base(attribute, inherit)
{
this._advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="AttributeMatchMethodPointcutAdvisor"/> class
/// for the supplied <paramref name="advice"/>.
/// </summary>
/// <param name="attribute">
/// The <see cref="System.Attribute"/> to match.
/// </param>
/// <param name="inherit">
/// Flag that controls whether or not the inheritance tree of the
/// method to be included in the search for the <see cref="Attribute"/>?
/// </param>
/// <param name="advice">the advice to apply if the pointcut matches</param>
public AttributeMatchMethodPointcutAdvisor(Type attribute, bool inherit, IAdvice advice)
: base(attribute, inherit)
{
this._advice = advice;
}
/// <inheritdoc />
private AttributeMatchMethodPointcutAdvisor(SerializationInfo info, StreamingContext context)
: base(info, context)
{
Order = info.GetInt32("Order");
Advice = (IAdvice) info.GetValue("Advice", typeof(IAdvice));
}
/// <inheritdoc />
private AttributeMatchMethodPointcutAdvisor(SerializationInfo info, StreamingContext context)
: base(info, context)
{
Order = info.GetInt32("Order");
Advice = (IAdvice) info.GetValue("Advice", typeof(IAdvice));
}
/// <inheritdoc />
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Order", Order);
info.AddValue("Advice", Advice);
}
/// <inheritdoc />
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("Order", Order);
info.AddValue("Advice", Advice);
}
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
/// <exception cref="System.NotSupportedException">
/// Always; this property is not yet supported.
/// </exception>
public virtual bool IsPerInstance
{
get
{
throw new NotSupportedException(
"The 'IsPerInstance' property of the IAdvisor interface is " +
"not yet supported in Spring.NET.");
}
}
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
/// <exception cref="System.NotSupportedException">
/// Always; this property is not yet supported.
/// </exception>
public virtual bool IsPerInstance
{
get
{
throw new NotSupportedException(
"The 'IsPerInstance' property of the IAdvisor interface is " +
"not yet supported in Spring.NET.");
}
}
/// <summary>
/// Returns this <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </summary>
/// <returns>
/// This <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </returns>
public virtual int Order
{
get { return this._order; }
set { this._order = value; }
}
/// <summary>
/// Returns this <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </summary>
/// <returns>
/// This <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </returns>
public virtual int Order
{
get { return this._order; }
set { this._order = value; }
}
/// <summary>
/// Return the advice part of this advisor.
/// </summary>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
/// <see cref="Spring.Aop.IAdvisor.Advice"/>
public virtual IAdvice Advice
{
get { return this._advice; }
set { this._advice = value; }
}
/// <summary>
/// Return the advice part of this advisor.
/// </summary>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
/// <see cref="Spring.Aop.IAdvisor.Advice"/>
public virtual IAdvice Advice
{
get { return this._advice; }
set { this._advice = value; }
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public virtual IPointcut Pointcut
{
get { return this; }
}
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public virtual IPointcut Pointcut
{
get { return this; }
}
}

View File

@@ -20,102 +20,102 @@
using Spring.Util;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Pointcut that looks for a specific attribute being present on a class or
/// method.
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public class AttributeMatchingPointcut : IPointcut
{
private readonly ITypeFilter typeFilter;
private readonly IMethodMatcher methodMatcher;
/// <summary>
/// Pointcut that looks for a specific attribute being present on a class or
/// method.
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the
/// given attribute type.
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
[Serializable]
public class AttributeMatchingPointcut : IPointcut
/// <param name="attributeType">Type of the attribute to look for at the class level.</param>
public AttributeMatchingPointcut(Type attributeType)
{
private readonly ITypeFilter typeFilter;
private readonly IMethodMatcher methodMatcher;
ValidateAttributeTypeArgument(attributeType);
this.typeFilter = new AttributeTypeFilter(attributeType);
this.methodMatcher = TrueMethodMatcher.True;
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the
/// given attribute type
/// </summary>
/// <param name="attributeType">Type of the attribute.</param>
/// <param name="checkInherited">if set to <c>true</c> [check inherited].</param>
public AttributeMatchingPointcut(Type attributeType, bool checkInherited)
{
ValidateAttributeTypeArgument(attributeType);
this.typeFilter = new AttributeTypeFilter(attributeType, checkInherited);
this.methodMatcher = TrueMethodMatcher.True;
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the
/// given attribute type.
/// </summary>
/// <param name="attributeType">Type of the attribute to look for at the class level.</param>
public AttributeMatchingPointcut(Type attributeType)
/// <summary>
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the given
/// attribute type
/// </summary>
/// <param name="classAttributeType">The attribute type to look for at the class level.</param>
/// <param name="methodAttributeType">The attribute type to look for at the method attribute.</param>
public AttributeMatchingPointcut(Type classAttributeType, Type methodAttributeType)
{
AssertUtils.IsTrue(classAttributeType != null || methodAttributeType != null,
"Either Type attribute type or Method attribute type needs to be specified (or both)");
if (classAttributeType != null)
{
this.typeFilter = new AttributeTypeFilter(classAttributeType);
}
else
{
this.typeFilter = TrueTypeFilter.True;
}
if (methodAttributeType != null)
{
this.methodMatcher = new AttributeMethodMatcher(methodAttributeType);
}
else
{
ValidateAttributeTypeArgument(attributeType);
this.typeFilter = new AttributeTypeFilter(attributeType);
this.methodMatcher = TrueMethodMatcher.True;
}
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the
/// given attribute type
/// </summary>
/// <param name="attributeType">Type of the attribute.</param>
/// <param name="checkInherited">if set to <c>true</c> [check inherited].</param>
public AttributeMatchingPointcut(Type attributeType, bool checkInherited)
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>The current <see cref="Spring.Aop.ITypeFilter"/>.</value>
public ITypeFilter TypeFilter
{
get { return this.typeFilter; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>The current <see cref="Spring.Aop.IMethodMatcher"/>.</value>
public IMethodMatcher MethodMatcher
{
get { return this.methodMatcher; }
}
private static void ValidateAttributeTypeArgument(Type attributeType)
{
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
if (!typeof(Attribute).IsAssignableFrom(attributeType))
{
ValidateAttributeTypeArgument(attributeType);
this.typeFilter = new AttributeTypeFilter(attributeType, checkInherited);
this.methodMatcher = TrueMethodMatcher.True;
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeMatchingPointcut"/> class for the given
/// attribute type
/// </summary>
/// <param name="classAttributeType">The attribute type to look for at the class level.</param>
/// <param name="methodAttributeType">The attribute type to look for at the method attribute.</param>
public AttributeMatchingPointcut(Type classAttributeType, Type methodAttributeType)
{
AssertUtils.IsTrue(classAttributeType != null || methodAttributeType != null,
"Either Type attribute type or Method attribute type needs to be specified (or both)");
if (classAttributeType != null)
{
this.typeFilter = new AttributeTypeFilter(classAttributeType);
} else
{
this.typeFilter = TrueTypeFilter.True;
}
if (methodAttributeType != null)
{
this.methodMatcher = new AttributeMethodMatcher(methodAttributeType);
} else
{
this.methodMatcher = TrueMethodMatcher.True;
}
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>The current <see cref="Spring.Aop.ITypeFilter"/>.</value>
public ITypeFilter TypeFilter
{
get { return this.typeFilter; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>The current <see cref="Spring.Aop.IMethodMatcher"/>.</value>
public IMethodMatcher MethodMatcher
{
get { return this.methodMatcher; }
}
private static void ValidateAttributeTypeArgument(Type attributeType)
{
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
if (!typeof(Attribute).IsAssignableFrom(attributeType))
{
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
attributeType));
}
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
attributeType));
}
}
}

View File

@@ -20,105 +20,101 @@
using System.Reflection;
using System.Runtime.Serialization;
using Spring.Util;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// MethodMatcher that looks for a specific attribute being present on the
/// method (checking both the method on the onviked interface, if any and the corresponding
/// method on the target class
/// </summary>
/// <author>Juergen hoeller</author>
/// <author>Mark Pollack</author>
/// <seealso cref="AttributeMatchingPointcut"/>
[Serializable]
public class AttributeMethodMatcher : StaticMethodMatcher, ISerializable
{
private readonly Type attributeType;
/// <summary>
/// MethodMatcher that looks for a specific attribute being present on the
/// method (checking both the method on the onviked interface, if any and the corresponding
/// method on the target class
/// Initializes a new instance of the <see cref="AttributeMethodMatcher"/> class for the
/// given atribute type.
/// </summary>
/// <author>Juergen hoeller</author>
/// <author>Mark Pollack</author>
/// <seealso cref="AttributeMatchingPointcut"/>
[Serializable]
public class AttributeMethodMatcher : StaticMethodMatcher, ISerializable
/// <param name="attributeType">Type of the attribute to look for.</param>
public AttributeMethodMatcher(Type attributeType)
{
private readonly Type attributeType;
ValidateAttributeTypeArgument(attributeType);
this.attributeType = attributeType;
}
/// <inheritdoc />
private AttributeMethodMatcher(SerializationInfo info, StreamingContext context)
{
var type = info.GetString("AttributeType");
attributeType = type != null ? Type.GetType(type) : null;
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeMethodMatcher"/> class for the
/// given atribute type.
/// </summary>
/// <param name="attributeType">Type of the attribute to look for.</param>
public AttributeMethodMatcher(Type attributeType)
/// <inheritdoc />
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("AttributeType", attributeType?.AssemblyQualifiedName);
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).</param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
/// <remarks>
/// <p>
/// Must be implemented by a derived class in order to specify matching
/// rules.
/// </p>
/// </remarks>
public override bool Matches(MethodInfo method, Type targetType)
{
if (method.IsDefined(attributeType, true))
{
ValidateAttributeTypeArgument(attributeType);
this.attributeType = attributeType;
// Checks whether the attribute is defined on the method or a super definition of the method
// but does not check attributes on implemented interfaces.
return true;
}
/// <inheritdoc />
private AttributeMethodMatcher(SerializationInfo info, StreamingContext context)
else
{
var type = info.GetString("AttributeType");
attributeType = type != null ? Type.GetType(type) : null;
}
Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method);
/// <inheritdoc />
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("AttributeType", attributeType?.AssemblyQualifiedName);
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).</param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
/// <remarks>
/// <p>
/// Must be implemented by a derived class in order to specify matching
/// rules.
/// </p>
/// </remarks>
public override bool Matches(MethodInfo method, Type targetType)
{
if (method.IsDefined(attributeType, true))
// Also check whether the attribute is defined on a method implemented from an interface.
// First find all interfaces for the type that contains the method.
// Next, check each interface for the presence of the attribute on the corresponding
// method from the interface.
foreach (Type interfaceType in method.DeclaringType.GetInterfaces())
{
// Checks whether the attribute is defined on the method or a super definition of the method
// but does not check attributes on implemented interfaces.
return true;
MethodInfo intfMethod = interfaceType.GetMethod(method.Name, parameterTypes);
if (intfMethod != null && intfMethod.IsDefined(attributeType, true))
{
return true;
}
}
else
{
Type[] parameterTypes = ReflectionUtils.GetParameterTypes(method);
// Also check whether the attribute is defined on a method implemented from an interface.
// First find all interfaces for the type that contains the method.
// Next, check each interface for the presence of the attribute on the corresponding
// method from the interface.
foreach (Type interfaceType in method.DeclaringType.GetInterfaces())
{
MethodInfo intfMethod = interfaceType.GetMethod(method.Name, parameterTypes);
if (intfMethod != null && intfMethod.IsDefined(attributeType, true))
{
return true;
}
}
return false;
}
return false;
}
}
private static void ValidateAttributeTypeArgument(Type attributeType)
private static void ValidateAttributeTypeArgument(Type attributeType)
{
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
if (!typeof(Attribute).IsAssignableFrom(attributeType))
{
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
if (!typeof(Attribute).IsAssignableFrom(attributeType))
{
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
attributeType));
}
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
attributeType));
}
}
}

View File

@@ -20,88 +20,86 @@
using Spring.Util;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// ITypeFilter that looks for a specific attribute being present on a class
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
public class AttributeTypeFilter : ITypeFilter
{
private readonly Type attributeType;
private readonly bool checkInherited;
/// <summary>
/// ITypeFilter that looks for a specific attribute being present on a class
/// The attribute <see cref="Type"/> for this filter.
/// </summary>
/// <author>Juergen Hoeller</author>
/// <author>Mark Pollack (.NET)</author>
public class AttributeTypeFilter : ITypeFilter
public Type AttributeType
{
private readonly Type attributeType;
private readonly bool checkInherited;
get { return attributeType; }
}
/// <summary>
/// The attribute <see cref="Type"/> for this filter.
/// </summary>
public Type AttributeType
/// <summary>
/// Indicates, whether this filter considers base types for filtering.
/// </summary>
public bool CheckInherited
{
get { return checkInherited; }
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeTypeFilter"/> class for the
/// given attribute type.
/// </summary>
/// <param name="attributeType">Type of the attribute to look for.</param>
public AttributeTypeFilter(Type attributeType) : this(attributeType, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeTypeFilter"/> class for the
/// given attribute type.
/// </summary>
/// <param name="attributeType">Type of the attribute.</param>
/// <param name="checkInherited">if set to <c>true</c> [check inherited].</param>
public AttributeTypeFilter(Type attributeType, bool checkInherited)
{
#region parameter validation
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
if (!typeof(Attribute).IsAssignableFrom(attributeType))
{
get { return attributeType; }
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
attributeType));
}
/// <summary>
/// Indicates, whether this filter considers base types for filtering.
/// </summary>
public bool CheckInherited
#endregion
this.attributeType = attributeType;
this.checkInherited = checkInherited;
}
/// <summary>
/// Should the pointcut apply to the supplied <see cref="System.Type"/>?
/// </summary>
/// <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 bool Matches(Type type)
{
if (checkInherited)
{
get { return checkInherited; }
return AttributeUtils.FindAttribute(type, attributeType) != null;
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeTypeFilter"/> class for the
/// given attribute type.
/// </summary>
/// <param name="attributeType">Type of the attribute to look for.</param>
public AttributeTypeFilter(Type attributeType) : this(attributeType, false)
else
{
object[] atts = type.GetCustomAttributes(attributeType, false);
return ArrayUtils.HasLength(atts);
}
/// <summary>
/// Initializes a new instance of the <see cref="AttributeTypeFilter"/> class for the
/// given attribute type.
/// </summary>
/// <param name="attributeType">Type of the attribute.</param>
/// <param name="checkInherited">if set to <c>true</c> [check inherited].</param>
public AttributeTypeFilter(Type attributeType, bool checkInherited)
{
#region parameter validation
AssertUtils.ArgumentNotNull(attributeType, "attributeType");
if (!typeof(Attribute).IsAssignableFrom(attributeType))
{
throw new ArgumentException(
string.Format(
"The [{0}] Type must be derived from the [System.Attribute] class.",
attributeType));
}
#endregion
this.attributeType = attributeType;
this.checkInherited = checkInherited;
}
/// <summary>
/// Should the pointcut apply to the supplied <see cref="System.Type"/>?
/// </summary>
/// <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 bool Matches(Type type)
{
if (checkInherited)
{
return AttributeUtils.FindAttribute(type, attributeType) != null;
}
else
{
object[] atts = type.GetCustomAttributes(attributeType, false);
return ArrayUtils.HasLength(atts);
}
}
}
}

View File

@@ -22,152 +22,151 @@
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Convenient class for building up pointcuts.
/// </summary>
/// <remarks>
/// <p>
/// All methods return a <see cref="Spring.Aop.Support.ComposablePointcut"/>
/// instance, which facilitates the following concise usage pattern...
/// </p>
/// <code language="C#">
/// IPointcut pointcut = new ComposablePointcut()
/// .Union(typeFilter)
/// .Intersection(methodMatcher)
/// .Intersection(pointcut);
/// </code>
/// <p>
/// There is no <c>Union()</c> method on this class. Use the
/// <see cref="Spring.Aop.Support.Pointcuts.Union"/> method for such functionality.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class ComposablePointcut : IPointcut
{
/// <summary>
/// Convenient class for building up pointcuts.
/// </summary>
/// <remarks>
/// <p>
/// All methods return a <see cref="Spring.Aop.Support.ComposablePointcut"/>
/// instance, which facilitates the following concise usage pattern...
/// </p>
/// <code language="C#">
/// IPointcut pointcut = new ComposablePointcut()
/// .Union(typeFilter)
/// .Intersection(methodMatcher)
/// .Intersection(pointcut);
/// </code>
/// <p>
/// There is no <c>Union()</c> method on this class. Use the
/// <see cref="Spring.Aop.Support.Pointcuts.Union"/> method for such functionality.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class ComposablePointcut : IPointcut
{
private ITypeFilter _typeFilter;
private IMethodMatcher _methodMatcher;
private ITypeFilter _typeFilter;
private IMethodMatcher _methodMatcher;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.ComposablePointcut"/> class
/// that matches all the methods on all <see cref="System.Type"/>s.
/// </summary>
public ComposablePointcut()
{
_typeFilter = TrueTypeFilter.True;
_methodMatcher = TrueMethodMatcher.True;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.ComposablePointcut"/> class
/// that matches all the methods on all <see cref="System.Type"/>s.
/// </summary>
public ComposablePointcut()
{
_typeFilter = TrueTypeFilter.True;
_methodMatcher = TrueMethodMatcher.True;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.ComposablePointcut"/> class
/// that uses the supplied <paramref name="typeFilter"/> and
/// <paramref name="methodMatcher"/>.
/// </summary>
/// <param name="typeFilter">
/// The type filter to use.
/// </param>
/// <param name="methodMatcher">
/// The method matcher to use.
/// </param>
public ComposablePointcut(ITypeFilter typeFilter, IMethodMatcher methodMatcher)
{
_typeFilter = typeFilter;
_methodMatcher = methodMatcher;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.ComposablePointcut"/> class
/// that uses the supplied <paramref name="typeFilter"/> and
/// <paramref name="methodMatcher"/>.
/// </summary>
/// <param name="typeFilter">
/// The type filter to use.
/// </param>
/// <param name="methodMatcher">
/// The method matcher to use.
/// </param>
public ComposablePointcut(ITypeFilter typeFilter, IMethodMatcher methodMatcher)
{
_typeFilter = typeFilter;
_methodMatcher = methodMatcher;
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public virtual ITypeFilter TypeFilter
{
get { return _typeFilter; }
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public virtual ITypeFilter TypeFilter
{
get { return _typeFilter; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
public virtual IMethodMatcher MethodMatcher
{
get { return _methodMatcher; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
public virtual IMethodMatcher MethodMatcher
{
get { return _methodMatcher; }
}
/// <summary>
/// Changes the current type filter to be the union of the existing filter and the
/// supplied <paramref name="filter"/>.
/// </summary>
/// <param name="filter">The filter to union with.</param>
/// <returns>
/// The union of the existing filter and the supplied <paramref name="filter"/>.
/// </returns>
public virtual ComposablePointcut Union(ITypeFilter filter)
{
_typeFilter = TypeFilters.Union(_typeFilter, filter);
return this;
}
/// <summary>
/// Changes the current type filter to be the union of the existing filter and the
/// supplied <paramref name="filter"/>.
/// </summary>
/// <param name="filter">The filter to union with.</param>
/// <returns>
/// The union of the existing filter and the supplied <paramref name="filter"/>.
/// </returns>
public virtual ComposablePointcut Union(ITypeFilter filter)
{
_typeFilter = TypeFilters.Union(_typeFilter, filter);
return this;
}
/// <summary>
/// Changes the current type filter to be the intersection of the existing filter
/// and the supplied <paramref name="filter"/>.
/// </summary>
/// <param name="filter">The filter to diff against.</param>
/// <returns>
/// The intersection of the existing filter and the supplied <paramref name="filter"/>.
/// </returns>
public virtual ComposablePointcut Intersection(ITypeFilter filter)
{
_typeFilter = TypeFilters.Intersection(_typeFilter, filter);
return this;
}
/// <summary>
/// Changes the current type filter to be the intersection of the existing filter
/// and the supplied <paramref name="filter"/>.
/// </summary>
/// <param name="filter">The filter to diff against.</param>
/// <returns>
/// The intersection of the existing filter and the supplied <paramref name="filter"/>.
/// </returns>
public virtual ComposablePointcut Intersection(ITypeFilter filter)
{
_typeFilter = TypeFilters.Intersection(_typeFilter, filter);
return this;
}
/// <summary>
/// Changes the current method matcher to be the union of the existing matcher and the
/// supplied <paramref name="matcher"/>.
/// </summary>
/// <param name="matcher">The matcher to union with.</param>
/// <returns>
/// The union of the existing matcher and the supplied <paramref name="matcher"/>.
/// </returns>
public virtual ComposablePointcut Union(IMethodMatcher matcher)
{
_methodMatcher = MethodMatchers.Union(_methodMatcher, matcher);
return this;
}
/// <summary>
/// Changes the current method matcher to be the union of the existing matcher and the
/// supplied <paramref name="matcher"/>.
/// </summary>
/// <param name="matcher">The matcher to union with.</param>
/// <returns>
/// The union of the existing matcher and the supplied <paramref name="matcher"/>.
/// </returns>
public virtual ComposablePointcut Union(IMethodMatcher matcher)
{
_methodMatcher = MethodMatchers.Union(_methodMatcher, matcher);
return this;
}
/// <summary>
/// Changes the current method matcher to be the intersection of the existing matcher
/// and the supplied <paramref name="matcher"/>.
/// </summary>
/// <param name="matcher">The matcher to diff against.</param>
/// <returns>
/// The intersection of the existing matcher and the supplied <paramref name="matcher"/>.
/// </returns>
public virtual ComposablePointcut Intersection(IMethodMatcher matcher)
{
_methodMatcher = MethodMatchers.Intersection(_methodMatcher, matcher);
return this;
}
/// <summary>
/// Changes the current method matcher to be the intersection of the existing matcher
/// and the supplied <paramref name="matcher"/>.
/// </summary>
/// <param name="matcher">The matcher to diff against.</param>
/// <returns>
/// The intersection of the existing matcher and the supplied <paramref name="matcher"/>.
/// </returns>
public virtual ComposablePointcut Intersection(IMethodMatcher matcher)
{
_methodMatcher = MethodMatchers.Intersection(_methodMatcher, matcher);
return this;
}
/// <summary>
/// Changes current pointcut to intersection of the current and supplied pointcut
/// </summary>
/// <param name="other">pointcut to diff against</param>
/// <returns>updated pointcut</returns>
public virtual ComposablePointcut Intersection(IPointcut other)
{
_typeFilter = TypeFilters.Intersection(_typeFilter, other.TypeFilter);
_methodMatcher = MethodMatchers.Intersection(_methodMatcher, other.MethodMatcher);
return this;
}
}
/// <summary>
/// Changes current pointcut to intersection of the current and supplied pointcut
/// </summary>
/// <param name="other">pointcut to diff against</param>
/// <returns>updated pointcut</returns>
public virtual ComposablePointcut Intersection(IPointcut other)
{
_typeFilter = TypeFilters.Intersection(_typeFilter, other.TypeFilter);
_methodMatcher = MethodMatchers.Intersection(_methodMatcher, other.MethodMatcher);
return this;
}
}

View File

@@ -16,222 +16,220 @@
using System.Reflection;
using System.Runtime.Serialization;
using Spring.Core;
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Pointcut and method matcher for use in simple <b>cflow</b>-style
/// pointcuts.
/// </summary>
/// <remarks>
/// <p>
/// Evaluating such pointcuts is slower than evaluating normal pointcuts,
/// but can nevertheless be useful in some cases. Of course, your mileage
/// may vary as to what 'slower' actually means.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Simon White (.NET)</author>
[Serializable]
public class ControlFlowPointcut : IPointcut, ITypeFilter, IMethodMatcher, ISerializable
{
/// <summary>
/// Pointcut and method matcher for use in simple <b>cflow</b>-style
/// pointcuts.
/// </summary>
/// <remarks>
/// <p>
/// Evaluating such pointcuts is slower than evaluating normal pointcuts,
/// but can nevertheless be useful in some cases. Of course, your mileage
/// may vary as to what 'slower' actually means.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Simon White (.NET)</author>
[Serializable]
public class ControlFlowPointcut : IPointcut, ITypeFilter, IMethodMatcher, ISerializable
{
private Type _type;
private string _methodName;
private int _evaluationCount;
private Type _type;
private string _methodName;
private int _evaluationCount;
/// <summary>
/// Creates a new instance of the <see cref="ControlFlowPointcut"/>
/// class.
/// </summary>
/// <param name="type">
/// The class under which <b>all</b> control flows are to be matched.
/// </param>
public ControlFlowPointcut(Type type) : this(type, null)
{
}
/// <summary>
/// Creates a new instance of the <see cref="ControlFlowPointcut"/>
/// class.
/// </summary>
/// <param name="type">
/// The class under which <b>all</b> control flows are to be matched.
/// </param>
public ControlFlowPointcut(Type type) : this(type, null)
{
}
/// <summary>
/// Construct a new pointcut that matches all calls below the
/// given method in the given class.
/// </summary>
/// <remarks>
/// <p>
/// If the supplied <paramref name="methodName"/> is
/// <see langword="null"/>, <b>all</b> control flows below the given
/// class will be successfully matched.
/// </p>
/// </remarks>
/// <param name="type">
/// The class under which <b>all</b> control flows are to be matched.
/// </param>
/// <param name="methodName">
/// The method name under which <b>all</b> control flows are to be matched.
/// </param>
public ControlFlowPointcut(Type type, string methodName)
{
_type = type;
_methodName = methodName;
}
/// <summary>
/// Construct a new pointcut that matches all calls below the
/// given method in the given class.
/// </summary>
/// <remarks>
/// <p>
/// If the supplied <paramref name="methodName"/> is
/// <see langword="null"/>, <b>all</b> control flows below the given
/// class will be successfully matched.
/// </p>
/// </remarks>
/// <param name="type">
/// The class under which <b>all</b> control flows are to be matched.
/// </param>
/// <param name="methodName">
/// The method name under which <b>all</b> control flows are to be matched.
/// </param>
public ControlFlowPointcut(Type type, string methodName)
{
_type = type;
_methodName = methodName;
}
/// <inheritdoc />
private ControlFlowPointcut(SerializationInfo info, StreamingContext context)
{
var type = info.GetString("Type");
_type = type != null ? Type.GetType(type) : null;
_methodName = info.GetString("MethodName");
_evaluationCount = info.GetInt32("EvaluationCount");
}
/// <inheritdoc />
private ControlFlowPointcut(SerializationInfo info, StreamingContext context)
{
var type = info.GetString("Type");
_type = type != null ? Type.GetType(type) : null;
_methodName = info.GetString("MethodName");
_evaluationCount = info.GetInt32("EvaluationCount");
}
/// <inheritdoc />
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Type", _type?.AssemblyQualifiedName);
info.AddValue("MethodName", _methodName);
info.AddValue("EvaluationCount", _evaluationCount);
}
/// <inheritdoc />
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("Type", _type?.AssemblyQualifiedName);
info.AddValue("MethodName", _methodName);
info.AddValue("EvaluationCount", _evaluationCount);
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public ITypeFilter TypeFilter
{
get { return this; }
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public ITypeFilter TypeFilter
{
get { return this; }
}
/// <summary>
/// Gets the number of times this pointcut has been <i>evaluated</i>.
/// </summary>
/// <remarks>
/// <p>
/// Useful as a debugging aid.
/// </p>
/// <p>
/// Note that this value is distinct from the number of times that this
/// pointcut sucessfully matches a target method, in that a
/// <see cref="ControlFlowPointcut"/> may be evaluated many times but
/// never actually match even once.
/// </p>
/// </remarks>
/// <value>
/// The number of times this pointcut has been <i>evaluated</i>.
/// </value>
public int EvaluationCount
{
get { return _evaluationCount; }
}
/// <summary>
/// Gets the number of times this pointcut has been <i>evaluated</i>.
/// </summary>
/// <remarks>
/// <p>
/// Useful as a debugging aid.
/// </p>
/// <p>
/// Note that this value is distinct from the number of times that this
/// pointcut sucessfully matches a target method, in that a
/// <see cref="ControlFlowPointcut"/> may be evaluated many times but
/// never actually match even once.
/// </p>
/// </remarks>
/// <value>
/// The number of times this pointcut has been <i>evaluated</i>.
/// </value>
public int EvaluationCount
{
get { return _evaluationCount; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
public IMethodMatcher MethodMatcher
{
get { return this; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
public IMethodMatcher MethodMatcher
{
get { return this; }
}
/// <summary>
/// Is this a runtime pointcut?
/// </summary>
/// <remarks>
/// <p>
/// This implementation is a runtime pointcut, and so always returns
/// <see langword="true"/>.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this is a runtime pointcut.
/// </value>
/// <seealso cref="Spring.Aop.IMethodMatcher.IsRuntime"/>
public bool IsRuntime
{
get { return true; }
}
/// <summary>
/// Is this a runtime pointcut?
/// </summary>
/// <remarks>
/// <p>
/// This implementation is a runtime pointcut, and so always returns
/// <see langword="true"/>.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this is a runtime pointcut.
/// </value>
/// <seealso cref="Spring.Aop.IMethodMatcher.IsRuntime"/>
public bool IsRuntime
{
get { return true; }
}
/// <summary>
/// Should the pointcut apply to the supplied <see cref="System.Type"/>?
/// </summary>
/// <remarks>
/// <p>
/// Subclasses are encouraged to override this method for greater
/// filtering (and performance).
/// </p>
/// <p>
/// This, the default, implementation always matches (returns
/// <see langword="true"/>).
/// </p>
/// </remarks>
/// <param name="type">The candidate target class.</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>
/// Should the pointcut apply to the supplied <see cref="System.Type"/>?
/// </summary>
/// <remarks>
/// <p>
/// Subclasses are encouraged to override this method for greater
/// filtering (and performance).
/// </p>
/// <p>
/// This, the default, implementation always matches (returns
/// <see langword="true"/>).
/// </p>
/// </remarks>
/// <param name="type">The candidate target class.</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>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// Perform static checking. If this returns false, or if the isRuntime() method
/// returns false, no runtime check will be made.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses are encouraged to override this method if it is possible
/// to filter out some candidate classes.
/// </p>
/// <p>
/// This, the default, implementation always matches (returns
/// <see langword="true"/>). This means that the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will always be invoked.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target class (may be <see langword="null"/>, in which case the
/// candidate class must be taken to be the <paramref name="method"/>'s
/// declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
/// <seealso cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
public virtual bool Matches(MethodInfo method, Type targetType)
{
return true;
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// Perform static checking. If this returns false, or if the isRuntime() method
/// returns false, no runtime check will be made.
/// </summary>
/// <remarks>
/// <p>
/// Subclasses are encouraged to override this method if it is possible
/// to filter out some candidate classes.
/// </p>
/// <p>
/// This, the default, implementation always matches (returns
/// <see langword="true"/>). This means that the three argument
/// <see cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
/// method will always be invoked.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target class (may be <see langword="null"/>, in which case the
/// candidate class must be taken to be the <paramref name="method"/>'s
/// declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
/// <seealso cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type)"/>
public virtual bool Matches(MethodInfo method, Type targetType)
{
return true;
}
/// <summary>
/// Is there a runtime (dynamic) match for the supplied
/// <paramref name="method"/>?
/// </summary>
/// <remarks>
/// <p>
/// Subclasses are encouraged to override this method if it is possible
/// to filter out some candidate classes.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">The target class.</param>
/// <param name="args">The arguments to the method</param>
/// <returns>
/// <see langword="true"/> if there is a runtime match.</returns>
/// <seealso cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
public virtual bool Matches(MethodInfo method, Type targetType, object[] args)
{
++_evaluationCount;
IControlFlow cflow = ControlFlowFactory.CreateControlFlow();
return (_methodName != null)
? cflow.Under(_type, _methodName)
: cflow.Under(_type);
}
}
/// <summary>
/// Is there a runtime (dynamic) match for the supplied
/// <paramref name="method"/>?
/// </summary>
/// <remarks>
/// <p>
/// Subclasses are encouraged to override this method if it is possible
/// to filter out some candidate classes.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">The target class.</param>
/// <param name="args">The arguments to the method</param>
/// <returns>
/// <see langword="true"/> if there is a runtime match.</returns>
/// <seealso cref="Spring.Aop.IMethodMatcher.Matches(MethodInfo, Type, object[])"/>
public virtual bool Matches(MethodInfo method, Type targetType, object[] args)
{
++_evaluationCount;
IControlFlow cflow = ControlFlowFactory.CreateControlFlow();
return (_methodName != null)
? cflow.Under(_type, _methodName)
: cflow.Under(_type);
}
}

View File

@@ -25,255 +25,255 @@ using Spring.Collections;
#endregion
namespace Spring.Aop.Support
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
{
/// <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();
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>
/// <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="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>
/// 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");
}
/// <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; }
}
_introduction = introduction;
foreach (Type intf in interfaces)
{
if (intf != typeof(IAdvice))
{
AddInterface(intf);
}
}
}
/// <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>
/// 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>
/// 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>
/// 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>
/// 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>
/// 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>
/// 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>
/// 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>
/// 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>
/// 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>
/// 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.");
}
}
}
/// <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;
}
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>
/// 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.");
}
}
}
/// <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);
}
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 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 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 int GetHashCode()
{
unchecked
{
return ((_introduction != null ? _introduction.GetHashCode() : 0)*397) ^ (_interfaces != null ? _interfaces.GetHashCode() : 0);
}
}
}
/// <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);
}
}
}

View File

@@ -18,42 +18,40 @@
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Concrete ObjectFactory-based IPointcutAdvisor thta allows for any Advice to be
/// configured as reference to an Advice object in the ObjectFatory, as well as
/// the Pointcut to be configured through an object property.
/// </summary>
/// <remarks>
/// Specifying the name of an advice object instead of the advice object itself
/// (if running within a ObjectFactory/ApplicationContext) increases loose coupling
/// at initialization time, in order to not intialize the advice object until the pointcut
/// actually matches.
/// </remarks>
/// <author>Juerge Hoeller</author>
/// <author>Mark Pollack</author>
public class DefaultObjectFactoryPointcutAdvisor : AbstractObjectFactoryPointcutAdvisor
{
private IPointcut pointcut = TruePointcut.True;
/// <summary>
/// Concrete ObjectFactory-based IPointcutAdvisor thta allows for any Advice to be
/// configured as reference to an Advice object in the ObjectFatory, as well as
/// the Pointcut to be configured through an object property.
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
/// <remarks>
/// Specifying the name of an advice object instead of the advice object itself
/// (if running within a ObjectFactory/ApplicationContext) increases loose coupling
/// at initialization time, in order to not intialize the advice object until the pointcut
/// actually matches.
/// </remarks>
/// <author>Juerge Hoeller</author>
/// <author>Mark Pollack</author>
public class DefaultObjectFactoryPointcutAdvisor : AbstractObjectFactoryPointcutAdvisor
public override IPointcut Pointcut
{
private IPointcut pointcut = TruePointcut.True;
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public override IPointcut Pointcut
{
get { return pointcut; }
set { pointcut = (pointcut != null ? value : TruePointcut.True); }
}
/// <summary>
/// Describe this Advisor, showing pointcut and name of advice object.
/// </summary>
/// <returns>Type name , pointcut, and advice object name.</returns>
public override string ToString()
{
return GetType().Name + ": pointcut [" + Pointcut + "]; advice object = '" + AdviceObjectName + "'";
}
get { return pointcut; }
set { pointcut = (pointcut != null ? value : TruePointcut.True); }
}
}
/// <summary>
/// Describe this Advisor, showing pointcut and name of advice object.
/// </summary>
/// <returns>Type name , pointcut, and advice object name.</returns>
public override string ToString()
{
return GetType().Name + ": pointcut [" + Pointcut + "]; advice object = '" + AdviceObjectName + "'";
}
}

View File

@@ -24,101 +24,99 @@ using AopAlliance.Aop;
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Convenient pointcut-driven advisor implementation.
/// </summary>
/// <remarks>
/// <p>
/// This is the most commonly used <see cref="Spring.Aop.IAdvisor"/> implementation.
/// It can be used with any pointcut and advice type, except for introductions.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class DefaultPointcutAdvisor : AbstractGenericPointcutAdvisor
{
/// <summary>
/// Convenient pointcut-driven advisor implementation.
/// </summary>
/// <remarks>
/// <p>
/// This is the most commonly used <see cref="Spring.Aop.IAdvisor"/> implementation.
/// It can be used with any pointcut and advice type, except for introductions.
/// </p>
/// </remarks>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public class DefaultPointcutAdvisor : AbstractGenericPointcutAdvisor
{
private IPointcut pointcut = TruePointcut.True;
private IPointcut pointcut = TruePointcut.True;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultPointcutAdvisor"/> class.
/// </summary>
public DefaultPointcutAdvisor()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultPointcutAdvisor"/> class.
/// </summary>
public DefaultPointcutAdvisor()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// class for the supplied <paramref name="advice"/>,
/// </summary>
/// <param name="advice">
/// The advice to use.
/// </param>
public DefaultPointcutAdvisor(IAdvice advice)
: this(TruePointcut.True, advice)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// class for the supplied <paramref name="advice"/>,
/// </summary>
/// <param name="advice">
/// The advice to use.
/// </param>
public DefaultPointcutAdvisor(IAdvice advice)
: this(TruePointcut.True, advice)
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// class for the supplied <paramref name="advice"/> and
/// <paramref name="pointcut"/>.
/// </summary>
/// <param name="advice">
/// The advice to use.
/// </param>
/// <param name="pointcut">
/// The pointcut to use.
/// </param>
public DefaultPointcutAdvisor(IPointcut pointcut, IAdvice advice)
{
this.pointcut = pointcut;
Advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DefaultPointcutAdvisor"/>
/// class for the supplied <paramref name="advice"/> and
/// <paramref name="pointcut"/>.
/// </summary>
/// <param name="advice">
/// The advice to use.
/// </param>
/// <param name="pointcut">
/// The pointcut to use.
/// </param>
public DefaultPointcutAdvisor(IPointcut pointcut, IAdvice advice)
{
this.pointcut = pointcut;
Advice = advice;
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public override IPointcut Pointcut
{
get { return pointcut; }
set { pointcut = value;}
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
public override IPointcut Pointcut
{
get { return pointcut; }
set { pointcut = value; }
}
///<summary>
/// 2 <see cref="DefaultPointcutAdvisor"/>s are considered equal, if
/// a) their pointcuts are equal
/// b) their advices are equal
///</summary>
public override bool Equals(object obj)
{
return base.Equals(obj as DefaultPointcutAdvisor);
}
///<summary>
/// 2 <see cref="DefaultPointcutAdvisor"/>s are considered equal, if
/// a) their pointcuts are equal
/// b) their advices are equal
///</summary>
public override bool Equals(object obj)
{
return base.Equals(obj as DefaultPointcutAdvisor);
}
/// <summary>
/// Calculates a unique hashcode based on advice + pointcut
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Calculates a unique hashcode based on advice + pointcut
/// </summary>
public override int GetHashCode()
{
return base.GetHashCode();
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents the current
/// <see cref="System.Object"/>.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> representation of this advisor.
/// </returns>
public override string ToString()
{
return GetType().Name + ": pointcut=[" + pointcut + "] advice=[" + Advice + "]";
}
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents the current
/// <see cref="System.Object"/>.
/// </summary>
/// <returns>
/// A <see cref="System.String"/> representation of this advisor.
/// </returns>
public override string ToString()
{
return GetType().Name + ": pointcut=[" + pointcut + "] advice=[" + Advice + "]";
}
}

View File

@@ -24,90 +24,89 @@ using System.Reflection;
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Convenient abstract superclass for dynamic method matchers that do
/// care about arguments at runtime.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public abstract class DynamicMethodMatcher : IMethodMatcher
{
/// <summary>
/// Convenient abstract superclass for dynamic method matchers that do
/// care about arguments at runtime.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public abstract class DynamicMethodMatcher : IMethodMatcher
{
#region Constructor (s) / Destructor
#region Constructor (s) / Destructor
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DynamicMethodMatcher"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes no
/// public constructors.
/// </p>
/// </remarks>
protected DynamicMethodMatcher()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DynamicMethodMatcher"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an <see langword="abstract"/> class, and as such exposes no
/// public constructors.
/// </p>
/// </remarks>
protected DynamicMethodMatcher()
{
}
#endregion
#endregion
/// <summary>
/// Is this <see cref="Spring.Aop.IMethodMatcher"/> dynamic?
/// </summary>
/// <value>
/// Always returns <see langword="true"/>, to specify that this is a
/// dynamic matcher.
/// </value>
public virtual bool IsRuntime
{
get { return true; }
}
/// <summary>
/// Is this <see cref="Spring.Aop.IMethodMatcher"/> dynamic?
/// </summary>
/// <value>
/// Always returns <see langword="true"/>, to specify that this is a
/// dynamic matcher.
/// </value>
public virtual bool IsRuntime
{
get { return true; }
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <remarks>
/// <p>
/// Derived classes can override this method to add preconditions for
/// dynamic matching.
/// </p>
/// <p>
/// This implementation always returns <see langword="true"/>.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public virtual bool Matches(MethodInfo method, Type targetType)
{
return true;
}
/// <summary>
/// Does the supplied <paramref name="method"/> satisfy this matcher?
/// </summary>
/// <remarks>
/// <p>
/// Derived classes can override this method to add preconditions for
/// dynamic matching.
/// </p>
/// <p>
/// This implementation always returns <see langword="true"/>.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/> (may be <see langword="null"/>,
/// in which case the candidate <see cref="System.Type"/> must be taken
/// to be the <paramref name="method"/>'s declaring class).
/// </param>
/// <returns>
/// <see langword="true"/> if this this method matches statically.
/// </returns>
public virtual bool Matches(MethodInfo method, Type targetType)
{
return true;
}
/// <summary>
/// Is there a runtime (dynamic) match for the supplied
/// <paramref name="method"/>?
/// </summary>
/// <remarks>
/// <p>
/// Must be overriden by derived classes to provide criteria for dynamic matching.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/>.
/// </param>
/// <param name="args">The arguments to the method</param>
/// <returns>
/// <see langword="true"/> if there is a runtime match.</returns>
public abstract bool Matches(MethodInfo method, Type targetType, object[] args);
}
/// <summary>
/// Is there a runtime (dynamic) match for the supplied
/// <paramref name="method"/>?
/// </summary>
/// <remarks>
/// <p>
/// Must be overriden by derived classes to provide criteria for dynamic matching.
/// </p>
/// </remarks>
/// <param name="method">The candidate method.</param>
/// <param name="targetType">
/// The target <see cref="System.Type"/>.
/// </param>
/// <param name="args">The arguments to the method</param>
/// <returns>
/// <see langword="true"/> if there is a runtime match.</returns>
public abstract bool Matches(MethodInfo method, Type targetType, object[] args);
}

View File

@@ -25,150 +25,149 @@ using Spring.Core;
#endregion
namespace Spring.Aop.Support
namespace Spring.Aop.Support;
/// <summary>
/// Convenient superclass for <see cref="Spring.Aop.IAdvisor"/>s
/// that are also dynamic pointcuts.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public abstract class DynamicMethodMatcherPointcutAdvisor
: DynamicMethodMatcher, IPointcutAdvisor, IPointcut, IOrdered
{
/// <summary>
/// Convenient superclass for <see cref="Spring.Aop.IAdvisor"/>s
/// that are also dynamic pointcuts.
/// </summary>
/// <author>Rod Johnson</author>
/// <author>Aleksandar Seovic (.NET)</author>
[Serializable]
public abstract class DynamicMethodMatcherPointcutAdvisor
: DynamicMethodMatcher, IPointcutAdvisor, IPointcut, IOrdered
{
private int _order = Int32.MaxValue;
private IAdvice _advice;
private int _order = Int32.MaxValue;
private IAdvice _advice;
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DynamicMethodMatcherPointcutAdvisor"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
protected DynamicMethodMatcherPointcutAdvisor()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DynamicMethodMatcherPointcutAdvisor"/>
/// class.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
protected DynamicMethodMatcherPointcutAdvisor()
{
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DynamicMethodMatcherPointcutAdvisor"/>
/// class for the supplied <paramref name="advice"/>.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
/// <param name="advice">
/// The advice portion of this advisor.
/// </param>
protected DynamicMethodMatcherPointcutAdvisor(IAdvice advice)
{
this._advice = advice;
}
/// <summary>
/// Creates a new instance of the
/// <see cref="Spring.Aop.Support.DynamicMethodMatcherPointcutAdvisor"/>
/// class for the supplied <paramref name="advice"/>.
/// </summary>
/// <remarks>
/// <p>
/// This is an abstract class, and as such has no publicly
/// visible constructors.
/// </p>
/// </remarks>
/// <param name="advice">
/// The advice portion of this advisor.
/// </param>
protected DynamicMethodMatcherPointcutAdvisor(IAdvice advice)
{
this._advice = advice;
}
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// Not supported for dynamic advisors.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
/// <exception cref="System.NotSupportedException">Always.</exception>
/// <see cref="Spring.Aop.IAdvisor.IsPerInstance"/>
public virtual bool IsPerInstance
{
get
{
throw new NotSupportedException(
"The 'IsPerInstance' property of the IAdvisor interface " +
"is not yet supported in Spring.NET.");
}
}
/// <summary>
/// Is this advice associated with a particular instance?
/// </summary>
/// <remarks>
/// <p>
/// Not supported for dynamic advisors.
/// </p>
/// </remarks>
/// <value>
/// <see langword="true"/> if this advice is associated with a
/// particular instance.
/// </value>
/// <exception cref="System.NotSupportedException">Always.</exception>
/// <see cref="Spring.Aop.IAdvisor.IsPerInstance"/>
public virtual bool IsPerInstance
{
get
{
throw new NotSupportedException(
"The 'IsPerInstance' property of the IAdvisor interface " +
"is not yet supported in Spring.NET.");
}
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <remarks>
/// <p>
/// This implementation always returns a filter that evaluates to <see langword="true"/>
/// for any <see cref="System.Type"/>.
/// </p>
/// </remarks>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public virtual ITypeFilter TypeFilter
{
get { return TrueTypeFilter.True; }
}
/// <summary>
/// The <see cref="Spring.Aop.ITypeFilter"/> for this pointcut.
/// </summary>
/// <remarks>
/// <p>
/// This implementation always returns a filter that evaluates to <see langword="true"/>
/// for any <see cref="System.Type"/>.
/// </p>
/// </remarks>
/// <value>
/// The current <see cref="Spring.Aop.ITypeFilter"/>.
/// </value>
public virtual ITypeFilter TypeFilter
{
get { return TrueTypeFilter.True; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <remarks>
/// <p>
/// This implementation always returns itself (this object).
/// </p>
/// </remarks>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
public virtual IMethodMatcher MethodMatcher
{
get { return this; }
}
/// <summary>
/// The <see cref="Spring.Aop.IMethodMatcher"/> for this pointcut.
/// </summary>
/// <remarks>
/// <p>
/// This implementation always returns itself (this object).
/// </p>
/// </remarks>
/// <value>
/// The current <see cref="Spring.Aop.IMethodMatcher"/>.
/// </value>
public virtual IMethodMatcher MethodMatcher
{
get { return this; }
}
/// <summary>
/// Returns this <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </summary>
/// <returns>
/// This <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </returns>
public virtual int Order
{
get { return this._order; }
set { this._order = value; }
}
/// <summary>
/// Returns this <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </summary>
/// <returns>
/// This <see cref="Spring.Aop.IAdvisor"/>s order in the
/// interception chain.
/// </returns>
public virtual int Order
{
get { return this._order; }
set { this._order = value; }
}
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
/// <see cref="Spring.Aop.IAdvisor.Advice"/>
public virtual IAdvice Advice
{
get { return this._advice; }
set { this._advice = value; }
}
/// <summary>
/// Return the advice part of this aspect.
/// </summary>
/// <returns>
/// The advice that should apply if the pointcut matches.
/// </returns>
/// <see cref="Spring.Aop.IAdvisor.Advice"/>
public virtual IAdvice Advice
{
get { return this._advice; }
set { this._advice = value; }
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
/// <remarks>
/// <p>
/// This implementation always returns itself (this object).
/// </p>
/// </remarks>
public IPointcut Pointcut
{
get { return this; }
}
}
/// <summary>
/// The <see cref="Spring.Aop.IPointcut"/> that drives this advisor.
/// </summary>
/// <remarks>
/// <p>
/// This implementation always returns itself (this object).
/// </p>
/// </remarks>
public IPointcut Pointcut
{
get { return this; }
}
}

Some files were not shown because too many files have changed in this diff Show More