|
From: <fab...@us...> - 2009-04-17 14:24:56
|
Revision: 4183
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4183&view=rev
Author: fabiomaulo
Date: 2009-04-17 14:24:40 +0000 (Fri, 17 Apr 2009)
Log Message:
-----------
Fix NH-1736 and some related issues (as the one in SessionFactoryHelper)
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Hql/Util/SessionFactoryHelper.cs
trunk/nhibernate/src/NHibernate/Util/StringHelper.cs
trunk/nhibernate/src/NHibernate/Util/TypeNameParser.cs
trunk/nhibernate/src/NHibernate.Test/UtilityTest/StringHelperFixture.cs
trunk/nhibernate/src/NHibernate.Test/UtilityTest/TypeNameParserFixture.cs
Modified: trunk/nhibernate/src/NHibernate/Hql/Util/SessionFactoryHelper.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Hql/Util/SessionFactoryHelper.cs 2009-04-16 16:44:03 UTC (rev 4182)
+++ trunk/nhibernate/src/NHibernate/Hql/Util/SessionFactoryHelper.cs 2009-04-17 14:24:40 UTC (rev 4183)
@@ -11,6 +11,17 @@
{
public static IQueryable FindQueryableUsingImports(ISessionFactoryImplementor sfi, string className)
{
+ // NH : short cut
+ if(string.IsNullOrEmpty(className))
+ {
+ return null;
+ }
+
+ if(!char.IsLetter(className[0]) && !className[0].Equals('_'))
+ {
+ return null;
+ }
+
// NH : this method prevent unrecognized class when entityName != class.FullName
// this is a patch for the TODO below
var possibleResult = sfi.TryGetEntityPersister(GetEntityName(className)) as IQueryable;
Modified: trunk/nhibernate/src/NHibernate/Util/StringHelper.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Util/StringHelper.cs 2009-04-16 16:44:03 UTC (rev 4182)
+++ trunk/nhibernate/src/NHibernate/Util/StringHelper.cs 2009-04-17 14:24:40 UTC (rev 4183)
@@ -235,7 +235,7 @@
/// <returns></returns>
public static string GetFullClassname(string typeName)
{
- return new TypeNameParser().ParseTypeName(typeName, null, null).Type;
+ return new TypeNameParser(null, null).ParseTypeName(typeName).Type;
}
/// <summary>
Modified: trunk/nhibernate/src/NHibernate/Util/TypeNameParser.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Util/TypeNameParser.cs 2009-04-16 16:44:03 UTC (rev 4182)
+++ trunk/nhibernate/src/NHibernate/Util/TypeNameParser.cs 2009-04-17 14:24:40 UTC (rev 4183)
@@ -1,193 +1,230 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
-using System.IO;
using System.Text;
namespace NHibernate.Util
{
public class ParserException : ApplicationException
{
- public ParserException(string message) : base(message) {}
+ public ParserException(string message) : base(message) { }
}
public class TypeNameParser
{
- private TextReader input;
+ private readonly string defaultNamespace;
+ private readonly string defaultAssembly;
- private void SkipSpaces()
+ public TypeNameParser(string defaultNamespace, string defaultAssembly)
{
- while (input.Peek() == ' ')
- {
- input.Read();
- }
+ this.defaultNamespace = defaultNamespace;
+ this.defaultAssembly = defaultAssembly;
}
- private char[] Characters(int count)
+ public static AssemblyQualifiedTypeName Parse(string type)
{
- var chars = new char[count];
- if (input.ReadBlock(chars, 0, count) < count)
- {
- throw new ParserException(count + " characters expected");
- }
+ return Parse(type, null, null);
+ }
- return chars;
+ public static AssemblyQualifiedTypeName Parse(string type, string defaultNamespace, string defaultAssembly)
+ {
+ return new TypeNameParser(defaultNamespace, defaultAssembly).ParseTypeName(type);
}
- private char[] PossiblyEscapedCharacter()
+ public AssemblyQualifiedTypeName ParseTypeName(string type)
{
- if (input.Peek() == '\\')
+ if (type == null)
{
- return Characters(2);
+ throw new ArgumentNullException("type");
}
- else
+ if (type.Trim('[',']','\\', ',') == string.Empty)
{
- return Characters(1);
+ throw new ArgumentException(string.Format("The type to parse is not a type name:{0}", type), "type");
}
- }
- private string AssemblyName()
- {
- var result = new StringBuilder();
- SkipSpaces();
+ int genericTypeArgsStartIdx = type.IndexOf('[');
+ int genericTypeArgsEndIdx = type.LastIndexOf(']');
+ int genericTypeCardinalityIdx = -1;
+ if (genericTypeArgsStartIdx >= 0)
+ {
+ genericTypeCardinalityIdx = type.IndexOf('`', 0, genericTypeArgsStartIdx);
+ }
- int code;
- while ((code = input.Peek()) != -1)
+ if (genericTypeArgsStartIdx == -1 || genericTypeCardinalityIdx == -1)
{
- var ch = (char) code;
+ return ParseNonGenericType(type);
+ }
+ else
+ {
+ var isArrayType = type.EndsWith("[]");
+ if(genericTypeCardinalityIdx < 0)
+ {
+ throw new ParserException("Invalid generic fully-qualified type name:" + type);
+ }
+ string cardinalityString = type.Substring(genericTypeCardinalityIdx + 1, genericTypeArgsStartIdx - genericTypeCardinalityIdx - 1);
+ int genericTypeCardinality = int.Parse(cardinalityString);
- if (ch == ']')
+ // get the FullName of the non-generic type
+ string fullName = type.Substring(0, genericTypeArgsStartIdx);
+ if (type.Length - genericTypeArgsEndIdx - 1 > 0)
+ fullName += type.Substring(genericTypeArgsEndIdx + 1, type.Length - genericTypeArgsEndIdx - 1);
+
+ // parse the type arguments
+ var genericTypeArgs = new List<AssemblyQualifiedTypeName>();
+ string typeArguments = type.Substring(genericTypeArgsStartIdx + 1, genericTypeArgsEndIdx - genericTypeArgsStartIdx - 1);
+ foreach (string item in GenericTypesArguments(typeArguments, genericTypeCardinality))
{
- break;
+ var typeArgument = ParseTypeName(item);
+ genericTypeArgs.Add(typeArgument);
}
- result.Append(PossiblyEscapedCharacter());
+ // construct the generic type definition
+ return MakeGenericType(ParseNonGenericType(fullName), isArrayType, genericTypeArgs.ToArray());
}
-
- return result.ToString();
}
- private string BracketedPart(string defaultNamespace, string defaultAssembly)
+ public AssemblyQualifiedTypeName MakeGenericType(AssemblyQualifiedTypeName qualifiedName, bool isArrayType,
+ AssemblyQualifiedTypeName[] typeArguments)
{
- Debug.Assert(input.Peek() == '[');
+ Debug.Assert(typeArguments.Length > 0);
- var result = new StringBuilder();
- var genericTypeName = new StringBuilder(200);
-
- int depth = 0;
- do
+ var baseType = qualifiedName.Type;
+ var sb = new StringBuilder(typeArguments.Length * 200);
+ sb.Append(baseType);
+ sb.Append('[');
+ for (int i = 0; i < typeArguments.Length; i++)
{
- int c = input.Peek();
- if (c == '[')
+ if(i>0)
{
- depth++;
- result.Append(PossiblyEscapedCharacter());
+ sb.Append(",");
}
- else if (c == ']')
- {
- depth--;
- if (genericTypeName.Length > 0)
- {
- var r = Parse(genericTypeName.ToString(), defaultNamespace, defaultAssembly);
- result.Append(r.ToString());
- genericTypeName.Remove(0, genericTypeName.Length);
- }
- result.Append(PossiblyEscapedCharacter());
- }
- else if (c == ',' || c == ' ')
- {
- if (genericTypeName.Length > 0)
- genericTypeName.Append(PossiblyEscapedCharacter());
- else
- result.Append(PossiblyEscapedCharacter());
- }
- else
- {
- genericTypeName.Append(PossiblyEscapedCharacter());
- }
+ sb.Append('[').Append(typeArguments[i].ToString()).Append(']');
}
- while (depth > 0 && input.Peek() != -1);
-
- if (depth > 0 && input.Peek() == -1)
+ sb.Append(']');
+ if(isArrayType)
{
- throw new ParserException("Unmatched left bracket ('[')");
+ sb.Append("[]");
}
-
- return result.ToString();
+ return new AssemblyQualifiedTypeName(sb.ToString(), qualifiedName.Assembly);
}
- public AssemblyQualifiedTypeName ParseTypeName(string text, string defaultNamespace, string defaultAssembly)
+ private static IEnumerable<string> GenericTypesArguments(string s, int cardinality)
{
- text = text.Trim();
- if (IsSystemType(text))
- {
- defaultNamespace = null;
- defaultAssembly = null;
- }
- var type = new StringBuilder(text.Length);
- string assembly = StringHelper.IsEmpty(defaultAssembly) ? null : defaultAssembly;
+ Debug.Assert(cardinality != 0);
+ Debug.Assert(string.IsNullOrEmpty(s) == false);
+ Debug.Assert(s.Length > 0);
- try
+ int startIndex = 0;
+ while (cardinality > 0)
{
- bool seenNamespace = false;
+ var sb = new StringBuilder(s.Length);
+ int bracketCount = 0;
- using (input = new StringReader(text))
+ for (int i = startIndex; i < s.Length; i++)
{
- int code;
- while ((code = input.Peek()) != -1)
+ switch (s[i])
{
- var ch = (char) code;
+ case '[':
+ bracketCount++;
+ continue;
- if (ch == '.')
- {
- seenNamespace = true;
- }
-
- if (ch == ',')
- {
- input.Read();
- assembly = AssemblyName();
- if (input.Peek() != -1)
+ case ']':
+ if (--bracketCount == 0)
{
- throw new ParserException("Extra characters found at the end of the type name");
+ string item = s.Substring(startIndex + 1, i - startIndex - 1);
+ yield return item;
+ sb = new StringBuilder(s.Length);
+ startIndex = i + 2; // 2 = '[' + ']'
}
- }
- else if (ch == '[')
- {
- type.Append(BracketedPart(defaultNamespace, defaultAssembly));
- }
- else
- {
- type.Append(PossiblyEscapedCharacter());
- }
+ break;
+
+ default:
+ sb.Append(s[i]);
+ continue;
}
+ }
- input.Close();
+ if (bracketCount != 0)
+ {
+ throw new ParserException(string.Format("The brackets are unbalanced in the type name: {0}", s));
}
- if (!seenNamespace && StringHelper.IsNotEmpty(defaultNamespace))
+ if (sb.Length > 0)
{
- type.Insert(0, '.').Insert(0, defaultNamespace);
+ var result = sb.ToString();
+ startIndex += result.Length;
+ yield return result.TrimStart(' ', ',');
}
- return new AssemblyQualifiedTypeName(type.ToString(), assembly);
+ cardinality--;
}
- catch (Exception e)
+ }
+
+ private AssemblyQualifiedTypeName ParseNonGenericType(string typeName)
+ {
+ string typeFullName;
+ string assembliQualifiedName;
+
+ if (NeedDefaultAssembly(typeName))
{
- throw new ArgumentException("Invalid fully-qualified type name: " + text, "text", e);
+ assembliQualifiedName = defaultAssembly;
+ typeFullName = typeName;
}
+ else
+ {
+ int assemblyFullNameIdx = FindAssemblyQualifiedNameStartIndex(typeName);
+ if (assemblyFullNameIdx > 0)
+ {
+ assembliQualifiedName =
+ typeName.Substring(assemblyFullNameIdx + 1, typeName.Length - assemblyFullNameIdx - 1).Trim();
+ typeFullName = typeName.Substring(0, assemblyFullNameIdx).Trim();
+ }
+ else
+ {
+ assembliQualifiedName = null;
+ typeFullName = typeName.Trim();
+ }
+ }
+
+ if (NeedDefaultNamespace(typeFullName) && !string.IsNullOrEmpty(defaultNamespace))
+ {
+ typeFullName = string.Concat(defaultNamespace, ".", typeFullName);
+ }
+
+ return new AssemblyQualifiedTypeName(typeFullName, assembliQualifiedName);
}
- private bool IsSystemType(string tyname)
+ private static int FindAssemblyQualifiedNameStartIndex(string typeName)
{
- return tyname.StartsWith("System."); // ugly
+ for (int i = 0; i < typeName.Length; i++)
+ {
+ if(typeName[i] == ',' && typeName[i-1] != '\\')
+ {
+ return i;
+ }
+ }
+
+ return -1;
}
- public static AssemblyQualifiedTypeName Parse(string text)
+ private static bool NeedDefaultNamespaceOrDefaultAssembly(string typeFullName)
{
- return Parse(text, null, null);
+ return !typeFullName.StartsWith("System."); // ugly
}
- public static AssemblyQualifiedTypeName Parse(string text, string defaultNamespace, string defaultAssembly)
+ private static bool NeedDefaultNamespace(string typeFullName)
{
- return new TypeNameParser().ParseTypeName(text, defaultNamespace, defaultAssembly);
+ if (!NeedDefaultNamespaceOrDefaultAssembly(typeFullName))
+ {
+ return false;
+ }
+ int assemblyFullNameIndex = typeFullName.IndexOf(',');
+ int firstDotIndex = typeFullName.IndexOf('.');
+ // does not have a dot or the dot is part of AssemblyFullName
+ return firstDotIndex < 0 || (firstDotIndex > assemblyFullNameIndex && assemblyFullNameIndex > 0);
}
+
+ private static bool NeedDefaultAssembly(string typeFullName)
+ {
+ return NeedDefaultNamespaceOrDefaultAssembly(typeFullName) && typeFullName.IndexOf(',') < 0;
+ }
}
}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate.Test/UtilityTest/StringHelperFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/UtilityTest/StringHelperFixture.cs 2009-04-16 16:44:03 UTC (rev 4182)
+++ trunk/nhibernate/src/NHibernate.Test/UtilityTest/StringHelperFixture.cs 2009-04-17 14:24:40 UTC (rev 4183)
@@ -37,7 +37,7 @@
string expected = typeof (IDictionary<int, string>).FullName;
Assert.AreEqual(expected, StringHelper.GetFullClassname(typeName));
typeName = "some.namespace.SomeType`1[[System.Int32, mscorlib], System.Int32], some.assembly";
- expected = "some.namespace.SomeType`1[[System.Int32, mscorlib], System.Int32]";
+ expected = "some.namespace.SomeType`1[[System.Int32, mscorlib],[System.Int32]]";
Assert.AreEqual(expected, StringHelper.GetFullClassname(typeName));
}
@@ -107,7 +107,7 @@
public void GetClassnameFromGenericType()
{
const string typeName = "classname`1[innerns1.innerClass]";
- const string expected = "classname`1[innerns1.innerClass]";
+ const string expected = "classname`1[[innerns1.innerClass]]";
Assert.AreEqual(expected, StringHelper.GetClassname(typeName));
}
@@ -116,7 +116,7 @@
public void GetClassnameFromGenericFQClass()
{
const string typeName = "ns1.ns2.classname`1[innerns1.innerClass]";
- const string expected = "classname`1[innerns1.innerClass]";
+ const string expected = "classname`1[[innerns1.innerClass]]";
Assert.AreEqual(expected, StringHelper.GetClassname(typeName));
}
Modified: trunk/nhibernate/src/NHibernate.Test/UtilityTest/TypeNameParserFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/UtilityTest/TypeNameParserFixture.cs 2009-04-16 16:44:03 UTC (rev 4182)
+++ trunk/nhibernate/src/NHibernate.Test/UtilityTest/TypeNameParserFixture.cs 2009-04-17 14:24:40 UTC (rev 4183)
@@ -1,13 +1,14 @@
using System;
using NHibernate.Util;
using NUnit.Framework;
+using System.Collections.Generic;
namespace NHibernate.Test.UtilityTest
{
[TestFixture]
public class TypeNameParserFixture
{
- private void CheckInput(string input, string expectedType, string expectedAssembly)
+ private static void CheckInput(string input, string expectedType, string expectedAssembly)
{
AssemblyQualifiedTypeName tn = TypeNameParser.Parse(input);
Assert.AreEqual(expectedType, tn.Type, "Type name should match");
@@ -35,31 +36,33 @@
[Test]
public void ParseFullAssemblyName()
{
- string assemblyName = "SomeAssembly, SomeCulture, SomethingElse";
+ const string assemblyName = "SomeAssembly, SomeCulture, SomethingElse";
CheckInput("SomeType, " + assemblyName, "SomeType", assemblyName);
}
[Test]
public void ParseGenericTypeName()
{
- string assemblyName = "SomeAssembly";
- string typeName = "SomeType`1[System.Int32]";
+ const string assemblyName = "SomeAssembly";
+ const string typeName = "SomeType`1[System.Int32]";
+ const string expectedTypeName = "SomeType`1[[System.Int32]]";
- CheckInput(typeName + ", " + assemblyName, typeName, assemblyName);
+ CheckInput(typeName + ", " + assemblyName, expectedTypeName, assemblyName);
}
[Test]
public void ParseComplexGenericTypeName()
{
- string typeName = "SomeType`1[[System.Int32, mscorlib], System.Int32]";
+ const string typeName = "SomeType`2[[System.Int32, mscorlib], System.Int32]";
+ const string expectedTypeName = "SomeType`2[[System.Int32, mscorlib],[System.Int32]]";
- CheckInput(typeName, typeName, null);
+ CheckInput(typeName, expectedTypeName, null);
}
- [Test, ExpectedException(typeof(ArgumentException))]
+ [Test, Ignore("Not a big problem because the next type request will throw the exception"), ExpectedException(typeof(ParserException))]
public void ParseUnmatchedBracket()
{
- TypeNameParser.Parse("SomeName[");
+ TypeNameParser.Parse("SomeName[");
}
[Test]
@@ -71,7 +74,7 @@
[Test]
public void ParseWithDefaultAssemblyUnused()
{
- string defaultAssembly = "DefaultAssembly";
+ const string defaultAssembly = "DefaultAssembly";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse("SomeType, AnotherAssembly", null, defaultAssembly);
Assert.AreEqual("SomeType", tn.Type);
Assert.AreEqual("AnotherAssembly", tn.Assembly);
@@ -80,7 +83,7 @@
[Test]
public void ParseWithDefaultAssembly()
{
- string defaultAssembly = "SomeAssembly";
+ const string defaultAssembly = "SomeAssembly";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse("SomeType", null, defaultAssembly);
Assert.AreEqual("SomeType", tn.Type);
Assert.AreEqual(defaultAssembly, tn.Assembly);
@@ -89,8 +92,8 @@
[Test]
public void ParseWithDefaultNamespaceAndAssembly()
{
- string defaultAssembly = "DefaultAssembly";
- string defaultNamespace = "DefaultNamespace";
+ const string defaultAssembly = "DefaultAssembly";
+ const string defaultNamespace = "DefaultNamespace";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse("SomeType", defaultNamespace, defaultAssembly);
Assert.AreEqual("DefaultNamespace.SomeType", tn.Type);
@@ -99,7 +102,7 @@
[Test]
public void ParseWithDefaultNamespaceNoAssembly()
{
- string defaultNamespace = "DefaultNamespace";
+ const string defaultNamespace = "DefaultNamespace";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse("SomeType", defaultNamespace, null);
Assert.AreEqual("DefaultNamespace.SomeType", tn.Type);
@@ -109,8 +112,8 @@
[Test]
public void ParseWithDefaultNamespaceUnused()
{
- string defaultAssembly = "DefaultAssembly";
- string defaultNamespace = "DefaultNamespace";
+ const string defaultAssembly = "DefaultAssembly";
+ const string defaultNamespace = "DefaultNamespace";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse("SomeNamespace.SomeType", defaultNamespace, defaultAssembly);
Assert.AreEqual("SomeNamespace.SomeType", tn.Type);
@@ -134,7 +137,7 @@
string fullSpec = "TName`1[PartialName]";
string defaultassembly = "SomeAssembly";
string defaultNamespace = "SomeAssembly.MyNS";
- string expectedType = "SomeAssembly.MyNS.TName`1[SomeAssembly.MyNS.PartialName, SomeAssembly]";
+ string expectedType = "SomeAssembly.MyNS.TName`1[[SomeAssembly.MyNS.PartialName, SomeAssembly]]";
string expectedAssembly = "SomeAssembly";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse(fullSpec, defaultNamespace, defaultassembly);
@@ -167,7 +170,7 @@
string fullSpec = "TName`1[SomeAssembly.MyOtherNS.PartialName]";
string defaultassembly = "SomeAssembly";
string defaultNamespace = "SomeAssembly.MyNS";
- string expectedType = "SomeAssembly.MyNS.TName`1[SomeAssembly.MyOtherNS.PartialName, SomeAssembly]";
+ string expectedType = "SomeAssembly.MyNS.TName`1[[SomeAssembly.MyOtherNS.PartialName, SomeAssembly]]";
string expectedAssembly = "SomeAssembly";
AssemblyQualifiedTypeName tn = TypeNameParser.Parse(fullSpec, defaultNamespace, defaultassembly);
@@ -177,7 +180,7 @@
fullSpec = "SomeType`1[System.Int32]";
defaultassembly = "SomeAssembly";
defaultNamespace = null;
- expectedType = "SomeType`1[System.Int32]";
+ expectedType = "SomeType`1[[System.Int32]]";
expectedAssembly = "SomeAssembly";
tn = TypeNameParser.Parse(fullSpec, defaultNamespace, defaultassembly);
@@ -196,5 +199,57 @@
{
}
+
+ public class MyComplexClass<T1, T2, T3>
+ {
+
+ }
+
+ [Test]
+ public void ParseComplexGenericType()
+ {
+ var expectedType = typeof(MyComplexClass<MyGClass<int>, IDictionary<string, MyGClass<string>>, string>).AssemblyQualifiedName;
+ var a = TypeNameParser.Parse(expectedType);
+ Assert.AreEqual(expectedType, a.ToString(), "Type name should match");
+ }
+
+ [Test]
+ [Description("Should parse arrays of System types")]
+ public void SystemArray()
+ {
+ var expectedType = typeof(string[]).AssemblyQualifiedName;
+ var a = TypeNameParser.Parse(expectedType);
+ Assert.AreEqual(expectedType, a.ToString());
+ }
+
+ [Test]
+ [Description("Should parse arrays of custom types")]
+ public void CustomArray()
+ {
+ var expectedType = "A[]";
+ var a = TypeNameParser.Parse(expectedType);
+ Assert.AreEqual(expectedType, a.ToString());
+
+ expectedType = typeof(MyGClass<int>[]).FullName;
+ a = TypeNameParser.Parse(expectedType);
+ Assert.AreEqual(expectedType, a.ToString());
+
+ expectedType = typeof(MyGClass<int[]>[]).FullName;
+ a = TypeNameParser.Parse(expectedType);
+ Assert.AreEqual(expectedType, a.ToString());
+
+ expectedType = "MyGClass`1[[System.Int32[]]][]";
+ a = TypeNameParser.Parse(expectedType);
+ Assert.AreEqual(expectedType, a.ToString());
+ }
+
+ [Test]
+ public void NH1736()
+ {
+ var typeName =
+ "Test.NHMapping.CustomCollection`2[[Test.Common.InvoiceDetail, Test.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a873a127e0d1872],[Test.ReadOnlyBusinessObjectList`1[[Test.Common.InvoiceDetail, Test.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a873a127e0d1872]], Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a873a127e0d1872]], Test.NHMapping, Version=1.0.0.0, Culture=neutral, PublicKeyToken=3a873a127e0d1872";
+ var a = TypeNameParser.Parse(typeName);
+ Assert.AreEqual(typeName, a.ToString());
+ }
}
}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|