Skip to content

Commit 83fcf1a

Browse files
author
Davy Brion
committed
fix for NH-1728
SVN: trunk@4179
1 parent 762afec commit 83fcf1a

File tree

4 files changed

+79
-34
lines changed

4 files changed

+79
-34
lines changed

src/NHibernate.Test/TransformTests/AliasToBeanResultTransformerFixture.cs

+54-16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections;
23
using System.Collections.Generic;
34
using NHibernate.Transform;
@@ -36,6 +37,11 @@ public string Something
3637
}
3738
}
3839

40+
public struct TestStruct
41+
{
42+
public string Something { get; set; }
43+
}
44+
3945
#region Overrides of TestCase
4046

4147
protected override IList Mappings
@@ -53,32 +59,64 @@ protected override string MappingsAssembly
5359
[Test]
5460
public void WorkWithOutPublicParameterLessCtor()
5561
{
56-
Setup();
62+
try
63+
{
64+
Setup();
5765

58-
using (ISession s = OpenSession())
66+
using (ISession s = OpenSession())
67+
{
68+
IList<WithOutPublicParameterLessCtor> l =
69+
s.CreateSQLQuery("select s.Name as something from Simple s").SetResultTransformer(
70+
Transformers.AliasToBean<WithOutPublicParameterLessCtor>()).List<WithOutPublicParameterLessCtor>();
71+
Assert.That(l.Count, Is.EqualTo(2));
72+
Assert.That(l, Has.All.Not.Null);
73+
}
74+
}
75+
finally
5976
{
60-
IList<WithOutPublicParameterLessCtor> l =
61-
s.CreateSQLQuery("select s.Name as something from Simple s").SetResultTransformer(
62-
Transformers.AliasToBean<WithOutPublicParameterLessCtor>()).List<WithOutPublicParameterLessCtor>();
63-
Assert.That(l.Count, Is.EqualTo(2));
64-
Assert.That(l, Has.All.Not.Null);
77+
Cleanup();
6578
}
66-
67-
Cleanup();
6879
}
6980

7081
[Test]
7182
public void WorkWithPublicParameterLessCtor()
7283
{
73-
Setup();
84+
try
85+
{
86+
Setup();
87+
88+
var queryString = "select s.Name as something from Simple s";
89+
AssertAreWorking(queryString); // working for field access
7490

75-
var queryString = "select s.Name as something from Simple s";
76-
AssertAreWorking(queryString); // working for field access
77-
78-
queryString = "select s.Name as Something from Simple s";
79-
AssertAreWorking(queryString); // working for property access
91+
queryString = "select s.Name as Something from Simple s";
92+
AssertAreWorking(queryString); // working for property access
93+
}
94+
finally
95+
{
96+
Cleanup();
97+
}
98+
}
8099

81-
Cleanup();
100+
[Test]
101+
public void WorksWithStruct()
102+
{
103+
try
104+
{
105+
Setup();
106+
107+
IList<TestStruct> result;
108+
using (ISession s = OpenSession())
109+
{
110+
result = s.CreateSQLQuery("select s.Name as something from Simple s")
111+
.SetResultTransformer(Transformers.AliasToBean<TestStruct>())
112+
.List<TestStruct>();
113+
}
114+
Assert.AreEqual(2, result.Count);
115+
}
116+
finally
117+
{
118+
Cleanup();
119+
}
82120
}
83121

84122
private void AssertAreWorking(string queryString)

src/NHibernate/Properties/BasicPropertyAccessor.cs

+15-14
Original file line numberDiff line numberDiff line change
@@ -130,31 +130,32 @@ internal static BasicSetter GetSetterOrNull(System.Type type, string propertyNam
130130
return null;
131131
}
132132

133+
// the BindingFlags.IgnoreCase is important here because if type is a struct, the GetProperty method does
134+
// not ignore case by default. If type is a class, it _does_ ignore case... we're better off explicitly
135+
// stating that casing should be ignored so we get the same behavior for both structs and classes
133136
PropertyInfo property =
134137
type.GetProperty(propertyName,
135-
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly);
138+
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase);
136139

137140
if (property != null && property.CanWrite)
138141
{
139142
return new BasicSetter(type, property, propertyName);
140143
}
141-
else
142-
{
143-
// recursively call this method for the base Type
144-
BasicSetter setter = GetSetterOrNull(type.BaseType, propertyName);
145144

146-
// didn't find anything in the base class - check to see if there is
147-
// an explicit interface implementation.
148-
if (setter == null)
145+
// recursively call this method for the base Type
146+
BasicSetter setter = GetSetterOrNull(type.BaseType, propertyName);
147+
148+
// didn't find anything in the base class - check to see if there is
149+
// an explicit interface implementation.
150+
if (setter == null)
151+
{
152+
System.Type[] interfaces = type.GetInterfaces();
153+
for (int i = 0; setter == null && i < interfaces.Length; i++)
149154
{
150-
System.Type[] interfaces = type.GetInterfaces();
151-
for (int i = 0; setter == null && i < interfaces.Length; i++)
152-
{
153-
setter = GetSetterOrNull(interfaces[i], propertyName);
154-
}
155+
setter = GetSetterOrNull(interfaces[i], propertyName);
155156
}
156-
return setter;
157157
}
158+
return setter;
158159
}
159160

160161
/// <summary>

src/NHibernate/Transform/AliasToBeanResultTransformer.cs

+8-2
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,12 @@ public AliasToBeanResultTransformer(System.Type resultClass)
4040
throw new ArgumentNullException("resultClass");
4141
}
4242
this.resultClass = resultClass;
43+
4344
constructor = resultClass.GetConstructor(flags, null, System.Type.EmptyTypes, null);
44-
if (constructor == null)
45+
46+
// if resultClass is a ValueType (struct), GetConstructor will return null...
47+
// in that case, we'll use Activator.CreateInstance instead of the ConstructorInfo to create instances
48+
if (constructor == null && resultClass.IsClass)
4549
{
4650
throw new ArgumentException("The target class of a AliasToBeanResultTransformer need a parameter-less constructor",
4751
"resultClass");
@@ -73,7 +77,9 @@ public object TransformTuple(object[] tuple, String[] aliases)
7377
}
7478
}
7579
}
76-
result = constructor.Invoke(null);
80+
81+
// if resultClass is not a class but a value type, we need to use Activator.CreateInstance
82+
result = resultClass.IsClass ? constructor.Invoke(null) : Activator.CreateInstance(resultClass, true);
7783

7884
for (int i = 0; i < aliases.Length; i++)
7985
{

src/NHibernate/Transform/Transformers.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ public static IResultTransformer AliasToBean(System.Type target)
2222
return new AliasToBeanResultTransformer(target);
2323
}
2424

25-
public static IResultTransformer AliasToBean<T>() where T: class
25+
public static IResultTransformer AliasToBean<T>()
2626
{
27-
return AliasToBean(typeof (T));
27+
return AliasToBean(typeof(T));
2828
}
2929

3030
public static readonly IResultTransformer DistinctRootEntity = new DistinctRootEntityResultTransformer();

0 commit comments

Comments
 (0)