User: jonathon.rossi
Date: 2009/11/29 01:05 AM
Added:
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
LoggingTestCase.cs
Modified:
/DynamicProxy/trunk/src/
Changes.txt
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
BasePEVerifyTestCase.cs, Castle.DynamicProxy.Tests-vs2008.csproj
/DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Classes/
SimpleClass.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/
DefaultProxyBuilder.cs, IProxyBuilder.cs, ModuleScope.cs,
ProxyGenerationOptions.cs, ProxyGenerator.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
ClassMembersCollector.cs, ClassProxyTargetContributor.cs, MembersCollector.cs
/DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
AttributeDisassembler.cs, BaseProxyGenerator.cs, CacheKey.cs,
ClassProxyGenerator.cs, InterfaceProxyWithTargetGenerator.cs,
InvocationTypeGenerator.cs
Log:
Fixed DYNPROXY-ISSUE-120: Add logging to DynamicProxy.
Introduced basic logging for cache hit/miss, methods that cannot be
intercepted, and overriding Equals/GetHashCode.
Directory Changes:
Directory: /DynamicProxy/trunk/src/
===================================
Property changes on: DynamicProxy/trunk/src
___________________________________________________________________
Directory: /svn:ignore/
=======================
+ *.suo
*.user
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassMembersCollector.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassMembersCollector.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -23,7 +23,6 @@
public ClassMembersCollector(Type targetType, ITypeContributor
targetContributor)
: base(targetType, targetContributor, true, new
InterfaceMapping())
{
-
}
protected override MethodToGenerate
GetMethodToGenerate(MethodInfo method, IProxyGenerationHook hook, bool
isStandalone)
@@ -48,6 +47,5 @@
return new MethodToGenerate(method, isStandalone,
target, method, accepted);
}
-
}
}
File Changes:
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/
=======================================================
File [modified]: DefaultProxyBuilder.cs
Delta lines: +1 -3
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/AttributeDisassembler.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/AttributeDisassembler.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -28,7 +28,6 @@
}
catch (Exception ex)
{
-
// there is no real way to log a warning here...
return HandleError(type,ex);
}
@@ -43,7 +42,7 @@
protected virtual CustomAttributeBuilder HandleError(Type
attributeType, Exception exception)
{
// ouch...
- string message = "Dynamic Proxy was unable to
disassemble attribute " + attributeType.Name +
+ string message = "DynamicProxy was unable to
disassemble attribute " + attributeType.Name +
" using default AttributeDisassembler.
" +
"To handle the disassembly process
properly implement the IAttributeDisassembler interface, " +
"and register your disassembler to
handle this type of attributes using " +
@@ -152,7 +151,6 @@
}
}
-
PropertyInfo bestMatch = null;
//now we try to find it by type
File [modified]: IProxyBuilder.cs
Delta lines: +0 -2
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/ModuleScope.cs 2009-11-29
00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/ModuleScope.cs 2009-11-29
08:05:35 UTC (rev 6370)
@@ -25,8 +25,6 @@
#if SILVERLIGHT
using Castle.DynamicProxy.SilverlightExtensions;
-#else
-
#endif
File [modified]: ModuleScope.cs
Delta lines: +0 -3
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/ProxyGenerationOptions.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/ProxyGenerationOptions.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -39,7 +39,6 @@
#endif
private MixinData mixinData; // this is calculated dynamically
on proxy type creation
-
/// <summary>
/// Initializes a new instance of the <see
cref="ProxyGenerationOptions"/> class.
/// </summary>
@@ -58,7 +57,6 @@
{
}
-
#if SILVERLIGHT
#warning What to do?
#else
@@ -154,7 +152,6 @@
get { return mixins == null ? false : mixins.Count !=
0; }
}
-
public override bool Equals(object obj)
{
File [modified]: ProxyGenerationOptions.cs
Delta lines: +17 -1
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/ProxyGenerator.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/ProxyGenerator.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-
namespace Castle.DynamicProxy
{
using System;
@@ -24,6 +23,7 @@
#endif
using System.Text;
using Castle.Core.Interceptor;
+ using Castle.Core.Logging;
/// <summary>
/// Provides proxy objects for classes and interfaces.
@@ -31,6 +31,7 @@
[CLSCompliant(true)]
public class ProxyGenerator
{
+ private ILogger logger = NullLogger.Instance;
private readonly IProxyBuilder proxyBuilder;
#region Constructors
@@ -42,6 +43,8 @@
public ProxyGenerator(IProxyBuilder builder)
{
proxyBuilder = builder;
+
+ Logger = new TraceLogger("Castle.DynamicProxy",
LoggerLevel.Warn);
}
/// <summary>
@@ -56,6 +59,19 @@
#region Properties
/// <summary>
+ /// Gets or sets the <see cref="ILogger"/> that this <see
cref="ProxyGenerator"/> log to.
+ /// </summary>
+ public ILogger Logger
+ {
+ get { return logger; }
+ set
+ {
+ logger = value;
+ proxyBuilder.Logger = value;
+ }
+ }
+
+ /// <summary>
/// Gets the proxy builder instance used to generate proxy
types.
/// </summary>
File [modified]: ProxyGenerator.cs
Delta lines: +24 -32
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/BasePEVerifyTestCase.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/BasePEVerifyTestCase.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -21,31 +21,30 @@
using NUnit.Framework;
#if !MONO && !SILVERLIGHT // mono doesn't have PEVerify
- [SetUpFixture]
- public class FindPeVerify
- {
- [SetUp]
- public void FindPeVerifySetUp()
- {
- var peVerifyProbingPaths =
Settings.Default.PeVerifyProbingPaths;
- foreach (var path in peVerifyProbingPaths)
- {
- var file = Path.Combine(path, "peverify.exe");
- if (File.Exists(file))
- {
- PeVerifyPath = file;
- return;
- }
- }
- throw new FileNotFoundException(
+ [SetUpFixture]
+ public class FindPeVerify
+ {
+ [SetUp]
+ public void FindPeVerifySetUp()
+ {
+ var peVerifyProbingPaths =
Settings.Default.PeVerifyProbingPaths;
+ foreach (var path in peVerifyProbingPaths)
+ {
+ var file = Path.Combine(path, "peverify.exe");
+ if (File.Exists(file))
+ {
+ PeVerifyPath = file;
+ return;
+ }
+ }
+ throw new FileNotFoundException(
"Please check the PeVerifyProbingPaths
configuration setting and set it to the folder where peverify.exe is located");
- }
+ }
- public static string PeVerifyPath { get; set; }
- }
-#endif
+ public static string PeVerifyPath { get; set; }
+ }
+#endif
-
public abstract class BasePEVerifyTestCase
{
protected ProxyGenerator generator;
@@ -77,7 +76,6 @@
}
#if !MONO && !SILVERLIGHT // mono doesn't have PEVerify
-
[TearDown]
public virtual void TearDown()
{
@@ -90,11 +88,9 @@
}
}
-
public void RunPEVerifyOnGeneratedAssembly(string assemblyPath)
{
Process process = new Process();
-
process.StartInfo.FileName = FindPeVerify.PeVerifyPath;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
@@ -115,17 +111,13 @@
Assert.Fail("PeVerify reported error(s): " +
Environment.NewLine + processOutput, result);
}
}
-
#else
-
-
-#if !SILVERLIGHT
+ #if !SILVERLIGHT
[TearDown]
-#endif
- public virtual void TearDown ()
+ #endif
+ public virtual void TearDown()
{
}
-
#endif
}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/
=============================================================
File [modified]: BasePEVerifyTestCase.cs
Delta lines: +1 -0
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Castle.DynamicProxy.Tests-vs2008.csproj
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Castle.DynamicProxy.Tests-vs2008.csproj
2009-11-29 08:05:35 UTC (rev 6370)
@@ -186,6 +186,7 @@
<Compile Include="Interfaces\Two.cs" />
<Compile Include="InvocationMethodInvocationTargetTestCase.cs" />
<Compile Include="InvocationTypesCachingTestCase.cs" />
+ <Compile Include="LoggingTestCase.cs" />
<Compile Include="MethodEquivalenceTestCase.cs" />
<Compile Include="MixinDataTestCase.cs" />
File [modified]: Castle.DynamicProxy.Tests-vs2008.csproj
Delta lines: +0 -2
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Classes/SimpleClass.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Classes/SimpleClass.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -14,8 +14,6 @@
namespace Castle.DynamicProxy.Tests.Classes
{
- using System;
-
public class SimpleClass
{
File [added]: LoggingTestCase.cs
Delta lines: +2 -0
===================================================================
--- DynamicProxy/trunk/src/Changes.txt 2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Changes.txt 2009-11-29 08:05:35 UTC (rev 6370)
@@ -1,5 +1,7 @@
Unreleased Changes
==================
+- Fixed DYNPROXY-ISSUE-120: Add logging to DynamicProxy.
+ Introduced basic logging for cache hit/miss, methods that cannot be
intercepted, and overriding Equals/GetHashCode.
- Fixed DYNPROXY-ISSUE-94 - CreateProxyWithTarget fails if you use
ProxyGenerationHook
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/Classes/
=====================================================================
File [modified]: SimpleClass.cs
Delta lines: +416 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/LoggingTestCase.cs
(rev 0)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy.Tests/LoggingTestCase.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -0,0 +1,416 @@
+// Copyright 2004-2009 Castle Project - http://www.castleproject.org/
+//
+// 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.
+
+namespace Castle.DynamicProxy.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Reflection;
+ using Castle.Core.Logging;
+ using NUnit.Framework;
+
+ [TestFixture]
+ public class LoggingTestCase
+ {
+ [Test]
+ public void CacheMiss()
+ {
+ // Arrange
+ CollectingLogger logger = new CollectingLogger();
+ ProxyGenerator generator = new ProxyGenerator { Logger
= logger };
+
+ // Act
+ generator.CreateClassProxy<EmptyClass>();
+
+ // Assert
+ Assert.That(logger.RecordedMessage(LoggerLevel.Debug,
"No cached proxy type was found for target type " +
+
"Castle.DynamicProxy.Tests.LoggingTestCase+EmptyClass."));
+ }
+
+ [Test]
+ public void CacheHitClassProxy()
+ {
+ // Arrange
+ CollectingLogger logger = new CollectingLogger();
+ ProxyGenerator generator = new ProxyGenerator { Logger
= logger };
+
+ // Act
+ generator.CreateClassProxy<EmptyClass>();
+ generator.CreateClassProxy<EmptyClass>();
+
+ // Assert
+ Assert.That(logger.RecordedMessage(LoggerLevel.Debug,
"Found cached proxy type Castle.Proxies.EmptyClassProxy " +
+ "for target type
Castle.DynamicProxy.Tests.LoggingTestCase+EmptyClass."));
+ }
+
+ [Test]
+ public void CacheHitInterfaceProxy()
+ {
+ // Arrange
+ CollectingLogger logger = new CollectingLogger();
+ ProxyGenerator generator = new ProxyGenerator { Logger
= logger };
+
+ // Act
+
generator.CreateInterfaceProxyWithoutTarget<IEmptyInterface>();
+
generator.CreateInterfaceProxyWithoutTarget<IEmptyInterface>();
+
+ // Assert
+ Assert.That(logger.RecordedMessage(LoggerLevel.Debug,
"Found cached proxy type Castle.Proxies.IEmptyInterfaceProxy " +
+ "for target type
Castle.DynamicProxy.Tests.LoggingTestCase+IEmptyInterface."));
+ }
+
+ [Test]
+ public void
ProxyGenerationOptionsEqualsAndGetHashCodeNotOverriden()
+ {
+ // Arrange
+ CollectingLogger logger = new CollectingLogger();
+ ProxyGenerator generator = new ProxyGenerator { Logger
= logger };
+
+ // Act
+ ProxyGenerationOptions options = new
ProxyGenerationOptions {
+ Hook = new EmptyHook()
+ };
+ generator.CreateClassProxy(typeof(EmptyClass), options);
+
+ // Assert
+ Assert.That(logger.RecordedMessage(LoggerLevel.Warn,
"The IProxyGenerationHook type " +
+
"Castle.DynamicProxy.Tests.LoggingTestCase+EmptyHook does not override both
Equals and GetHashCode. " +
+ "If these are not correctly overridden caching
will fail to work causing performance problems."));
+ }
+
+ [Test]
+ public void ExcludedNonVirtualMethods()
+ {
+ // Arrange
+ CollectingLogger logger = new CollectingLogger();
+ ProxyGenerator generator = new ProxyGenerator { Logger
= logger };
+
+ // Act
+ generator.CreateClassProxy<NonVirtualMethodClass>();
+
+ // Assert
+ Assert.That(logger.RecordedMessage(LoggerLevel.Debug,
"Excluded non-virtual method ClassMethod on " +
+
"Castle.DynamicProxy.Tests.LoggingTestCase+NonVirtualMethodClass because it
cannot be intercepted."));
+ Assert.That(logger.RecordedMessage(LoggerLevel.Debug,
"Excluded sealed method InterfaceMethod on " +
+
"Castle.DynamicProxy.Tests.LoggingTestCase+NonVirtualMethodClass because it
cannot be intercepted."));
+ }
+
+ [Test]
+ public void FoundExplicitlyImplementedInterfaceMethods()
+ {
+ // Arrange
+ CollectingLogger logger = new CollectingLogger();
+ ProxyGenerator generator = new ProxyGenerator { Logger
= logger };
+
+ // Act
+
generator.CreateClassProxy<ClassWithInterfaceMethodExplicitlyImplemented>();
+
+ // Assert
+ Assert.That(logger.RecordedMessage(LoggerLevel.Debug,
"Excluded explicitly implemented interface method " +
+
"Castle.DynamicProxy.Tests.LoggingTestCase.ISingleMethodInterface.InterfaceMethod
on type " +
+
"Castle.DynamicProxy.Tests.LoggingTestCase+ClassWithInterfaceMethodExplicitlyImplemented
" +
+ "because it cannot be intercepted."));
+ }
+
+ #region Test Types
+
+ public class EmptyClass
+ {
+ }
+
+ public interface IEmptyInterface
+ {
+ }
+
+ public interface ISingleMethodInterface
+ {
+ void InterfaceMethod();
+ }
+
+ public class NonVirtualMethodClass : ISingleMethodInterface
+ {
+ public void ClassMethod()
+ {
+ }
+
+ public void InterfaceMethod()
+ {
+ }
+ }
+
+ public class ClassWithInterfaceMethodExplicitlyImplemented :
ISingleMethodInterface
+ {
+ void ISingleMethodInterface.InterfaceMethod()
+ {
+ }
+ }
+
+ public class EmptyHook : IProxyGenerationHook
+ {
+ public bool ShouldInterceptMethod(Type type, MethodInfo
methodInfo)
+ {
+ return true;
+ }
+
+ public void NonVirtualMemberNotification(Type type,
MemberInfo memberInfo)
+ {
+ }
+
+ public void MethodsInspected()
+ {
+ }
+ }
+
+ #endregion
+ }
+
+ #region CollectingLogger
+
+ public class CollectingLogger : ILogger
+ {
+ private readonly List<string> messages = new List<string>();
+
+ public bool RecordedMessage(LoggerLevel level, string message)
+ {
+ return messages.Contains(level.ToString().ToUpper() +
": " + message);
+ }
+
+ public void Debug(string message)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string message, Exception exception)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Debug(string format, params object[] args)
+ {
+ messages.Add("DEBUG: " + string.Format(format, args));
+ }
+
+ public void DebugFormat(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DebugFormat(Exception exception, string format,
params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DebugFormat(IFormatProvider formatProvider, string
format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DebugFormat(Exception exception, IFormatProvider
formatProvider, string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Info(string message)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Info(string message, Exception exception)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Info(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InfoFormat(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InfoFormat(Exception exception, string format,
params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InfoFormat(IFormatProvider formatProvider, string
format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InfoFormat(Exception exception, IFormatProvider
formatProvider, string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warn(string message)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warn(string message, Exception exception)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Warn(string format, params object[] args)
+ {
+ messages.Add("WARN: " + string.Format(format, args));
+ }
+
+ public void WarnFormat(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void WarnFormat(Exception exception, string format,
params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void WarnFormat(IFormatProvider formatProvider, string
format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void WarnFormat(Exception exception, IFormatProvider
formatProvider, string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string message)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string message, Exception exception)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Error(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ErrorFormat(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ErrorFormat(Exception exception, string format,
params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ErrorFormat(IFormatProvider formatProvider, string
format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void ErrorFormat(Exception exception, IFormatProvider
formatProvider, string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string message)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string message, Exception exception)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Fatal(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalFormat(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalFormat(Exception exception, string format,
params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalFormat(IFormatProvider formatProvider, string
format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalFormat(Exception exception, IFormatProvider
formatProvider, string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalError(string message)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalError(string message, Exception exception)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void FatalError(string format, params object[] args)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ILogger CreateChildLogger(string loggerName)
+ {
+ throw new NotImplementedException();
+ }
+
+ public bool IsDebugEnabled
+ {
+ get { return true; }
+ }
+
+ public bool IsInfoEnabled
+ {
+ get { return true; }
+ }
+
+ public bool IsWarnEnabled
+ {
+ get { return true; }
+ }
+
+ public bool IsErrorEnabled
+ {
+ get { return true; }
+ }
+
+ public bool IsFatalEnabled
+ {
+ get { return true; }
+ }
+
+ public bool IsFatalErrorEnabled
+ {
+ get { return true; }
+ }
+ }
+
+ #endregion
+}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/
====================================================================
File [modified]: ClassMembersCollector.cs
Delta lines: +11 -7
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassProxyTargetContributor.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/ClassProxyTargetContributor.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -19,13 +19,14 @@
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
+ using Castle.Core.Logging;
+ using Castle.DynamicProxy.Generators;
+ using Castle.DynamicProxy.Generators.Emitters;
+ using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
- using Generators;
- using Generators.Emitters;
- using Generators.Emitters.SimpleAST;
-
public class ClassProxyTargetContributor : CompositeTypeContributor
{
+ private ILogger logger = NullLogger.Instance;
private readonly Type targetType;
private readonly IList<MethodInfo> methodsToSkip;
@@ -35,13 +36,17 @@
this.methodsToSkip = methodsToSkip;
}
+ public ILogger Logger
+ {
+ get { return logger; }
+ set { logger = value; }
+ }
-
public override void
CollectElementsToProxy(IProxyGenerationHook hook)
{
Debug.Assert(hook != null, "hook != null");
- var targetItem = new ClassMembersCollector(targetType,
this);
+ var targetItem = new ClassMembersCollector(targetType,
this) { Logger = logger };
targetItem.CollectMembersToProxy(hook);
targets.Add(targetItem);
@@ -54,7 +59,6 @@
item.CollectMembersToProxy(hook);
targets.Add(item);
}
-
}
File [modified]: ClassProxyTargetContributor.cs
Delta lines: +24 -9
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MembersCollector.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Contributors/MembersCollector.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -17,20 +17,22 @@
using System;
using System.Collections.Generic;
using System.Reflection;
- using Generators;
+ using Castle.Core.Logging;
+ using Castle.DynamicProxy.Generators;
public abstract class MembersCollector
{
private const BindingFlags Flags = BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance;
+
protected readonly bool onlyProxyVirtual;
protected readonly InterfaceMapping map;
+ private ILogger logger = NullLogger.Instance;
private IList<MethodInfo> checkedMethods = new
List<MethodInfo>();
private readonly IDictionary<PropertyInfo, PropertyToGenerate>
properties = new Dictionary<PropertyInfo, PropertyToGenerate>();
private readonly IDictionary<EventInfo, EventToGenerate> events
= new Dictionary<EventInfo, EventToGenerate>();
private readonly IDictionary<MethodInfo, MethodToGenerate>
methodsToProxy = new Dictionary<MethodInfo, MethodToGenerate>();
private readonly Type type;
-
protected readonly ITypeContributor contributor;
protected MembersCollector(Type type, ITypeContributor
contributor, bool onlyProxyVirtual, InterfaceMapping map)
@@ -41,6 +43,12 @@
this.map = map;
}
+ public ILogger Logger
+ {
+ get { return logger; }
+ set { logger = value; }
+ }
+
public IEnumerable<MethodToGenerate> Methods
{
get { return methodsToProxy.Values; }
@@ -181,8 +189,8 @@
protected virtual MethodInfo GetMethodOnTarget(MethodInfo
method)
{
- var index = Array.IndexOf(map.InterfaceMethods, method);
- if(index==-1)
+ int index = Array.IndexOf(map.InterfaceMethods, method);
+ if (index == -1)
{
return null;
}
@@ -190,7 +198,6 @@
return map.TargetMethods[index];
}
-
/// <summary>
/// Checks if the method is public or protected.
/// </summary>
@@ -201,7 +208,6 @@
#if SILVERLIGHT
return method.IsPublic || method.IsFamily ||
method.IsFamilyOrAssembly;
#else
-
if (method.IsPublic
|| method.IsFamily
|| method.IsFamilyAndAssembly
@@ -215,6 +221,13 @@
return true;
}
+ // Explicitly implemented interface method on class
+ if (method.IsPrivate && method.IsFinal)
+ {
+ Logger.Debug("Excluded explicitly implemented
interface method {0} on type {1} because it cannot be intercepted.",
+ method.Name,
method.DeclaringType.FullName);
+ }
+
return false;
#endif
}
@@ -231,7 +244,10 @@
{
// we can never intercept a sealed (final) method
if (method.IsFinal)
+ {
+ Logger.Debug("Excluded sealed method {0} on {1}
because it cannot be intercepted.", method.Name, method.DeclaringType.FullName);
return false;
+ }
bool isInternalsAndNotVisibleToDynamicProxy =
InternalsHelper.IsInternal(method);
if (isInternalsAndNotVisibleToDynamicProxy)
@@ -248,9 +264,10 @@
#if SILVERLIGHT
if (method.DeclaringType != typeof(object))
#else
- if (method.DeclaringType != typeof (object) &&
method.DeclaringType != typeof (MarshalByRefObject))
+ if (method.DeclaringType != typeof(object) &&
method.DeclaringType != typeof(MarshalByRefObject))
#endif
{
+ Logger.Debug("Excluded non-virtual
method {0} on {1} because it cannot be intercepted.", method.Name,
method.DeclaringType.FullName);
hook.NonVirtualMemberNotification(type,
method);
}
@@ -274,7 +291,5 @@
#endif
return hook.ShouldInterceptMethod(type, method);
}
-
-
}
}
File [modified]: MembersCollector.cs
Delta lines: +13 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/DefaultProxyBuilder.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/DefaultProxyBuilder.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -16,6 +16,7 @@
{
using System;
using System.Collections.Generic;
+ using Castle.Core.Logging;
using Castle.DynamicProxy.Generators;
#if SILVERLIGHT
using Castle.DynamicProxy.SilverlightExtensions;
@@ -26,6 +27,7 @@
/// </summary>
public class DefaultProxyBuilder : IProxyBuilder
{
+ private ILogger logger = NullLogger.Instance;
private readonly ModuleScope scope;
/// <summary>
@@ -44,6 +46,13 @@
{
this.scope = scope;
}
+
+ public ILogger Logger
+ {
+ get { return logger; }
+ set { logger = value; }
+ }
+
public ModuleScope ModuleScope
{
get { return scope; }
@@ -67,6 +76,7 @@
AssertValidTypes(additionalInterfacesToProxy);
var generator = new ClassProxyGenerator(scope,
classToProxy);
+ generator.Logger = logger;
return
generator.GenerateCode(additionalInterfacesToProxy, options);
}
@@ -76,6 +86,7 @@
AssertValidTypes(additionalInterfacesToProxy);
var generator = new
InterfaceProxyWithoutTargetGenerator(scope, interfaceToProxy);
+ generator.Logger = logger;
return generator.GenerateCode(typeof(object),
additionalInterfacesToProxy, options);
}
@@ -86,6 +97,7 @@
AssertValidTypes(additionalInterfacesToProxy);
var generator = new
InterfaceProxyWithTargetGenerator(scope, interfaceToProxy);
+ generator.Logger = logger;
return generator.GenerateCode(targetType,
additionalInterfacesToProxy, options);
}
@@ -96,6 +108,7 @@
AssertValidTypes(additionalInterfacesToProxy);
var generator = new
InterfaceProxyWithTargetInterfaceGenerator(scope, interfaceToProxy);
+ generator.Logger = logger;
return generator.GenerateCode(interfaceToProxy,
additionalInterfacesToProxy, options);
}
Directory: /DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/
==================================================================
File [modified]: AttributeDisassembler.cs
Delta lines: +41 -1
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/BaseProxyGenerator.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/BaseProxyGenerator.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -21,6 +21,7 @@
using System.Runtime.Serialization;
using System.Xml.Serialization;
using Castle.Core.Interceptor;
+ using Castle.Core.Logging;
using Castle.DynamicProxy.Generators.Emitters;
using Castle.DynamicProxy.Generators.Emitters.CodeBuilders;
using Castle.DynamicProxy.Generators.Emitters.SimpleAST;
@@ -35,6 +36,7 @@
/// </summary>
public abstract class BaseProxyGenerator
{
+ private ILogger logger = NullLogger.Instance;
private readonly ModuleScope scope;
private ProxyGenerationOptions proxyGenerationOptions;
@@ -46,6 +48,12 @@
this.targetType = targetType;
}
+ public ILogger Logger
+ {
+ get { return logger; }
+ set { logger = value; }
+ }
+
protected ProxyGenerationOptions ProxyGenerationOptions
{
get
@@ -254,12 +262,44 @@
#endregion
+ protected void
EnsureOptionsOverrideEqualsAndGetHashCode(ProxyGenerationOptions options)
+ {
+ if (Logger.IsWarnEnabled)
+ {
+ // Check the proxy generation hook
+ if
(!OverridesEqualsAndGetHashCode(options.Hook.GetType()))
+ {
+ Logger.Warn("The IProxyGenerationHook
type {0} does not override both Equals and GetHashCode. " +
+ "If these are not correctly
overridden caching will fail to work causing performance problems.",
+
options.Hook.GetType().FullName);
+ }
+
+ // Interceptor selectors no longer need to
override Equals and GetHashCode
+ }
+ }
+
+ private bool OverridesEqualsAndGetHashCode(Type type)
+ {
+ MethodInfo equalsMethod = type.GetMethod("Equals",
BindingFlags.Public | BindingFlags.Instance);
+ if (equalsMethod == null || equalsMethod.DeclaringType
== typeof(object) || equalsMethod.IsAbstract)
+ {
+ return false;
+ }
+
+ MethodInfo getHashCodeMethod =
type.GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Instance);
+ if (getHashCodeMethod == null ||
getHashCodeMethod.DeclaringType == typeof(object) ||
getHashCodeMethod.IsAbstract)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
protected void AddMapping(Type @interface, ITypeContributor
implementer, IDictionary<Type, ITypeContributor> mapping)
{
Debug.Assert(implementer != null, "implementer !=
null");
Debug.Assert(@interface != null, "@interface != null");
Debug.Assert(@interface.IsInterface,
"@interface.IsInterface");
-
if (!mapping.ContainsKey(@interface))
File [modified]: BaseProxyGenerator.cs
Delta lines: +1 -2
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/CacheKey.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/CacheKey.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -17,8 +17,7 @@
using System;
using System.Reflection;
-#if SILVERLIGHT
-#else
+#if !SILVERLIGHT
[Serializable]
#endif
File [modified]: CacheKey.cs
Delta lines: +11 -10
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassProxyGenerator.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/ClassProxyGenerator.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -62,25 +62,31 @@
using (UpgradableLock locker = new
UpgradableLock(Scope.RWLock))
{
Type cacheType = GetFromCache(cacheKey);
-
if (cacheType != null)
{
+ Logger.Debug("Found cached proxy type
{0} for target type {1}.", cacheType.FullName, targetType.FullName);
return cacheType;
}
+ // Upgrade the lock to a write lock, then read
again. This is to avoid generating duplicate types
+ // under heavy multithreaded load.
locker.Upgrade();
cacheType = GetFromCache(cacheKey);
-
if (cacheType != null)
{
+ Logger.Debug("Found cached proxy type
{0} for target type {1}.", cacheType.FullName, targetType.FullName);
return cacheType;
}
+ // Log details about the cache miss
+ Logger.Debug("No cached proxy type was found
for target type {0}.", targetType.FullName);
+
EnsureOptionsOverrideEqualsAndGetHashCode(options);
+
ProxyGenerationOptions = options;
var name =
Scope.NamingScope.GetUniqueName("Castle.Proxies." + targetType.Name + "Proxy");
- proxyType = GenerateType(name,
interfaces,Scope.NamingScope.SafeSubScope());
+ proxyType = GenerateType(name, interfaces,
Scope.NamingScope.SafeSubScope());
AddToCache(cacheKey, proxyType);
}
@@ -91,7 +97,7 @@
private Type GenerateType(string newName, Type[] interfaces,
INamingScope namingScope)
{
IEnumerable<ITypeContributor> contributors;
- var implementedInterfaces =
GetTypeImplementerMapping(interfaces, out contributors,namingScope);
+ var implementedInterfaces =
GetTypeImplementerMapping(interfaces, out contributors, namingScope);
// Collect methods
foreach (var contributor in contributors)
@@ -111,8 +117,6 @@
// Fields generations
FieldReference interceptorsField =
CreateInterceptorsField(emitter);
-
-
// Constructor
var cctor = GenerateStaticConstructor(emitter);
@@ -139,7 +143,6 @@
GenerateConstructors(emitter, targetType,
constructorArguments.ToArray());
GenerateParameterlessConstructor(emitter, targetType,
interceptorsField);
-
// Complete type initializer code body
CompleteInitCacheMethod(cctor.CodeBuilder);
@@ -155,7 +158,7 @@
var methodsToSkip = new List<MethodInfo>();
var proxyInstance = new
ClassProxyInstanceContributor(targetType, methodsToSkip, interfaces);
// TODO: the trick with methodsToSkip is not very
nice...
- var proxyTarget = new
ClassProxyTargetContributor(targetType, methodsToSkip, namingScope);
+ var proxyTarget = new
ClassProxyTargetContributor(targetType, methodsToSkip, namingScope) { Logger =
Logger };
IDictionary<Type, ITypeContributor>
typeImplementerMapping = new Dictionary<Type, ITypeContributor>();
// Order of interface precedence:
@@ -195,10 +198,8 @@
// 3. then additional interfaces
foreach (var @interface in additionalInterfaces)
{
-
if (targetInterfaces.Contains(@interface))
{
-
if
(typeImplementerMapping.ContainsKey(@interface)) continue;
File [modified]: ClassProxyGenerator.cs
Delta lines: +8 -3
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InterfaceProxyWithTargetGenerator.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -57,21 +57,27 @@
using (UpgradableLock locker = new
UpgradableLock(Scope.RWLock))
{
Type cacheType = GetFromCache(cacheKey);
-
if (cacheType != null)
{
+ Logger.Debug("Found cached proxy type
{0} for target type {1}.", cacheType.FullName, targetType.FullName);
return cacheType;
}
+ // Upgrade the lock to a write lock, then read
again. This is to avoid generating duplicate types
+ // under heavy multithreaded load.
locker.Upgrade();
cacheType = GetFromCache(cacheKey);
-
if (cacheType != null)
{
+ Logger.Debug("Found cached proxy type
{0} for target type {1}.", cacheType.FullName, targetType.FullName);
return cacheType;
}
+ // Log details about the cache miss
+ Logger.Debug("No cached proxy type was found
for target type {0}.", targetType.FullName);
+
EnsureOptionsOverrideEqualsAndGetHashCode(options);
+
ProxyGenerationOptions = options;
var name =
Scope.NamingScope.GetUniqueName("Castle.Proxies." + targetType.Name + "Proxy");
@@ -229,7 +235,6 @@
var additionalInterfaces =
TypeUtil.GetAllInterfaces(interfaces);
var target =
AddMappingForTargetType(typeImplementerMapping, proxyTargetType,
targetInterfaces, additionalInterfaces,namingScope);
-
// 2. then mixins
if (ProxyGenerationOptions.HasMixins)
File [modified]: InterfaceProxyWithTargetGenerator.cs
Delta lines: +0 -4
===================================================================
---
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InvocationTypeGenerator.cs
2009-11-29 00:42:54 UTC (rev 6369)
+++
DynamicProxy/trunk/src/Castle.DynamicProxy/Generators/InvocationTypeGenerator.cs
2009-11-29 08:05:35 UTC (rev 6370)
@@ -237,10 +237,6 @@
invokeMethodOnTarget.CodeBuilder.AddStatement(new
ReturnStatement());
}
-
-
-
-
protected void
CreateEmptyIInvocationInvokeOnTarget(AbstractTypeEmitter nested)
{
File [modified]: InvocationTypeGenerator.cs
Delta lines: +6 -0
===================================================================
--- DynamicProxy/trunk/src/Castle.DynamicProxy/IProxyBuilder.cs 2009-11-29
00:42:54 UTC (rev 6369)
+++ DynamicProxy/trunk/src/Castle.DynamicProxy/IProxyBuilder.cs 2009-11-29
08:05:35 UTC (rev 6370)
@@ -17,6 +17,7 @@
using System;
using System.Runtime.CompilerServices;
using Castle.Core.Interceptor;
+ using Castle.Core.Logging;
using Castle.DynamicProxy.Generators;
/// <summary>
@@ -25,6 +26,11 @@
public interface IProxyBuilder
{
/// <summary>
+ /// Gets or sets the <see cref="ILogger"/> that this <see
cref="ProxyGenerator"/> logs to.
+ /// </summary>
+ ILogger Logger { get; set; }
+
+ /// <summary>
/// Gets the <see cref="ModuleScope"/> associated with this
builder.
/// </summary>
Directory: /DynamicProxy/trunk/src/
===================================
File [modified]: Changes.txt
Delta lines: +0 -0
===================================================================
--
You received this message because you are subscribed to the Google Groups
"Castle Project Commits" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/castle-project-commits?hl=en.