Fixing an issue with output parameters that are of type IntPtr
[castle.git] / Components / Binder / Castle.Components.Binder / DataReaderTreeBuilder.cs
blobfbfef02e273d5adc3e8f0fdfd35a1eda978d27cd
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Components.Binder
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
20 using System.Data;
22 /// <summary>
23 ///
24 /// </summary>
25 public class DataReaderTreeBuilder
27 /// <summary>
28 ///
29 /// </summary>
30 /// <param name="reader"></param>
31 /// <param name="prefix"></param>
32 /// <returns></returns>
33 public CompositeNode BuildSourceNode(IDataReader reader, String prefix)
35 CompositeNode root = new CompositeNode("root");
37 PopulateTree(root, reader, prefix);
39 return root;
42 /// <summary>
43 ///
44 /// </summary>
45 /// <param name="root"></param>
46 /// <param name="reader"></param>
47 /// <param name="prefix"></param>
48 public void PopulateTree(CompositeNode root, IDataReader reader, String prefix)
50 string[] fields = GetFields(reader);
52 int[] indexesToSkip = FindDuplicateFields(fields);
54 IndexedNode indexNode = new IndexedNode(prefix);
56 int row = 0;
58 while(reader.Read())
60 CompositeNode node = new CompositeNode(row.ToString());
62 for(int i=0; i<reader.FieldCount; i++)
64 // Is in the skip list?
65 if (Array.IndexOf(indexesToSkip, i) >= 0) continue;
67 // Is null?
68 if (reader.IsDBNull(i)) continue;
70 Type fieldType = reader.GetFieldType(i);
72 node.AddChildNode(new LeafNode(fieldType, fields[i], reader.GetValue(i)));
75 indexNode.AddChildNode(node);
77 row++;
80 root.AddChildNode(indexNode);
83 private string[] GetFields(IDataReader reader)
85 String[] fields = new String[reader.FieldCount];
87 for(int i=0; i< reader.FieldCount; i++)
89 fields[i] = reader.GetName(i);
92 return fields;
95 /// <summary>
96 /// Check the fields for duplicates.
97 /// </summary>
98 /// <param name="fields"></param>
99 /// <returns></returns>
100 /// <remarks>
101 /// I have to add this check as some stored procedures
102 /// return duplicate columns (doh!) and this isn't good
103 /// for the binder.
104 /// </remarks>
105 private int[] FindDuplicateFields(string[] fields)
107 HybridDictionary dict = new HybridDictionary(fields.Length, true);
108 ArrayList duplicateList = new ArrayList();
110 for(int i=0; i < fields.Length; i++)
112 String field = fields[i];
114 if (dict.Contains(field))
116 duplicateList.Add(i);
117 continue;
120 dict.Add(field, String.Empty);
123 return (int[]) duplicateList.ToArray(typeof(int));