Brought NHibernate proxy and byte code providers from NHibernate & unhAddins, set LocalSessionFactoryObject to use Spring proxy factory factory be default and thus removed LinFu dependency from NH 2.1 use

This commit is contained in:
lahma
2009-07-29 23:32:05 +00:00
parent efa1d5b7cc
commit bba99bbbaf
27 changed files with 893 additions and 39 deletions

View File

@@ -499,7 +499,24 @@ namespace Spring.Data.NHibernate
if (this.hibernateProperties != null)
{
if (config.GetProperty(Environment.ConnectionProvider) !=null &&
#if NH_2_1
// check whether proxy factory has been initialized
if (config.GetProperty(Environment.ProxyFactoryFactoryClass) == null
&& !hibernateProperties.Contains(Environment.ProxyFactoryFactoryClass))
{
// nothing set by user, lets use Spring.NET's proxy factory factory
#region Logging
if (log.IsInfoEnabled)
{
log.Info("Setting proxy factory to Spring provided one as user did not specify any");
}
#endregion
config.Properties.Add(
Environment.ProxyFactoryFactoryClass, typeof(Bytecode.ProxyFactoryFactory).AssemblyQualifiedName);
}
#endif
if (config.GetProperty(Environment.ConnectionProvider) != null &&
hibernateProperties.Contains(Environment.ConnectionProvider))
{
#region Logging

View File

@@ -0,0 +1,95 @@
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using NHibernate.Bytecode;
using NHibernate.Properties;
using NHibernate.Type;
using Spring.Objects.Factory;
#endregion
namespace Spring.Data.NHibernate.Bytecode
{
/// <summary>
///
/// </summary>
/// <author>Fabio Maulo</author>
public class BytecodeProvider : IBytecodeProvider
{
private readonly IListableObjectFactory listableObjectFactory;
private readonly IObjectsFactory objectsFactory;
private readonly DefaultCollectionTypeFactory collectionTypefactory;
///<summary>
///</summary>
///<param name="listableObjectFactory"></param>
public BytecodeProvider(IListableObjectFactory listableObjectFactory)
{
this.listableObjectFactory = listableObjectFactory;
objectsFactory = new ObjectsFactory(listableObjectFactory);
collectionTypefactory = new DefaultCollectionTypeFactory();
}
/// <summary>
/// Retrieve the <see cref="T:NHibernate.Bytecode.IReflectionOptimizer"/> delegate for this provider
/// capable of generating reflection optimization components.
/// </summary>
/// <param name="clazz">The class to be reflected upon.</param><param name="getters">All property getters to be accessed via reflection.</param><param name="setters">All property setters to be accessed via reflection.</param>
/// <returns>The reflection optimization delegate.</returns>
public IReflectionOptimizer GetReflectionOptimizer(Type clazz, IGetter[] getters, ISetter[] setters)
{
return new ReflectionOptimizer(listableObjectFactory, clazz, getters, setters);
}
/// <summary>
/// The specific factory for this provider capable of
/// generating run-time proxies for lazy-loading purposes.
/// </summary>
public IProxyFactoryFactory ProxyFactoryFactory
{
get { return new ProxyFactoryFactory(); }
}
/// <summary>
/// NHibernate's object instaciator.
/// </summary>
/// <remarks>
/// For entities <see cref="T:NHibernate.Bytecode.IReflectionOptimizer"/> and its implementations.
/// </remarks>
public IObjectsFactory ObjectsFactory
{
get { return objectsFactory; }
}
/// <summary>
/// Instanciator of NHibernate's collections default types.
/// </summary>
public ICollectionTypeFactory CollectionTypeFactory
{
get { return collectionTypefactory; }
}
}
}

View File

@@ -0,0 +1,136 @@
#if NH_2_1
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Reflection;
using AopAlliance.Intercept;
using NHibernate.Engine;
using NHibernate.Proxy.Poco;
using NHibernate.Type;
using Spring.Aop;
using Spring.Reflection.Dynamic;
#endregion
namespace Spring.Data.NHibernate.Bytecode
{
/// <summary>
///
/// </summary>
/// <author>Fabio Maulo</author>
[Serializable]
public class LazyInitializer : BasicLazyInitializer, IMethodInterceptor, ITargetSource
{
private static readonly MethodInfo exceptionInternalPreserveStackTrace =
typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic);
///<summary>
///</summary>
///<param name="entityName"></param>
///<param name="persistentClass"></param>
///<param name="id"></param>
///<param name="getIdentifierMethod"></param>
///<param name="setIdentifierMethod"></param>
///<param name="componentIdType"></param>
///<param name="session"></param>
public LazyInitializer(string entityName, Type persistentClass, object id, MethodInfo getIdentifierMethod,
MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType,
ISessionImplementor session)
: base(
entityName, persistentClass.IsInterface ? typeof(object) : persistentClass, id, getIdentifierMethod,
setIdentifierMethod, componentIdType, session) { }
#region Implementation of IInterceptor
/// <summary>
/// Implement this method to perform extra treatments before and after
/// the call to the supplied <paramref name="invocation"/>.
/// </summary>
/// <remarks>
/// <p>
/// Polite implementations would certainly like to invoke
/// <see cref="AopAlliance.Intercept.IJoinpoint.Proceed"/>.
/// </p>
/// </remarks>
/// <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)
{
try
{
MethodInfo methodInfo = invocation.Method;
object returnValue = base.Invoke(methodInfo, invocation.Arguments, invocation.Proxy);
if (returnValue != InvokeImplementation)
{
return returnValue;
}
SafeMethod method = new SafeMethod(methodInfo);
return method.Invoke(GetImplementation(), invocation.Arguments);
}
catch (TargetInvocationException ex)
{
exceptionInternalPreserveStackTrace.Invoke(ex.InnerException, new Object[] { });
throw ex.InnerException;
}
}
#endregion
#region Implementation of ITargetSource
object ITargetSource.GetTarget()
{
return Target;
}
void ITargetSource.ReleaseTarget(object target) { }
Type ITargetSource.TargetType
{
get { return PersistentClass; }
}
bool ITargetSource.IsStatic
{
get { return false; }
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,84 @@
#if NH_2_1
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using NHibernate.Bytecode;
using Spring.Objects.Factory;
#endregion
namespace Spring.Data.NHibernate.Bytecode
{
/// <summary>
///
/// </summary>
/// <author>Fabio Maulo</author>
public class ObjectsFactory : IObjectsFactory
{
private readonly IListableObjectFactory listableObjectFactory;
///<summary>
///</summary>
///<param name="listableObjectFactory"></param>
public ObjectsFactory(IListableObjectFactory listableObjectFactory)
{
this.listableObjectFactory = listableObjectFactory;
}
/// <summary>
/// Creates an instance of the specified type.
/// </summary>
/// <param name="type">The type of object to create.</param>
/// <returns>A reference to the created object.</returns>
public object CreateInstance(Type type)
{
string[] namesForType = listableObjectFactory.GetObjectNamesForType(type);
return namesForType.Length > 0 ? listableObjectFactory.GetObject(namesForType[0], type) : Activator.CreateInstance(type);
}
/// <summary>
/// Creates an instance of the specified type.
/// </summary>
/// <param name="type">The type of object to create.</param><param name="nonPublic">true if a public or nonpublic default constructor can match; false if only a public default constructor can match.</param>
/// <returns>A reference to the created object </returns>
public object CreateInstance(Type type, bool nonPublic)
{
string[] namesForType = listableObjectFactory.GetObjectNamesForType(type);
return namesForType.Length > 0 ? listableObjectFactory.GetObject(namesForType[0], type) : Activator.CreateInstance(type);
}
/// <summary>
/// Creates an instance of the specified type using the constructor that best matches the specified parameters.
/// </summary>
/// <param name="type">The type of object to create.</param><param name="ctorArgs">An array of constructor arguments.</param>
/// <returns>A reference to the created object.</returns>
public object CreateInstance(Type type, params object[] ctorArgs)
{
return Activator.CreateInstance(type, ctorArgs);
}
}
}
#endif

View File

@@ -0,0 +1,91 @@
#if NH_2_1
using System;
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using Common.Logging;
using NHibernate;
using NHibernate.Engine;
using NHibernate.Proxy;
#endregion
namespace Spring.Data.NHibernate.Bytecode
{
/// <summary>
/// A Spring for .NET backed <see cref="IProxyFactory"/> implementation for creating
/// NHibernate proxies.
/// </summary>
/// <seealso cref="ProxyFactoryFactory"/>
/// <author>Erich Eichinger</author>
public class ProxyFactory : AbstractProxyFactory
{
private static readonly ILog log = LogManager.GetLogger(typeof(ProxyFactory));
[Serializable]
private class SerializableProxyFactory : global::Spring.Aop.Framework.ProxyFactory
{
// ensure proxy types are generated as Serializable
public override bool IsSerializable
{
get { return true; }
}
}
#region IProxyFactory Members
/// <summary>
/// Creates a new proxy.
/// </summary>
/// <param name="id">The id value for the proxy to be generated.</param>
/// <param name="session">The session to which the generated proxy will be associated.</param>
/// <returns>The generated proxy.</returns>
/// <exception cref="T:NHibernate.HibernateException">Indicates problems generating requested proxy.</exception>
public override INHibernateProxy GetProxy(object id, ISessionImplementor session)
{
try
{
LazyInitializer initializer = new LazyInitializer(EntityName, PersistentClass.IsInterface ? typeof(object) : PersistentClass,
id, GetIdentifierMethod, SetIdentifierMethod, ComponentIdType, session);
SerializableProxyFactory proxyFactory = new SerializableProxyFactory();
proxyFactory.Interfaces = Interfaces;
proxyFactory.TargetSource = initializer;
proxyFactory.ProxyTargetType = IsClassProxy;
proxyFactory.AddAdvice(initializer);
object proxyInstance = proxyFactory.GetProxy();
return (INHibernateProxy)proxyInstance;
}
catch (Exception ex)
{
log.Error("Creating a proxy instance failed", ex);
throw new HibernateException("Creating a proxy instance failed", ex);
}
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,58 @@
#if NH_2_1
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using NHibernate.Bytecode;
using NHibernate.Proxy;
#endregion
namespace Spring.Data.NHibernate.Bytecode
{
/// <summary>
/// Creates a Spring for .NET backed <see cref="IProxyFactory"/> instance.
/// </summary>
/// <author>Erich Eichinger</author>
public class ProxyFactoryFactory : IProxyFactoryFactory
{
#region IProxyFactoryFactory Members
/// <summary>
/// Build a proxy factory specifically for handling runtime lazy loading.
/// </summary>
/// <returns>The lazy-load proxy factory.</returns>
public IProxyFactory BuildProxyFactory()
{
return new ProxyFactory();
}
///<summary>
///</summary>
public IProxyValidator ProxyValidator
{
get { return new DynProxyTypeValidator(); }
}
#endregion
}
}
#endif

View File

@@ -0,0 +1,81 @@
#if NH_2_1
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using NHibernate.Properties;
using Spring.Objects.Factory;
#endregion
namespace Spring.Data.NHibernate.Bytecode
{
/// <summary>
///
/// </summary>
/// <author>Fabio Maulo</author>
public class ReflectionOptimizer : global::NHibernate.Bytecode.Lightweight.ReflectionOptimizer
{
private readonly IListableObjectFactory listableObjectFactory;
///<summary>
///</summary>
///<param name="listableObjectFactory"></param>
///<param name="mappedType"></param>
///<param name="getters"></param>
///<param name="setters"></param>
public ReflectionOptimizer(IListableObjectFactory listableObjectFactory, Type mappedType, IGetter[] getters,
ISetter[] setters)
: base(mappedType, getters, setters)
{
this.listableObjectFactory = listableObjectFactory;
}
/// <summary>
/// Perform instantiation of an instance of the underlying class.
/// </summary>
/// <returns>The new instance.</returns>
public override object CreateInstance()
{
string[] namesForType = listableObjectFactory.GetObjectNamesForType(mappedType);
if (namesForType.Length > 0)
{
return listableObjectFactory.GetObject(namesForType[0], mappedType);
}
else
{
return base.CreateInstance();
}
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
protected override void ThrowExceptionForNoDefaultCtor(Type type)
{
}
}
}
#endif

View File

@@ -148,6 +148,12 @@
<Link>Data\NHibernate\LocalSessionFactoryObject.cs</Link>
</Compile>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="Data\NHibernate\Bytecode\LazyInitializer.cs" />
<Compile Include="Data\NHibernate\Bytecode\ProxyFactory.cs" />
<Compile Include="Data\NHibernate\Bytecode\ProxyFactoryFactory.cs" />
<Compile Include="Data\NHibernate\Bytecode\ReflectionOptimizer.cs" />
<Compile Include="Data\NHibernate\Bytecode\BytecodeProvider.cs" />
<Compile Include="Data\NHibernate\Bytecode\ObjectsFactory.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Spring.Aop\Spring.Aop.2008.csproj">

View File

@@ -24,7 +24,7 @@ using System.Collections;
using System.IO;
using NHibernate;
#if NH_2_1
using NHibernate.ByteCode.LinFu;
using Spring.Data.NHibernate.Bytecode;
#endif
using NHibernate.Cfg;
using NHibernate.Connection;
@@ -32,6 +32,7 @@ using NHibernate.Dialect;
using NHibernate.Driver;
using NUnit.Framework;
using Spring.Data.Common;
#endregion
@@ -57,9 +58,7 @@ namespace Spring.Data.NHibernate
properties.Add(Environment.Dialect, typeof(MsSql2000Dialect).AssemblyQualifiedName);
properties.Add(Environment.ConnectionDriver, typeof(SqlClientDriver).AssemblyQualifiedName);
properties.Add(Environment.ConnectionProvider, typeof(DriverConnectionProvider).AssemblyQualifiedName);
#if NH_2_1
properties.Add(Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName);
#endif
sfo.HibernateProperties = properties;
sfo.AfterPropertiesSet();

View File

@@ -29,9 +29,6 @@
<entry key="connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="proxyfactory.factory_class"
value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu"/>
</dictionary>
</property>
@@ -56,9 +53,6 @@
<entry key="connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="proxyfactory.factory_class"
value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu"/>
</dictionary>
</property>

View File

@@ -33,9 +33,6 @@
<entry key="connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="proxyfactory.factory_class"
value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu"/>
</dictionary>
</property>

View File

@@ -55,9 +55,6 @@
<entry key="hibernate.dialect"
value="NHibernate.Dialect.Oracle9Dialect"/>
-->
<entry key="proxyfactory.factory_class"
value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu"/>
</dictionary>
</property>

View File

@@ -53,9 +53,6 @@
<entry key="connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="proxyfactory.factory_class"
value="NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu"/>
</dictionary>
</property>

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{4A07E150-ED90-407C-8CAD-4760444DDFD9}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -36,10 +36,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\Iesi.Collections.dll</HintPath>
</Reference>
<Reference Include="LinFu.DynamicProxy, Version=1.0.3.14911, Culture=neutral, PublicKeyToken=62a6874124340d6e, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\LinFu.DynamicProxy.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\log4net.dll</HintPath>
@@ -48,10 +44,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\NHibernate.dll</HintPath>
</Reference>
<Reference Include="NHibernate.ByteCode.LinFu, Version=2.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\NHibernate.ByteCode.LinFu.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.4.1.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\Net\2.0\nunit.framework.dll</HintPath>

View File

@@ -0,0 +1,108 @@
#if NH_2_1XX
using log4net.Config;
using NHibernate.Bytecode;
using NHibernate.Cfg;
using NHibernate.Engine;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
namespace Spring.Data.NHibernate.Bytecode
{
public abstract class AbstractInjectableUserTypeFixture
{
protected ISessionFactoryImplementor sessions;
static AbstractInjectableUserTypeFixture()
{
XmlConfigurator.Configure();
}
/// <summary>
/// Initialize the ServiceLocator registering all services needed by this test.
/// </summary>
/// <remarks>
/// Services needed, in this test, are:
///
/// - uNhAddIns.Adapters.CommonTests.EnhancedBytecodeProvider.IDelimiter
/// Implementation: uNhAddIns.Adapters.CommonTests.EnhancedBytecodeProvider.ParenDelimiter
///
/// - uNhAddIns.Adapters.CommonTests.EnhancedBytecodeProvider.InjectableStringUserType
/// </remarks>
protected abstract void InitializeServiceLocator();
protected abstract IBytecodeProvider GetBytecodeProvider();
[Ignore("Work in progress")]
[TestFixtureSetUp]
public void CreateDb()
{
InitializeServiceLocator();
var cfg = new Configuration();
Environment.BytecodeProvider = GetBytecodeProvider();
cfg.Configure();
cfg.AddResource("uNhAddIns.Adapters.CommonTests.EnhancedBytecodeProvider.Foo.Spechbm.xml",
typeof(AbstractInjectableUserTypeFixture).Assembly);
new SchemaExport(cfg).Create(false, true);
sessions = (ISessionFactoryImplementor)cfg.BuildSessionFactory();
}
[Ignore("Work in progress")]
[TestFixtureTearDown]
public void CloseSessionFactory()
{
if (sessions != null)
{
sessions.Dispose();
}
sessions = null;
}
[Ignore("Work in progress")]
[Test]
public void SaveObjectWithStringChangedToUpper()
{
object savedId;
Foo f = new Foo { Description = "something" };
using (var s = sessions.OpenSession())
using (var tx = s.BeginTransaction())
{
savedId = s.Save(f);
tx.Commit();
}
using (var s = sessions.OpenSession())
{
var upperFoo = s.Get<Foo>(savedId);
Assert.AreEqual("[something]", upperFoo.Description);
}
}
[Ignore("Work in progress")]
[Test]
public void SaveNullPropertyAndGetItBack()
{
object savedId;
var f = new Foo();
using (var s = sessions.OpenSession())
using (var tx = s.BeginTransaction())
{
savedId = s.Save(f);
tx.Commit();
}
using (var s = sessions.OpenSession())
{
var upperFoo = s.Get<Foo>(savedId);
Assert.IsNull(upperFoo.Description);
}
}
}
}
#endif

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="uNhAddIns.Adapters.CommonTests"
namespace="uNhAddIns.Adapters.CommonTests.EnhancedBytecodeProvider">
<typedef name="SpecialString"
class="InjectableStringUserType"/>
<class name ="Foo">
<id type="int">
<generator class="hilo"/>
</id>
<property name="Description" type="SpecialString" />
</class>
</hibernate-mapping>

View File

@@ -0,0 +1,9 @@
#if NH_2_1XX
namespace Spring.Data.NHibernate.Bytecode
{
public class Foo
{
public virtual string Description { get; set; }
}
}
#endif

View File

@@ -0,0 +1,25 @@
#if NH_2_1XX
namespace Spring.Data.NHibernate.Bytecode
{
public interface IDelimiter
{
string Delimit(string source);
}
public class ParenDelimiter: IDelimiter
{
public string Delimit(string source)
{
return !source.StartsWith("[") ? string.Format("[{0}]", source) : source;
}
}
public class NoOpDelimiter: IDelimiter
{
public string Delimit(string source)
{
return source;
}
}
}
#endif

View File

@@ -0,0 +1,90 @@
#if NH_2_1XX
using System.Data;
using NHibernate;
using NHibernate.SqlTypes;
using NHibernate.UserTypes;
namespace Spring.Data.NHibernate.Bytecode
{
public class InjectableStringUserType : IUserType
{
private readonly IDelimiter delimiter;
public InjectableStringUserType(IDelimiter delimiter)
{
this.delimiter = delimiter;
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
var resultString = (string)NHibernateUtil.String.NullSafeGet(rs, names[0]);
if (resultString != null)
return delimiter.Delimit(resultString);
return null;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
if (value == null)
{
NHibernateUtil.String.NullSafeSet(cmd, null, index);
return;
}
value = delimiter.Delimit((string)value);
NHibernateUtil.String.NullSafeSet(cmd, value, index);
}
public object DeepCopy(object value)
{
if (value == null) return null;
return string.Copy((string)value);
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return DeepCopy(cached);
}
public object Disassemble(object value)
{
return DeepCopy(value);
}
public SqlType[] SqlTypes
{
get
{
return new[] { new SqlType(DbType.String) };
}
}
public System.Type ReturnedType
{
get { return typeof(string); }
}
public bool IsMutable
{
get { return false; }
}
public new bool Equals(object x, object y)
{
if (x == null || y == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
}
}
#endif

View File

@@ -0,0 +1,49 @@
#if NH_2_1XX
using NHibernate.Bytecode;
using NUnit.Framework;
using Spring.Context;
using Spring.Context.Support;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
namespace Spring.Data.NHibernate.Bytecode
{
//[TestFixture]
public class InjectableUserTypeFixture : AbstractInjectableUserTypeFixture
{
private IConfigurableListableObjectFactory objectFactory;
private static readonly IObjectDefinitionFactory objectDefinitionFactory = new DefaultObjectDefinitionFactory();
protected override void InitializeServiceLocator()
{
IConfigurableApplicationContext context = new StaticApplicationContext();
objectFactory = context.ObjectFactory;
Register<IDelimiter, ParenDelimiter>(objectFactory);
RegisterPrototype<InjectableStringUserType>(objectFactory);
}
protected override IBytecodeProvider GetBytecodeProvider()
{
return new BytecodeProvider(objectFactory);
}
private static void Register<TSerivice, TImplementation>(IConfigurableListableObjectFactory confObjFactory)
{
var odb = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, typeof (TImplementation)).
SetAutowireMode(AutoWiringMode.Constructor);
confObjFactory.RegisterObjectDefinition(typeof (TSerivice).FullName, odb.ObjectDefinition);
}
private static void RegisterPrototype<TImplementation>(IConfigurableListableObjectFactory confObjFactory)
{
var odb = ObjectDefinitionBuilder.RootObjectDefinition(objectDefinitionFactory, typeof(TImplementation))
.SetSingleton(false).SetAutowireMode(AutoWiringMode.AutoDetect);
confObjFactory.RegisterObjectDefinition(typeof(TImplementation).FullName, odb.ObjectDefinition);
}
}
}
#endif

View File

@@ -0,0 +1,13 @@
#if NH_2_1XX
using System;
namespace Spring.Data.NHibernate.Bytecode
{
public class Product
{
public virtual Guid Id { get; set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
}
}
#endif

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{90FEE979-7367-4542-BCCB-BF634E04A9D3}</ProjectGuid>
<OutputType>Library</OutputType>
@@ -36,10 +36,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\Iesi.Collections.dll</HintPath>
</Reference>
<Reference Include="LinFu.DynamicProxy, Version=1.0.3.14911, Culture=neutral, PublicKeyToken=62a6874124340d6e, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\LinFu.DynamicProxy.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=1.2.9.0, Culture=neutral, PublicKeyToken=b32731d11ce58905">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\log4net.dll</HintPath>
@@ -48,10 +44,6 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\NHibernate.dll</HintPath>
</Reference>
<Reference Include="NHibernate.ByteCode.LinFu, Version=2.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\NHibernate21\net\2.0\NHibernate.ByteCode.LinFu.dll</HintPath>
</Reference>
<Reference Include="nunit.framework, Version=2.2.7.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\net\2.0\nunit.framework.dll</HintPath>
@@ -98,6 +90,12 @@
<Compile Include="..\Spring.Data.NHibernate.Tests\Data\NHibernate\TestObject.cs">
<Link>Data\NHibernate\TestObject.cs</Link>
</Compile>
<Compile Include="Data\NHibernate\Bytecode\AbstractInjectableUserTypeFixture.cs" />
<Compile Include="Data\NHibernate\Bytecode\Foo.cs" />
<Compile Include="Data\NHibernate\Bytecode\IDelimiter.cs" />
<Compile Include="Data\NHibernate\Bytecode\InjectableStringUserType.cs" />
<Compile Include="Data\NHibernate\Bytecode\InjectableUserTypeFixture.cs" />
<Compile Include="Data\NHibernate\Bytecode\Product.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Spring.Data.NHibernate21.Tests.dll.config">
@@ -133,6 +131,9 @@
<ItemGroup>
<EmbeddedResource Include="Data\NHibernate\TestObject.hbm.xml" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Data\NHibernate\Bytecode\Foo.Spechbm.xml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -46,7 +46,7 @@
<!-- copy nh libs -->
<copy todir="${current.bin.dir}" overwrite="true">
<fileset basedir="${nh.lib.dir}">
<fileset basedir="${nh21.lib.dir}">
<include name="**/*.dll" />
</fileset>
</copy>