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; }
297 set { conflictDetection = value; }
300 public bool ConvertNullToDBNull {
301 get { return convertNullToDBNull; }
302 set { convertNullToDBNull = value; }
305 public string DataObjectTypeName {
307 return dataObjectTypeName != null ? dataObjectTypeName : string.Empty;
310 dataObjectTypeName = value;
314 public string DeleteMethod {
316 return deleteMethod != null ? deleteMethod : string.Empty;
319 deleteMethod = value;
323 public ParameterCollection DeleteParameters {
325 if (deleteParameters == null) {
326 deleteParameters = new ParameterCollection ();
327 deleteParameters.ParametersChanged += new EventHandler (OnParametersChanged);
329 return deleteParameters;
333 public bool EnablePaging {
338 enablePaging = value;
342 public string FilterExpression {
344 return filterExpression != null ? filterExpression : string.Empty;
347 filterExpression = value;
351 public ParameterCollection FilterParameters {
353 if (filterParameters == null) {
354 filterParameters = new ParameterCollection ();
355 filterParameters.ParametersChanged += new EventHandler (OnParametersChanged);
356 if (IsTrackingViewState)
357 ((IStateManager)filterParameters).TrackViewState ();
359 return filterParameters;
363 public string InsertMethod {
365 return insertMethod != null ? insertMethod : string.Empty;
368 insertMethod = value;
372 public ParameterCollection InsertParameters {
374 if (insertParameters == null) {
375 insertParameters = new ParameterCollection ();
376 insertParameters.ParametersChanged += new EventHandler (OnParametersChanged);
378 return insertParameters;
382 public string MaximumRowsParameterName {
384 return maximumRowsParameterName != null ? maximumRowsParameterName : "maximumRows";
387 maximumRowsParameterName = value;
391 public string OldValuesParameterFormatString {
393 return oldValuesParameterFormatString != null ? oldValuesParameterFormatString : "{0}";
396 oldValuesParameterFormatString = value;
400 public string SelectCountMethod {
402 return selectCountMethod != null ? selectCountMethod : string.Empty;
405 selectCountMethod = value;
409 public string SelectMethod {
411 return selectMethod != null ? selectMethod : string.Empty;
414 selectMethod = value;
418 public ParameterCollection SelectParameters {
420 if (selectParameters == null) {
421 selectParameters = new ParameterCollection ();
422 selectParameters.ParametersChanged += new EventHandler (OnParametersChanged);
423 if (IsTrackingViewState)
424 ((IStateManager)selectParameters).TrackViewState ();
426 return selectParameters;
430 public string SortParameterName {
432 return sortParameterName != null ? sortParameterName : string.Empty;
435 sortParameterName = value;
439 public string StartRowIndexParameterName {
441 return startRowIndexParameterName != null ? startRowIndexParameterName : "startRowIndex";
444 startRowIndexParameterName = value;
448 public string TypeName {
450 return typeName != null ? typeName : string.Empty;
458 public string UpdateMethod {
460 return updateMethod != null ? updateMethod : string.Empty;
463 updateMethod = value;
467 public ParameterCollection UpdateParameters {
469 if (updateParameters == null) {
470 updateParameters = new ParameterCollection ();
471 updateParameters.ParametersChanged += new EventHandler (OnParametersChanged);
473 return updateParameters;
477 private static string PrivateBinPath {
479 if (privateBinPath != null)
480 return privateBinPath;
482 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
483 privateBinPath = Path.Combine (setup.ApplicationBase, setup.PrivateBinPath);
485 return privateBinPath;
489 private Type LoadType (string typeName)
491 Type type = Type.GetType (typeName);
497 if ((tla = BuildManager.TopLevelAssemblies) != null) {
498 foreach (Assembly asm in tla) {
501 type = asm.GetType (typeName);
507 if (!Directory.Exists (PrivateBinPath))
510 string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
511 foreach (string s in binDlls) {
512 Assembly binA = Assembly.LoadFrom (s);
513 type = binA.GetType (typeName);
525 if (objectType == null) {
526 objectType = LoadType (TypeName);
527 if (objectType == null)
528 throw new InvalidOperationException ("Type not found: " + TypeName);
534 Type DataObjectType {
536 if (dataObjectType == null) {
537 dataObjectType = LoadType (DataObjectTypeName);
538 if (objectType == null)
539 throw new InvalidOperationException ("Type not found: " + DataObjectTypeName);
541 return dataObjectType;
545 public IEnumerable Select (DataSourceSelectArguments arguments)
547 return ExecuteSelect (arguments);
550 public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
552 return ExecuteUpdate (keys, values, oldValues);
555 public int Delete (IDictionary keys, IDictionary oldValues)
557 return ExecuteDelete (keys, oldValues);
560 public int Insert (IDictionary values)
562 return ExecuteInsert (values);
565 protected override int ExecuteInsert (IDictionary values)
568 throw new NotSupportedException ("Insert operation not supported.");
570 IOrderedDictionary paramValues;
573 if (DataObjectTypeName.Length == 0) {
574 paramValues = MergeParameterValues (InsertParameters, values, null, true);
575 method = GetObjectMethod (InsertMethod, paramValues, DataObjectMethodType.Insert);
577 method = ResolveDataObjectMethod (InsertMethod, values, null, out paramValues);
580 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
585 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
588 if (rargs.Exception != null && !rargs.ExceptionHandled)
589 throw rargs.Exception;
591 if (owner.EnableCaching)
592 owner.Cache.Expire ();
594 OnDataSourceViewChanged (EventArgs.Empty);
599 protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
602 throw new NotSupportedException ("Delete operation not supported.");
604 if (ConflictDetection == ConflictOptions.CompareAllValues && (oldValues == null || oldValues.Count == 0))
605 throw new InvalidOperationException ("ConflictDetection is set to CompareAllValues and oldValues collection is null or empty.");
607 IDictionary oldDataValues;
608 oldDataValues = BuildOldValuesList (keys, oldValues, false);
610 IOrderedDictionary paramValues;
613 if (DataObjectTypeName.Length == 0) {
614 paramValues = MergeParameterValues (DeleteParameters, null, oldDataValues, true);
615 method = GetObjectMethod (DeleteMethod, paramValues, DataObjectMethodType.Delete);
617 method = ResolveDataObjectMethod (DeleteMethod, oldDataValues, null, out paramValues);
620 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
625 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
629 if (rargs.Exception != null && !rargs.ExceptionHandled)
630 throw rargs.Exception;
632 if (owner.EnableCaching)
633 owner.Cache.Expire ();
635 OnDataSourceViewChanged (EventArgs.Empty);
640 protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
642 IOrderedDictionary paramValues;
645 IDictionary oldDataValues;
646 oldDataValues = BuildOldValuesList (keys, oldValues, true);
648 if (DataObjectTypeName.Length == 0)
650 IDictionary dataValues;
652 paramValues = MergeParameterValues (UpdateParameters, dataValues, oldDataValues, false);
653 method = GetObjectMethod (UpdateMethod, paramValues, DataObjectMethodType.Update);
657 if (ConflictDetection != ConflictOptions.CompareAllValues) {
658 oldDataValues = null;
660 IDictionary dataValues = new Hashtable ();
662 foreach (DictionaryEntry de in keys)
663 dataValues [de.Key] = de.Value;
665 if (values != null) {
666 foreach (DictionaryEntry de in values)
667 dataValues [de.Key] = de.Value;
670 method = ResolveDataObjectMethod (UpdateMethod, dataValues, oldDataValues, out paramValues);
673 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
678 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
681 if (rargs.Exception != null && !rargs.ExceptionHandled)
682 throw rargs.Exception;
684 if (owner.EnableCaching)
685 owner.Cache.Expire ();
687 OnDataSourceViewChanged (EventArgs.Empty);
692 private IDictionary BuildOldValuesList (IDictionary keys, IDictionary oldValues, bool keysWin)
694 IDictionary oldDataValues;
695 if (ConflictDetection == ConflictOptions.CompareAllValues) {
696 oldDataValues = new Hashtable ();
697 if (keys != null && !keysWin) {
698 foreach (DictionaryEntry de in keys)
699 oldDataValues [de.Key] = de.Value;
701 if (oldValues != null) {
702 foreach (DictionaryEntry de in oldValues)
703 oldDataValues [de.Key] = de.Value;
705 if (keys != null && keysWin) {
706 foreach (DictionaryEntry de in keys)
707 oldDataValues [de.Key] = de.Value;
711 oldDataValues = keys;
714 return oldDataValues;
717 protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
719 arguments.RaiseUnsupportedCapabilitiesError (this);
721 IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null, null, true);
722 ObjectDataSourceSelectingEventArgs args = new ObjectDataSourceSelectingEventArgs (paramValues, arguments, false);
724 object result = null;
726 if (owner.EnableCaching)
727 result = owner.Cache.GetCachedObject (SelectMethod, SelectParameters);
729 if (result == null) {
732 return new ArrayList ();
734 if (CanRetrieveTotalRowCount && arguments.RetrieveTotalRowCount)
735 arguments.TotalRowCount = QueryTotalRowCount (paramValues, arguments);
738 if (StartRowIndexParameterName.Length == 0)
739 throw new InvalidOperationException ("Paging is enabled, but the StartRowIndexParameterName property is not set.");
740 if (MaximumRowsParameterName.Length == 0)
741 throw new InvalidOperationException ("Paging is enabled, but the MaximumRowsParameterName property is not set.");
742 paramValues [StartRowIndexParameterName] = arguments.StartRowIndex;
743 paramValues [MaximumRowsParameterName] = arguments.MaximumRows;
746 if (SortParameterName.Length > 0)
747 paramValues [SortParameterName] = arguments.SortExpression;
749 result = InvokeSelect (SelectMethod, paramValues);
751 if (owner.EnableCaching)
752 owner.Cache.SetCachedObject (SelectMethod, SelectParameters, result);
755 if (FilterExpression.Length > 0 && !(result is DataGrid || result is DataView || result is DataTable))
756 throw new NotSupportedException ("The FilterExpression property was set and the Select method does not return a DataSet, DataTable, or DataView.");
758 if (owner.EnableCaching && result is IDataReader)
759 throw new NotSupportedException ("Data source does not support caching objects that implement IDataReader");
761 if (result is DataSet) {
762 DataSet dset = (DataSet) result;
763 if (dset.Tables.Count == 0)
764 throw new InvalidOperationException ("The select method returnet a DataSet which doesn't contain any table.");
765 result = dset.Tables [0];
768 if (result is DataTable) {
769 DataView dview = new DataView ((DataTable)result);
770 if (arguments.SortExpression != null && arguments.SortExpression.Length > 0) {
771 dview.Sort = arguments.SortExpression;
773 if (FilterExpression.Length > 0) {
774 IOrderedDictionary fparams = FilterParameters.GetValues (context, owner);
775 ObjectDataSourceFilteringEventArgs fargs = new ObjectDataSourceFilteringEventArgs (fparams);
778 object[] formatValues = new object [fparams.Count];
779 for (int n=0; n<formatValues.Length; n++) {
780 formatValues [n] = fparams [n];
781 if (formatValues [n] == null) return dview;
783 dview.RowFilter = string.Format (FilterExpression, formatValues);
789 if (result is IEnumerable)
790 return (IEnumerable) result;
792 return new object[] { result };
795 int QueryTotalRowCount (IOrderedDictionary mergedParameters, DataSourceSelectArguments arguments)
797 ObjectDataSourceSelectingEventArgs countArgs = new ObjectDataSourceSelectingEventArgs (mergedParameters, arguments, true);
798 OnSelecting (countArgs);
799 if (countArgs.Cancel)
802 object count = InvokeSelect (SelectCountMethod, mergedParameters);
803 return (int) Convert.ChangeType (count, typeof(int));
806 object InvokeSelect (string methodName, IOrderedDictionary paramValues)
808 MethodInfo method = GetObjectMethod (methodName, paramValues, DataObjectMethodType.Select);
809 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
812 if (rargs.Exception != null && !rargs.ExceptionHandled)
813 throw rargs.Exception;
815 return rargs.ReturnValue;
818 ObjectDataSourceStatusEventArgs InvokeMethod (MethodInfo method, IOrderedDictionary paramValues)
820 object instance = null;
822 if (!method.IsStatic)
823 instance = CreateObjectInstance ();
825 ParameterInfo[] pars = method.GetParameters ();
827 ArrayList outParamInfos;
828 object[] methodArgs = GetParameterArray (pars, paramValues, out outParamInfos);
830 if (methodArgs == null)
831 throw CreateMethodException (method.Name, paramValues);
833 object result = null;
834 Hashtable outParams = null;
837 result = method.Invoke (instance, methodArgs);
838 if (outParamInfos != null) {
839 outParams = new Hashtable ();
840 foreach (ParameterInfo op in outParamInfos)
841 outParams [op.Name] = methodArgs [op.Position];
843 return new ObjectDataSourceStatusEventArgs (result, outParams, null);
845 catch (Exception ex) {
846 return new ObjectDataSourceStatusEventArgs (result, outParams, ex);
849 if (instance != null)
850 DisposeObjectInstance (instance);
854 MethodInfo GetObjectMethod (string methodName, IOrderedDictionary parameters, DataObjectMethodType methodType)
856 MemberInfo[] methods = ObjectType.GetMember (methodName, MemberTypes.Method, BindingFlags.Instance |
857 BindingFlags.Static |
858 BindingFlags.Public |
859 BindingFlags.IgnoreCase |
860 BindingFlags.FlattenHierarchy);
861 if (methods.Length > 1) {
862 // MSDN: The ObjectDataSource resolves method overloads by method name and number
863 // of parameters; the names and types of the parameters are not considered.
864 // LAMESPEC: the tests show otherwise
865 DataObjectMethodAttribute methodAttribute = null;
866 MethodInfo methodInfo = null;
867 bool hasConflict = false;
868 foreach (MethodInfo me in methods) { // we look for methods only
869 ParameterInfo [] pinfos = me.GetParameters ();
870 if (pinfos.Length == parameters.Count) {
871 object [] attrs = me.GetCustomAttributes (typeof (DataObjectMethodAttribute), true);
872 DataObjectMethodAttribute domAttr = (attrs != null && attrs.Length > 0) ? (DataObjectMethodAttribute) attrs [0] : null;
873 if (domAttr != null && domAttr.MethodType != methodType)
876 bool paramsMatch = true;
877 foreach (ParameterInfo pinfo in pinfos) {
878 if (!parameters.Contains (pinfo.Name)) {
887 if (domAttr != null) {
888 if (methodAttribute != null) {
889 if (methodAttribute.IsDefault) {
890 if (domAttr.IsDefault) {
892 break; //fail due to a conflict
895 continue; //existing matches better
898 methodInfo = null; //we override
899 hasConflict = !domAttr.IsDefault;
903 methodInfo = null; //we override
906 if (methodInfo == null) {
907 methodAttribute = domAttr;
916 if (!hasConflict && methodInfo != null)
919 else if (methods.Length == 1) {
920 MethodInfo me = methods[0] as MethodInfo;
921 if (me != null && me.GetParameters().Length == parameters.Count)
925 throw CreateMethodException (methodName, parameters);
928 MethodInfo ResolveDataObjectMethod (string methodName, IDictionary values, IDictionary oldValues, out IOrderedDictionary paramValues)
931 if (oldValues != null)
932 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType, DataObjectType });
934 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType });
937 throw new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters of type '" + DataObjectType + "' in '" + ObjectType + "'.");
939 paramValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
940 ParameterInfo[] ps = method.GetParameters ();
942 if (oldValues != null) {
943 if (FormatOldParameter (ps[0].Name) == ps[1].Name) {
944 paramValues [ps[0].Name] = CreateDataObject (values);
945 paramValues [ps[1].Name] = CreateDataObject (oldValues);
946 } else if (FormatOldParameter (ps[1].Name) == ps[0].Name) {
947 paramValues [ps[0].Name] = CreateDataObject (oldValues);
948 paramValues [ps[1].Name] = CreateDataObject (values);
950 throw new InvalidOperationException ("Method '" + methodName + "' does not have any parameter that fits the value of OldValuesParameterFormatString.");
952 paramValues [ps[0].Name] = CreateDataObject (values);
957 Exception CreateMethodException (string methodName, IOrderedDictionary parameters)
960 foreach (string p in parameters.Keys) {
963 return new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters " + s + "in type '" + ObjectType + "'.");
966 object CreateDataObject (IDictionary values)
968 object ob = Activator.CreateInstance (DataObjectType);
969 foreach (DictionaryEntry de in values) {
970 PropertyInfo p = DataObjectType.GetProperty ((string)de.Key);
971 if (p == null) throw new InvalidOperationException ("Property " + de.Key + " not found in type '" +DataObjectType + "'.");
972 p.SetValue (ob, ConvertParameter (p.PropertyType, de.Value), null);
977 object CreateObjectInstance ()
979 ObjectDataSourceEventArgs args = new ObjectDataSourceEventArgs (null);
980 OnObjectCreating (args);
982 if (args.ObjectInstance != null)
983 return args.ObjectInstance;
985 object ob = Activator.CreateInstance (ObjectType);
987 args.ObjectInstance = ob;
988 OnObjectCreated (args);
990 return args.ObjectInstance;
993 void DisposeObjectInstance (object obj)
995 ObjectDataSourceDisposingEventArgs args = new ObjectDataSourceDisposingEventArgs (obj);
996 OnObjectDisposing (args);
999 IDisposable disp = obj as IDisposable;
1000 if (disp != null) disp.Dispose ();
1004 object FindValueByName (string name, IDictionary values, bool format)
1009 foreach (DictionaryEntry de in values) {
1010 string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
1011 if (name == valueName)
1012 return values [de.Key];
1014 foreach (DictionaryEntry de in values) {
1015 string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
1016 valueName = valueName.ToLower ();
1017 if (name.ToLower () == valueName)
1018 return values [de.Key];
1024 /// Merge the current data item fields with view parameter default values
1026 /// <param name="viewParams">default parameters</param>
1027 /// <param name="values">new parameters for update and insert</param>
1028 /// <param name="oldValues">old parameters for update and delete</param>
1029 /// <param name="allwaysAddNewValues">true for insert, as current item is
1030 /// irrelevant for insert</param>
1031 /// <returns>merged values</returns>
1032 IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values, IDictionary oldValues, bool allwaysAddNewValues)
1034 OrderedDictionary mergedValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
1035 foreach (Parameter p in viewParams) {
1036 bool oldAdded = false;
1037 if (oldValues != null) {
1038 object value = FindValueByName (p.Name, oldValues, true);
1039 if (value != null) {
1040 object dataValue = p.ConvertValue (value);
1041 mergedValues [p.Name] = dataValue;
1046 bool newAdded = false;
1047 if (values != null) {
1048 object value = FindValueByName (p.Name, values, false);
1049 if (value != null) {
1050 object dataValue = p.ConvertValue (value);
1051 mergedValues [p.Name] = dataValue;
1055 if ((!newAdded && !oldAdded) || allwaysAddNewValues) {
1056 object val = p.GetValue (context, owner);
1057 mergedValues [p.Name] = val;
1061 if (values != null) {
1062 foreach (DictionaryEntry de in values)
1063 if (FindValueByName ((string) de.Key, mergedValues, false) == null)
1064 mergedValues [de.Key] = de.Value;
1067 if (oldValues != null) {
1068 foreach (DictionaryEntry de in oldValues)
1069 if (FindValueByName ((string) de.Key, mergedValues, true) == null)
1070 mergedValues [FormatOldParameter ((string) de.Key)] = de.Value;
1073 return mergedValues;
1076 object[] GetParameterArray (ParameterInfo[] methodParams, IOrderedDictionary viewParams, out ArrayList outParamInfos)
1078 // FIXME: make this case insensitive
1080 outParamInfos = null;
1081 object[] values = new object [methodParams.Length];
1082 foreach (ParameterInfo mp in methodParams) {
1084 // Parameter names must match
1085 if (!viewParams.Contains (mp.Name)) return null;
1087 values [mp.Position] = ConvertParameter (mp.ParameterType, viewParams [mp.Name]);
1088 if (mp.ParameterType.IsByRef) {
1089 if (outParamInfos == null) outParamInfos = new ArrayList ();
1090 outParamInfos.Add (mp);
1096 object ConvertParameter (Type targetType, object value)
1098 return ConvertParameter (Type.GetTypeCode (targetType), value);
1101 object ConvertParameter (TypeCode targetType, object value)
1103 if (value == null) {
1104 if (targetType != TypeCode.Object && targetType != TypeCode.String)
1106 else if (ConvertNullToDBNull)
1107 return DBNull.Value;
1109 if (targetType == TypeCode.Object || targetType == TypeCode.Empty)
1112 return Convert.ChangeType (value, targetType);
1115 string FormatOldParameter (string name)
1117 string f = OldValuesParameterFormatString;
1119 return String.Format (f, name);
1124 void OnParametersChanged (object sender, EventArgs args)
1126 OnDataSourceViewChanged (EventArgs.Empty);
1129 protected virtual void LoadViewState (object savedState)
1131 object[] state = (savedState == null) ? new object [5] : (object[]) savedState;
1132 ((IStateManager)SelectParameters).LoadViewState (state[0]);
1133 ((IStateManager)UpdateParameters).LoadViewState (state[1]);
1134 ((IStateManager)DeleteParameters).LoadViewState (state[2]);
1135 ((IStateManager)InsertParameters).LoadViewState (state[3]);
1136 ((IStateManager)FilterParameters).LoadViewState (state[4]);
1139 protected virtual object SaveViewState()
1141 object[] state = new object [5];
1143 if (selectParameters != null)
1144 state [0] = ((IStateManager)selectParameters).SaveViewState ();
1145 if (updateParameters != null)
1146 state [1] = ((IStateManager)updateParameters).SaveViewState ();
1147 if (deleteParameters != null)
1148 state [2] = ((IStateManager)deleteParameters).SaveViewState ();
1149 if (insertParameters != null)
1150 state [3] = ((IStateManager)insertParameters).SaveViewState ();
1151 if (filterParameters != null)
1152 state [4] = ((IStateManager)filterParameters).SaveViewState ();
1154 foreach (object ob in state)
1155 if (ob != null) return state;
1160 protected virtual void TrackViewState()
1162 isTrackingViewState = true;
1164 if (selectParameters != null) ((IStateManager)selectParameters).TrackViewState ();
1165 if (filterParameters != null) ((IStateManager)filterParameters).TrackViewState ();
1168 protected bool IsTrackingViewState
1170 get { return isTrackingViewState; }
1174 bool IStateManager.IsTrackingViewState
1176 get { return IsTrackingViewState; }
1179 void IStateManager.TrackViewState()
1184 void IStateManager.LoadViewState (object savedState)
1186 LoadViewState (savedState);
1189 object IStateManager.SaveViewState()
1191 return SaveViewState ();