2 // System.Web.UI.WebControls.ObjectDataSourceView
5 // Lluis Sanchez Gual (lluis@novell.com)
7 // (C) 2005 Novell, Inc. (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Reflection;
34 using System.Collections;
35 using System.Collections.Specialized;
36 using System.ComponentModel;
39 using System.Web.Compilation;
41 namespace System.Web.UI.WebControls
44 public class ObjectDataSourceView : DataSourceView, IStateManager
46 ObjectDataSource owner;
51 bool convertNullToDBNull = false;
52 bool enablePaging = false;
53 string dataObjectTypeName = null;
54 string filterExpression = null;
55 string maximumRowsParameterName = null;
56 string oldValuesParameterFormatString = null;
57 string deleteMethod = null;
58 string insertMethod = null;
59 string selectCountMethod = null;
60 string selectMethod = null;
61 string sortParameterName = null;
62 string startRowIndexParameterName = null;
63 string typeName = null;
64 string updateMethod = null;
65 private static string privateBinPath = null;
67 bool isTrackingViewState = false;
68 ParameterCollection selectParameters;
69 ParameterCollection updateParameters;
70 ParameterCollection deleteParameters;
71 ParameterCollection insertParameters;
72 ParameterCollection filterParameters;
74 private static readonly object DeletedEvent = new object();
75 private static readonly object DeletingEvent = new object();
76 private static readonly object FilteringEvent = new object();
77 private static readonly object InsertedEvent = new object();
78 private static readonly object InsertingEvent = new object();
79 private static readonly object ObjectCreatedEvent = new object();
80 private static readonly object ObjectCreatingEvent = new object();
81 private static readonly object ObjectDisposingEvent = new object();
82 // private static readonly object ResolvingMethodEvent = new object();
83 private static readonly object SelectedEvent = new object();
84 private static readonly object SelectingEvent = new object();
85 private static readonly object UpdatedEvent = new object();
86 private static readonly object UpdatingEvent = new object();
88 public ObjectDataSourceView (ObjectDataSource owner, string name, HttpContext context): base (owner, name)
91 this.context = context;
94 public event ObjectDataSourceStatusEventHandler Deleted {
95 add { Events.AddHandler (DeletedEvent, value); }
96 remove { Events.RemoveHandler (DeletedEvent, value); }
99 public event ObjectDataSourceMethodEventHandler Deleting {
100 add { Events.AddHandler (DeletingEvent, value); }
101 remove { Events.RemoveHandler (DeletingEvent, value); }
104 public event ObjectDataSourceFilteringEventHandler Filtering {
105 add { Events.AddHandler (FilteringEvent, value); }
106 remove { Events.RemoveHandler (FilteringEvent, value); }
109 public event ObjectDataSourceStatusEventHandler Inserted {
110 add { Events.AddHandler (InsertedEvent, value); }
111 remove { Events.RemoveHandler (InsertedEvent, value); }
114 public event ObjectDataSourceMethodEventHandler Inserting {
115 add { Events.AddHandler (InsertingEvent, value); }
116 remove { Events.RemoveHandler (InsertingEvent, value); }
119 public event ObjectDataSourceObjectEventHandler ObjectCreated {
120 add { Events.AddHandler (ObjectCreatedEvent, value); }
121 remove { Events.RemoveHandler (ObjectCreatedEvent, value); }
124 public event ObjectDataSourceObjectEventHandler ObjectCreating {
125 add { Events.AddHandler (ObjectCreatingEvent, value); }
126 remove { Events.RemoveHandler (ObjectCreatingEvent, value); }
129 public event ObjectDataSourceDisposingEventHandler ObjectDisposing {
130 add { Events.AddHandler (ObjectDisposingEvent, value); }
131 remove { Events.RemoveHandler (ObjectDisposingEvent, value); }
134 /* public event ObjectDataSourceResolvingMethodEventHandler ResolvingMethod {
135 add { Events.AddHandler (ResolvingMethodEvent, value); }
136 remove { Events.RemoveHandler (ResolvingMethodEvent, value); }
139 public event ObjectDataSourceStatusEventHandler Selected {
140 add { Events.AddHandler (SelectedEvent, value); }
141 remove { Events.RemoveHandler (SelectedEvent, value); }
144 public event ObjectDataSourceSelectingEventHandler Selecting {
145 add { Events.AddHandler (SelectingEvent, value); }
146 remove { Events.RemoveHandler (SelectingEvent, value); }
149 public event ObjectDataSourceStatusEventHandler Updated {
150 add { Events.AddHandler (UpdatedEvent, value); }
151 remove { Events.RemoveHandler (UpdatedEvent, value); }
154 public event ObjectDataSourceMethodEventHandler Updating {
155 add { Events.AddHandler (UpdatingEvent, value); }
156 remove { Events.RemoveHandler (UpdatingEvent, value); }
159 protected virtual void OnDeleted (ObjectDataSourceStatusEventArgs e)
161 if (Events != null) {
162 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [DeletedEvent];
163 if (eh != null) eh (this, e);
167 protected virtual void OnDeleting (ObjectDataSourceMethodEventArgs e)
169 if (Events != null) {
170 ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [DeletingEvent];
171 if (eh != null) eh (this, e);
175 protected virtual void OnFiltering (ObjectDataSourceFilteringEventArgs e)
177 if (Events != null) {
178 ObjectDataSourceFilteringEventHandler eh = (ObjectDataSourceFilteringEventHandler) Events [FilteringEvent];
179 if (eh != null) eh (this, e);
183 protected virtual void OnInserted (ObjectDataSourceStatusEventArgs e)
185 if (Events != null) {
186 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [InsertedEvent];
187 if (eh != null) eh (this, e);
191 protected virtual void OnInserting (ObjectDataSourceMethodEventArgs e)
193 if (Events != null) {
194 ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [InsertingEvent];
195 if (eh != null) eh (this, e);
199 protected virtual void OnObjectCreated (ObjectDataSourceEventArgs e)
201 if (Events != null) {
202 ObjectDataSourceObjectEventHandler eh = (ObjectDataSourceObjectEventHandler) Events [ObjectCreatedEvent];
203 if (eh != null) eh (this, e);
207 protected virtual void OnObjectCreating (ObjectDataSourceEventArgs e)
209 if (Events != null) {
210 ObjectDataSourceObjectEventHandler eh = (ObjectDataSourceObjectEventHandler) Events [ObjectCreatingEvent];
211 if (eh != null) eh (this, e);
215 protected virtual void OnObjectDisposing (ObjectDataSourceDisposingEventArgs e)
217 if (Events != null) {
218 ObjectDataSourceDisposingEventHandler eh = (ObjectDataSourceDisposingEventHandler) Events [ObjectDisposingEvent];
219 if (eh != null) eh (this, e);
223 /* protected virtual void OnResolvingMethod (ObjectDataSourceResolvingMethodEventArgs e)
225 if (Events != null) {
226 ObjectDataSourceResolvingMethodEventHandler eh = (ObjectDataSourceResolvingMethodEventHandler) Events [ResolvingMethodEvent];
227 if (eh != null) eh (this, e);
232 protected virtual void OnSelected (ObjectDataSourceStatusEventArgs e)
234 if (Events != null) {
235 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [SelectedEvent];
236 if (eh != null) eh (this, e);
240 protected virtual void OnSelecting (ObjectDataSourceSelectingEventArgs e)
242 if (Events != null) {
243 ObjectDataSourceSelectingEventHandler eh = (ObjectDataSourceSelectingEventHandler) Events [SelectingEvent];
244 if (eh != null) eh (this, e);
248 protected virtual void OnUpdated (ObjectDataSourceStatusEventArgs e)
250 if (Events != null) {
251 ObjectDataSourceStatusEventHandler eh = (ObjectDataSourceStatusEventHandler) Events [UpdatedEvent];
252 if (eh != null) eh (this, e);
256 protected virtual void OnUpdating (ObjectDataSourceMethodEventArgs e)
258 if (Events != null) {
259 ObjectDataSourceMethodEventHandler eh = (ObjectDataSourceMethodEventHandler) Events [UpdatingEvent];
260 if (eh != null) eh (this, e);
264 public override bool CanDelete {
265 get { return DeleteMethod.Length > 0; }
268 public override bool CanInsert {
269 get { return InsertMethod.Length > 0; }
272 public override bool CanPage {
273 get { return EnablePaging; }
276 public override bool CanRetrieveTotalRowCount {
278 if( SelectCountMethod.Length > 0)
281 return !EnablePaging;
285 public override bool CanSort {
289 public override bool CanUpdate {
290 get { return UpdateMethod.Length > 0; }
293 // LAME SPEC: MSDN says value should be stored in ViewState but tests show otherwise.
294 private ConflictOptions conflictDetection = ConflictOptions.OverwriteChanges;
295 public ConflictOptions ConflictDetection {
296 get { return conflictDetection; }
298 if (ConflictDetection == value)
\r
300 conflictDetection = value;
\r
301 OnDataSourceViewChanged (EventArgs.Empty);
305 public bool ConvertNullToDBNull {
306 get { return convertNullToDBNull; }
307 set { convertNullToDBNull = value; }
310 public string DataObjectTypeName {
312 return dataObjectTypeName != null ? dataObjectTypeName : string.Empty;
315 if (DataObjectTypeName == value)
\r
317 dataObjectTypeName = value;
318 dataObjectType = null;
\r
319 OnDataSourceViewChanged (EventArgs.Empty);
323 public string DeleteMethod {
325 return deleteMethod != null ? deleteMethod : string.Empty;
328 deleteMethod = value;
332 public ParameterCollection DeleteParameters {
334 if (deleteParameters == null) {
335 deleteParameters = new ParameterCollection ();
337 return deleteParameters;
341 public bool EnablePaging {
346 if (EnablePaging == value)
\r
348 enablePaging = value;
\r
349 OnDataSourceViewChanged (EventArgs.Empty);
353 public string FilterExpression {
355 return filterExpression != null ? filterExpression : string.Empty;
358 if (FilterExpression == value)
\r
360 filterExpression = value;
\r
361 OnDataSourceViewChanged (EventArgs.Empty);
365 public ParameterCollection FilterParameters {
367 if (filterParameters == null) {
368 filterParameters = new ParameterCollection ();
369 filterParameters.ParametersChanged += new EventHandler (OnParametersChanged);
370 if (IsTrackingViewState)
371 ((IStateManager)filterParameters).TrackViewState ();
373 return filterParameters;
377 public string InsertMethod {
379 return insertMethod != null ? insertMethod : string.Empty;
382 insertMethod = value;
386 public ParameterCollection InsertParameters {
388 if (insertParameters == null) {
389 insertParameters = new ParameterCollection ();
391 return insertParameters;
395 public string MaximumRowsParameterName {
397 return maximumRowsParameterName != null ? maximumRowsParameterName : "maximumRows";
400 if (MaximumRowsParameterName == value)
\r
402 maximumRowsParameterName = value;
\r
403 OnDataSourceViewChanged (EventArgs.Empty);
407 public string OldValuesParameterFormatString {
409 return oldValuesParameterFormatString != null ? oldValuesParameterFormatString : "{0}";
412 if (OldValuesParameterFormatString == value)
\r
414 oldValuesParameterFormatString = value;
\r
415 OnDataSourceViewChanged (EventArgs.Empty);
419 public string SelectCountMethod {
421 return selectCountMethod != null ? selectCountMethod : string.Empty;
424 if (SelectCountMethod == value)
426 selectCountMethod = value;
427 OnDataSourceViewChanged (EventArgs.Empty);
431 public string SelectMethod {
433 return selectMethod != null ? selectMethod : string.Empty;
436 if (SelectMethod == value)
438 selectMethod = value;
439 OnDataSourceViewChanged (EventArgs.Empty);
443 public ParameterCollection SelectParameters {
445 if (selectParameters == null) {
446 selectParameters = new ParameterCollection ();
447 selectParameters.ParametersChanged += new EventHandler (OnParametersChanged);
448 if (IsTrackingViewState)
449 ((IStateManager)selectParameters).TrackViewState ();
451 return selectParameters;
455 public string SortParameterName {
457 return sortParameterName != null ? sortParameterName : string.Empty;
460 sortParameterName = value;
464 public string StartRowIndexParameterName {
466 return startRowIndexParameterName != null ? startRowIndexParameterName : "startRowIndex";
469 if (StartRowIndexParameterName == value)
\r
471 startRowIndexParameterName = value;
\r
472 OnDataSourceViewChanged (EventArgs.Empty);
476 public string TypeName {
478 return typeName != null ? typeName : string.Empty;
481 if (TypeName == value)
\r
485 OnDataSourceViewChanged (EventArgs.Empty);
489 public string UpdateMethod {
491 return updateMethod != null ? updateMethod : string.Empty;
494 updateMethod = value;
498 public ParameterCollection UpdateParameters {
500 if (updateParameters == null) {
501 updateParameters = new ParameterCollection ();
503 return updateParameters;
509 if (objectType == null) {
510 objectType = HttpApplication.LoadType (TypeName);
511 if (objectType == null)
512 throw new InvalidOperationException ("Type not found: " + TypeName);
518 Type DataObjectType {
520 if (dataObjectType == null) {
521 dataObjectType = HttpApplication.LoadType (DataObjectTypeName);
522 if (dataObjectType == null)
523 throw new InvalidOperationException ("Type not found: " + DataObjectTypeName);
525 return dataObjectType;
529 public IEnumerable Select (DataSourceSelectArguments arguments)
531 return ExecuteSelect (arguments);
534 public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
536 return ExecuteUpdate (keys, values, oldValues);
539 public int Delete (IDictionary keys, IDictionary oldValues)
541 return ExecuteDelete (keys, oldValues);
544 public int Insert (IDictionary values)
546 return ExecuteInsert (values);
549 protected override int ExecuteInsert (IDictionary values)
552 throw new NotSupportedException ("Insert operation not supported.");
554 IOrderedDictionary paramValues;
557 if (DataObjectTypeName.Length == 0) {
558 paramValues = MergeParameterValues (InsertParameters, values, null);
559 method = GetObjectMethod (InsertMethod, paramValues, DataObjectMethodType.Insert);
561 method = ResolveDataObjectMethod (InsertMethod, values, null, out paramValues);
564 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
569 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
572 if (rargs.Exception != null && !rargs.ExceptionHandled)
573 throw rargs.Exception;
575 if (owner.EnableCaching)
576 owner.Cache.Expire ();
578 OnDataSourceViewChanged (EventArgs.Empty);
583 protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
586 throw new NotSupportedException ("Delete operation not supported.");
588 if (ConflictDetection == ConflictOptions.CompareAllValues && (oldValues == null || oldValues.Count == 0))
589 throw new InvalidOperationException ("ConflictDetection is set to CompareAllValues and oldValues collection is null or empty.");
591 IDictionary oldDataValues;
592 oldDataValues = BuildOldValuesList (keys, oldValues, false);
594 IOrderedDictionary paramValues;
597 if (DataObjectTypeName.Length == 0) {
598 paramValues = MergeParameterValues (DeleteParameters, null, oldDataValues);
599 method = GetObjectMethod (DeleteMethod, paramValues, DataObjectMethodType.Delete);
601 method = ResolveDataObjectMethod (DeleteMethod, oldDataValues, null, out paramValues);
604 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
609 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
613 if (rargs.Exception != null && !rargs.ExceptionHandled)
614 throw rargs.Exception;
616 if (owner.EnableCaching)
617 owner.Cache.Expire ();
619 OnDataSourceViewChanged (EventArgs.Empty);
624 protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
626 IOrderedDictionary paramValues;
629 IDictionary oldDataValues;
630 oldDataValues = BuildOldValuesList (keys, oldValues, true);
632 if (DataObjectTypeName.Length == 0)
634 IDictionary dataValues;
636 paramValues = MergeParameterValues (UpdateParameters, dataValues, oldDataValues);
637 method = GetObjectMethod (UpdateMethod, paramValues, DataObjectMethodType.Update);
641 if (ConflictDetection != ConflictOptions.CompareAllValues) {
642 oldDataValues = null;
644 IDictionary dataValues = new Hashtable ();
646 foreach (DictionaryEntry de in keys)
647 dataValues [de.Key] = de.Value;
649 if (values != null) {
650 foreach (DictionaryEntry de in values)
651 dataValues [de.Key] = de.Value;
654 method = ResolveDataObjectMethod (UpdateMethod, dataValues, oldDataValues, out paramValues);
657 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
662 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
665 if (rargs.Exception != null && !rargs.ExceptionHandled)
666 throw rargs.Exception;
668 if (owner.EnableCaching)
669 owner.Cache.Expire ();
671 OnDataSourceViewChanged (EventArgs.Empty);
676 private IDictionary BuildOldValuesList (IDictionary keys, IDictionary oldValues, bool keysWin)
678 IDictionary oldDataValues;
679 if (ConflictDetection == ConflictOptions.CompareAllValues) {
680 oldDataValues = new Hashtable ();
681 if (keys != null && !keysWin) {
682 foreach (DictionaryEntry de in keys)
683 oldDataValues [de.Key] = de.Value;
685 if (oldValues != null) {
686 foreach (DictionaryEntry de in oldValues)
687 oldDataValues [de.Key] = de.Value;
689 if (keys != null && keysWin) {
690 foreach (DictionaryEntry de in keys)
691 oldDataValues [de.Key] = de.Value;
695 oldDataValues = keys;
698 return oldDataValues;
701 protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
703 arguments.RaiseUnsupportedCapabilitiesError (this);
705 IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null, null);
706 ObjectDataSourceSelectingEventArgs args = new ObjectDataSourceSelectingEventArgs (paramValues, arguments, false);
708 object result = null;
710 if (owner.EnableCaching)
711 result = owner.Cache.GetCachedObject (SelectMethod, SelectParameters);
713 if (result == null) {
716 return new ArrayList ();
718 if (CanRetrieveTotalRowCount && arguments.RetrieveTotalRowCount)
719 arguments.TotalRowCount = QueryTotalRowCount (paramValues, arguments);
722 if (StartRowIndexParameterName.Length == 0)
723 throw new InvalidOperationException ("Paging is enabled, but the StartRowIndexParameterName property is not set.");
724 if (MaximumRowsParameterName.Length == 0)
725 throw new InvalidOperationException ("Paging is enabled, but the MaximumRowsParameterName property is not set.");
726 paramValues [StartRowIndexParameterName] = arguments.StartRowIndex;
727 paramValues [MaximumRowsParameterName] = arguments.MaximumRows;
730 if (SortParameterName.Length > 0)
731 paramValues [SortParameterName] = arguments.SortExpression;
733 result = InvokeSelect (SelectMethod, paramValues);
735 if (owner.EnableCaching)
736 owner.Cache.SetCachedObject (SelectMethod, SelectParameters, result);
739 if (FilterExpression.Length > 0 && !(result is DataGrid || result is DataView || result is DataTable))
740 throw new NotSupportedException ("The FilterExpression property was set and the Select method does not return a DataSet, DataTable, or DataView.");
742 if (owner.EnableCaching && result is IDataReader)
743 throw new NotSupportedException ("Data source does not support caching objects that implement IDataReader");
745 if (result is DataSet) {
746 DataSet dset = (DataSet) result;
747 if (dset.Tables.Count == 0)
748 throw new InvalidOperationException ("The select method returnet a DataSet which doesn't contain any table.");
749 result = dset.Tables [0];
752 if (result is DataTable) {
753 DataView dview = new DataView ((DataTable)result);
754 if (arguments.SortExpression != null && arguments.SortExpression.Length > 0) {
755 dview.Sort = arguments.SortExpression;
757 if (FilterExpression.Length > 0) {
758 IOrderedDictionary fparams = FilterParameters.GetValues (context, owner);
759 ObjectDataSourceFilteringEventArgs fargs = new ObjectDataSourceFilteringEventArgs (fparams);
762 object[] formatValues = new object [fparams.Count];
763 for (int n=0; n<formatValues.Length; n++) {
764 formatValues [n] = fparams [n];
765 if (formatValues [n] == null) return dview;
767 dview.RowFilter = string.Format (FilterExpression, formatValues);
773 if (result is IEnumerable)
774 return (IEnumerable) result;
776 return new object[] { result };
779 int QueryTotalRowCount (IOrderedDictionary mergedParameters, DataSourceSelectArguments arguments)
781 ObjectDataSourceSelectingEventArgs countArgs = new ObjectDataSourceSelectingEventArgs (mergedParameters, arguments, true);
782 OnSelecting (countArgs);
783 if (countArgs.Cancel)
786 object count = InvokeSelect (SelectCountMethod, mergedParameters);
787 return (int) Convert.ChangeType (count, typeof(int));
790 object InvokeSelect (string methodName, IOrderedDictionary paramValues)
792 MethodInfo method = GetObjectMethod (methodName, paramValues, DataObjectMethodType.Select);
793 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
796 if (rargs.Exception != null && !rargs.ExceptionHandled)
797 throw rargs.Exception;
799 return rargs.ReturnValue;
802 ObjectDataSourceStatusEventArgs InvokeMethod (MethodInfo method, IOrderedDictionary paramValues)
804 object instance = null;
806 if (!method.IsStatic)
807 instance = CreateObjectInstance ();
809 ParameterInfo[] pars = method.GetParameters ();
811 ArrayList outParamInfos;
812 object[] methodArgs = GetParameterArray (pars, paramValues, out outParamInfos);
814 if (methodArgs == null)
815 throw CreateMethodException (method.Name, paramValues);
817 object result = null;
818 Hashtable outParams = null;
821 result = method.Invoke (instance, methodArgs);
822 if (outParamInfos != null) {
823 outParams = new Hashtable ();
824 foreach (ParameterInfo op in outParamInfos)
825 outParams [op.Name] = methodArgs [op.Position];
827 return new ObjectDataSourceStatusEventArgs (result, outParams, null);
829 catch (Exception ex) {
830 return new ObjectDataSourceStatusEventArgs (result, outParams, ex);
833 if (instance != null)
834 DisposeObjectInstance (instance);
838 MethodInfo GetObjectMethod (string methodName, IOrderedDictionary parameters, DataObjectMethodType methodType)
840 MemberInfo[] methods = ObjectType.GetMember (methodName, MemberTypes.Method, BindingFlags.Instance |
841 BindingFlags.Static |
842 BindingFlags.Public |
843 BindingFlags.IgnoreCase |
844 BindingFlags.FlattenHierarchy);
845 if (methods.Length > 1) {
846 // MSDN: The ObjectDataSource resolves method overloads by method name and number
847 // of parameters; the names and types of the parameters are not considered.
848 // LAMESPEC: the tests show otherwise
849 DataObjectMethodAttribute methodAttribute = null;
850 MethodInfo methodInfo = null;
851 bool hasConflict = false;
852 foreach (MethodInfo me in methods) { // we look for methods only
853 ParameterInfo [] pinfos = me.GetParameters ();
854 if (pinfos.Length == parameters.Count) {
855 object [] attrs = me.GetCustomAttributes (typeof (DataObjectMethodAttribute), true);
856 DataObjectMethodAttribute domAttr = (attrs != null && attrs.Length > 0) ? (DataObjectMethodAttribute) attrs [0] : null;
857 if (domAttr != null && domAttr.MethodType != methodType)
860 bool paramsMatch = true;
861 foreach (ParameterInfo pinfo in pinfos) {
862 if (!parameters.Contains (pinfo.Name)) {
871 if (domAttr != null) {
872 if (methodAttribute != null) {
873 if (methodAttribute.IsDefault) {
874 if (domAttr.IsDefault) {
876 break; //fail due to a conflict
879 continue; //existing matches better
882 methodInfo = null; //we override
883 hasConflict = !domAttr.IsDefault;
887 methodInfo = null; //we override
890 if (methodInfo == null) {
891 methodAttribute = domAttr;
900 if (!hasConflict && methodInfo != null)
903 else if (methods.Length == 1) {
904 MethodInfo me = methods[0] as MethodInfo;
905 if (me != null && me.GetParameters().Length == parameters.Count)
909 throw CreateMethodException (methodName, parameters);
912 MethodInfo ResolveDataObjectMethod (string methodName, IDictionary values, IDictionary oldValues, out IOrderedDictionary paramValues)
915 if (oldValues != null)
916 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType, DataObjectType });
918 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType });
921 throw new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters of type '" + DataObjectType + "' in '" + ObjectType + "'.");
923 paramValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
924 ParameterInfo[] ps = method.GetParameters ();
926 if (oldValues != null) {
927 if (FormatOldParameter (ps[0].Name) == ps[1].Name) {
928 paramValues [ps[0].Name] = CreateDataObject (values);
929 paramValues [ps[1].Name] = CreateDataObject (oldValues);
930 } else if (FormatOldParameter (ps[1].Name) == ps[0].Name) {
931 paramValues [ps[0].Name] = CreateDataObject (oldValues);
932 paramValues [ps[1].Name] = CreateDataObject (values);
934 throw new InvalidOperationException ("Method '" + methodName + "' does not have any parameter that fits the value of OldValuesParameterFormatString.");
936 paramValues [ps[0].Name] = CreateDataObject (values);
941 Exception CreateMethodException (string methodName, IOrderedDictionary parameters)
944 foreach (string p in parameters.Keys) {
947 return new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters " + s + "in type '" + ObjectType + "'.");
950 object CreateDataObject (IDictionary values)
952 object ob = Activator.CreateInstance (DataObjectType);
953 foreach (DictionaryEntry de in values) {
954 PropertyInfo p = DataObjectType.GetProperty ((string)de.Key);
955 if (p == null) throw new InvalidOperationException ("Property " + de.Key + " not found in type '" +DataObjectType + "'.");
956 object[] attributes = p.GetCustomAttributes (typeof (System.ComponentModel.TypeConverterAttribute),
958 Type propertyType = p.PropertyType;
959 object value = de.Value;
960 object converted = ConvertParameterWithTypeConverter (attributes, propertyType, value);
961 if (converted == null)
962 converted = ConvertParameter (propertyType, value);
964 p.SetValue (ob, converted, null);
969 object CreateObjectInstance ()
971 ObjectDataSourceEventArgs args = new ObjectDataSourceEventArgs (null);
972 OnObjectCreating (args);
974 if (args.ObjectInstance != null)
975 return args.ObjectInstance;
977 object ob = Activator.CreateInstance (ObjectType);
979 args.ObjectInstance = ob;
980 OnObjectCreated (args);
982 return args.ObjectInstance;
985 void DisposeObjectInstance (object obj)
987 ObjectDataSourceDisposingEventArgs args = new ObjectDataSourceDisposingEventArgs (obj);
988 OnObjectDisposing (args);
991 IDisposable disp = obj as IDisposable;
992 if (disp != null) disp.Dispose ();
996 object FindValueByName (string name, IDictionary values, bool format)
1001 foreach (DictionaryEntry de in values) {
1002 string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
1003 if (String.Compare (name, valueName, StringComparison.InvariantCultureIgnoreCase) == 0)
1004 return values [de.Key];
1010 /// Merge the current data item fields with view parameter default values
1012 /// <param name="viewParams">default parameters</param>
1013 /// <param name="values">new parameters for update and insert</param>
1014 /// <param name="oldValues">old parameters for update and delete</param>
1015 /// <param name="allwaysAddNewValues">true for insert, as current item is
1016 /// irrelevant for insert</param>
1017 /// <returns>merged values</returns>
1018 IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values, IDictionary oldValues)
1020 IOrderedDictionary parametersValues = viewParams.GetValues (context, owner);
1021 OrderedDictionary mergedValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
1022 foreach (string parameterName in parametersValues.Keys) {
1023 mergedValues [parameterName] = parametersValues [parameterName];
1024 if (oldValues != null) {
1025 object value = FindValueByName (parameterName, oldValues, true);
1026 if (value != null) {
1027 object dataValue = viewParams [parameterName].ConvertValue (value);
1028 mergedValues [parameterName] = dataValue;
1032 if (values != null) {
1033 object value = FindValueByName (parameterName, values, false);
1034 if (value != null) {
1035 object dataValue = viewParams [parameterName].ConvertValue (value);
1036 mergedValues [parameterName] = dataValue;
1041 if (values != null) {
1042 foreach (DictionaryEntry de in values)
1043 if (FindValueByName ((string) de.Key, mergedValues, false) == null)
1044 mergedValues [de.Key] = de.Value;
1047 if (oldValues != null) {
1048 foreach (DictionaryEntry de in oldValues) {
1049 string oldValueKey = FormatOldParameter ((string) de.Key);
1050 if (FindValueByName (oldValueKey, mergedValues, false) == null)
1051 mergedValues [oldValueKey] = de.Value;
1055 return mergedValues;
1058 object[] GetParameterArray (ParameterInfo[] methodParams, IOrderedDictionary viewParams, out ArrayList outParamInfos)
1060 // FIXME: make this case insensitive
1062 outParamInfos = null;
1063 object[] values = new object [methodParams.Length];
1065 foreach (ParameterInfo mp in methodParams) {
1067 // Parameter names must match
1068 if (!viewParams.Contains (mp.Name)) return null;
1070 values [mp.Position] = ConvertParameter (mp.ParameterType, viewParams [mp.Name]);
1071 if (mp.ParameterType.IsByRef) {
1072 if (outParamInfos == null) outParamInfos = new ArrayList ();
1073 outParamInfos.Add (mp);
1079 object ConvertParameterWithTypeConverter (object[] attributes, Type targetType, object value)
1081 if (attributes == null || attributes.Length == 0 || value == null)
1083 TypeConverterAttribute tca;
1085 TypeConverter converter;
1087 foreach (object a in attributes) {
1088 tca = a as TypeConverterAttribute;
1091 converterType = HttpApplication.LoadType (tca.ConverterTypeName, false);
1092 if (converterType == null)
1094 converter = Activator.CreateInstance (converterType, new object[] {targetType}) as TypeConverter;
1095 if (converter == null)
1097 if (converter.CanConvertFrom (value.GetType ()))
1098 return converter.ConvertFrom (value);
1099 else if (converter.CanConvertFrom (typeof (string)))
1100 return converter.ConvertFrom (value.ToString ());
1106 object ConvertParameter (Type targetType, object value)
1108 return ConvertParameter (Type.GetTypeCode (targetType), value);
1111 object ConvertParameter (TypeCode targetType, object value)
1113 if (value == null) {
1114 if (targetType != TypeCode.Object && targetType != TypeCode.String)
1116 else if (ConvertNullToDBNull)
1117 return DBNull.Value;
1119 if (targetType == TypeCode.Object || targetType == TypeCode.Empty)
1122 return Convert.ChangeType (value, targetType);
1125 string FormatOldParameter (string name)
1127 string f = OldValuesParameterFormatString;
1129 return String.Format (f, name);
1134 void OnParametersChanged (object sender, EventArgs args)
1136 OnDataSourceViewChanged (EventArgs.Empty);
1139 protected virtual void LoadViewState (object savedState)
1141 object[] state = (savedState == null) ? new object [5] : (object[]) savedState;
1142 ((IStateManager)SelectParameters).LoadViewState (state[0]);
1143 ((IStateManager)UpdateParameters).LoadViewState (state[1]);
1144 ((IStateManager)DeleteParameters).LoadViewState (state[2]);
1145 ((IStateManager)InsertParameters).LoadViewState (state[3]);
1146 ((IStateManager)FilterParameters).LoadViewState (state[4]);
1149 protected virtual object SaveViewState()
1151 object[] state = new object [5];
1153 if (selectParameters != null)
1154 state [0] = ((IStateManager)selectParameters).SaveViewState ();
1155 if (updateParameters != null)
1156 state [1] = ((IStateManager)updateParameters).SaveViewState ();
1157 if (deleteParameters != null)
1158 state [2] = ((IStateManager)deleteParameters).SaveViewState ();
1159 if (insertParameters != null)
1160 state [3] = ((IStateManager)insertParameters).SaveViewState ();
1161 if (filterParameters != null)
1162 state [4] = ((IStateManager)filterParameters).SaveViewState ();
1164 foreach (object ob in state)
1165 if (ob != null) return state;
1170 protected virtual void TrackViewState()
1172 isTrackingViewState = true;
1174 if (selectParameters != null) ((IStateManager)selectParameters).TrackViewState ();
1175 if (filterParameters != null) ((IStateManager)filterParameters).TrackViewState ();
1178 protected bool IsTrackingViewState
1180 get { return isTrackingViewState; }
1184 bool IStateManager.IsTrackingViewState
1186 get { return IsTrackingViewState; }
1189 void IStateManager.TrackViewState()
1194 void IStateManager.LoadViewState (object savedState)
1196 LoadViewState (savedState);
1199 object IStateManager.SaveViewState()
1201 return SaveViewState ();