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);
496 if ((tla = BuildManager.TopLevelAssemblies) != null) {
497 foreach (Assembly asm in tla) {
500 type = asm.GetType (typeName);
506 if (!Directory.Exists (PrivateBinPath))
509 string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
510 foreach (string s in binDlls) {
511 Assembly binA = Assembly.LoadFrom (s);
512 type = binA.GetType (typeName);
524 if (objectType == null) {
525 objectType = LoadType (TypeName);
526 if (objectType == null)
527 throw new InvalidOperationException ("Type not found: " + TypeName);
533 Type DataObjectType {
535 if (dataObjectType == null) {
536 dataObjectType = LoadType (DataObjectTypeName);
537 if (objectType == null)
538 throw new InvalidOperationException ("Type not found: " + DataObjectTypeName);
540 return dataObjectType;
544 public IEnumerable Select (DataSourceSelectArguments arguments)
546 return ExecuteSelect (arguments);
549 public int Update (IDictionary keys, IDictionary values, IDictionary oldValues)
551 return ExecuteUpdate (keys, values, oldValues);
554 public int Delete (IDictionary keys, IDictionary oldValues)
556 return ExecuteDelete (keys, oldValues);
559 public int Insert (IDictionary values)
561 return ExecuteInsert (values);
564 protected override int ExecuteInsert (IDictionary values)
567 throw new NotSupportedException ("Insert operation not supported.");
569 IOrderedDictionary paramValues;
572 if (DataObjectTypeName.Length == 0) {
573 paramValues = MergeParameterValues (InsertParameters, values, null, true);
574 method = GetObjectMethod (InsertMethod, paramValues, DataObjectMethodType.Insert);
576 method = ResolveDataObjectMethod (InsertMethod, values, null, out paramValues);
579 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
584 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
587 if (rargs.Exception != null && !rargs.ExceptionHandled)
588 throw rargs.Exception;
590 if (owner.EnableCaching)
591 owner.Cache.Expire ();
593 OnDataSourceViewChanged (EventArgs.Empty);
598 protected override int ExecuteDelete (IDictionary keys, IDictionary oldValues)
601 throw new NotSupportedException ("Delete operation not supported.");
603 if (ConflictDetection == ConflictOptions.CompareAllValues && (oldValues == null || oldValues.Count == 0))
604 throw new InvalidOperationException ("ConflictDetection is set to CompareAllValues and oldValues collection is null or empty.");
606 IDictionary oldDataValues;
607 oldDataValues = BuildOldValuesList (keys, oldValues, false);
609 IOrderedDictionary paramValues;
612 if (DataObjectTypeName.Length == 0) {
613 paramValues = MergeParameterValues (DeleteParameters, null, oldDataValues, true);
614 method = GetObjectMethod (DeleteMethod, paramValues, DataObjectMethodType.Delete);
616 method = ResolveDataObjectMethod (DeleteMethod, oldDataValues, null, out paramValues);
619 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
624 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
628 if (rargs.Exception != null && !rargs.ExceptionHandled)
629 throw rargs.Exception;
631 if (owner.EnableCaching)
632 owner.Cache.Expire ();
634 OnDataSourceViewChanged (EventArgs.Empty);
639 protected override int ExecuteUpdate (IDictionary keys, IDictionary values, IDictionary oldValues)
641 IOrderedDictionary paramValues;
644 IDictionary oldDataValues;
645 oldDataValues = BuildOldValuesList (keys, oldValues, true);
647 if (DataObjectTypeName.Length == 0)
649 IDictionary dataValues;
651 paramValues = MergeParameterValues (UpdateParameters, dataValues, oldDataValues, false);
652 method = GetObjectMethod (UpdateMethod, paramValues, DataObjectMethodType.Update);
656 if (ConflictDetection != ConflictOptions.CompareAllValues) {
657 oldDataValues = null;
659 IDictionary dataValues = new Hashtable ();
661 foreach (DictionaryEntry de in keys)
662 dataValues [de.Key] = de.Value;
664 if (values != null) {
665 foreach (DictionaryEntry de in values)
666 dataValues [de.Key] = de.Value;
669 method = ResolveDataObjectMethod (UpdateMethod, dataValues, oldDataValues, out paramValues);
672 ObjectDataSourceMethodEventArgs args = new ObjectDataSourceMethodEventArgs (paramValues);
677 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
680 if (rargs.Exception != null && !rargs.ExceptionHandled)
681 throw rargs.Exception;
683 if (owner.EnableCaching)
684 owner.Cache.Expire ();
686 OnDataSourceViewChanged (EventArgs.Empty);
691 private IDictionary BuildOldValuesList (IDictionary keys, IDictionary oldValues, bool keysWin)
693 IDictionary oldDataValues;
694 if (ConflictDetection == ConflictOptions.CompareAllValues) {
695 oldDataValues = new Hashtable ();
696 if (keys != null && !keysWin) {
697 foreach (DictionaryEntry de in keys)
698 oldDataValues [de.Key] = de.Value;
700 if (oldValues != null) {
701 foreach (DictionaryEntry de in oldValues)
702 oldDataValues [de.Key] = de.Value;
704 if (keys != null && keysWin) {
705 foreach (DictionaryEntry de in keys)
706 oldDataValues [de.Key] = de.Value;
710 oldDataValues = keys;
713 return oldDataValues;
716 protected internal override IEnumerable ExecuteSelect (DataSourceSelectArguments arguments)
718 arguments.RaiseUnsupportedCapabilitiesError (this);
720 IOrderedDictionary paramValues = MergeParameterValues (SelectParameters, null, null, true);
721 ObjectDataSourceSelectingEventArgs args = new ObjectDataSourceSelectingEventArgs (paramValues, arguments, false);
723 object result = null;
725 if (owner.EnableCaching)
726 result = owner.Cache.GetCachedObject (SelectMethod, SelectParameters);
728 if (result == null) {
731 return new ArrayList ();
733 if (CanRetrieveTotalRowCount && arguments.RetrieveTotalRowCount)
734 arguments.TotalRowCount = QueryTotalRowCount (paramValues, arguments);
737 if (StartRowIndexParameterName.Length == 0)
738 throw new InvalidOperationException ("Paging is enabled, but the StartRowIndexParameterName property is not set.");
739 if (MaximumRowsParameterName.Length == 0)
740 throw new InvalidOperationException ("Paging is enabled, but the MaximumRowsParameterName property is not set.");
741 paramValues [StartRowIndexParameterName] = arguments.StartRowIndex;
742 paramValues [MaximumRowsParameterName] = arguments.MaximumRows;
745 if (SortParameterName.Length > 0)
746 paramValues [SortParameterName] = arguments.SortExpression;
748 result = InvokeSelect (SelectMethod, paramValues);
750 if (owner.EnableCaching)
751 owner.Cache.SetCachedObject (SelectMethod, SelectParameters, result);
754 if (FilterExpression.Length > 0 && !(result is DataGrid || result is DataView || result is DataTable))
755 throw new NotSupportedException ("The FilterExpression property was set and the Select method does not return a DataSet, DataTable, or DataView.");
757 if (owner.EnableCaching && result is IDataReader)
758 throw new NotSupportedException ("Data source does not support caching objects that implement IDataReader");
760 if (result is DataSet) {
761 DataSet dset = (DataSet) result;
762 if (dset.Tables.Count == 0)
763 throw new InvalidOperationException ("The select method returnet a DataSet which doesn't contain any table.");
764 result = dset.Tables [0];
767 if (result is DataTable) {
768 DataView dview = new DataView ((DataTable)result);
769 if (arguments.SortExpression != null && arguments.SortExpression.Length > 0) {
770 dview.Sort = arguments.SortExpression;
772 if (FilterExpression.Length > 0) {
773 IOrderedDictionary fparams = FilterParameters.GetValues (context, owner);
774 ObjectDataSourceFilteringEventArgs fargs = new ObjectDataSourceFilteringEventArgs (fparams);
777 object[] formatValues = new object [fparams.Count];
778 for (int n=0; n<formatValues.Length; n++) {
779 formatValues [n] = fparams [n];
780 if (formatValues [n] == null) return dview;
782 dview.RowFilter = string.Format (FilterExpression, formatValues);
788 if (result is IEnumerable)
789 return (IEnumerable) result;
791 return new object[] { result };
794 int QueryTotalRowCount (IOrderedDictionary mergedParameters, DataSourceSelectArguments arguments)
796 ObjectDataSourceSelectingEventArgs countArgs = new ObjectDataSourceSelectingEventArgs (mergedParameters, arguments, true);
797 OnSelecting (countArgs);
798 if (countArgs.Cancel)
801 object count = InvokeSelect (SelectCountMethod, mergedParameters);
802 return (int) Convert.ChangeType (count, typeof(int));
805 object InvokeSelect (string methodName, IOrderedDictionary paramValues)
807 MethodInfo method = GetObjectMethod (methodName, paramValues, DataObjectMethodType.Select);
808 ObjectDataSourceStatusEventArgs rargs = InvokeMethod (method, paramValues);
811 if (rargs.Exception != null && !rargs.ExceptionHandled)
812 throw rargs.Exception;
814 return rargs.ReturnValue;
817 ObjectDataSourceStatusEventArgs InvokeMethod (MethodInfo method, IOrderedDictionary paramValues)
819 object instance = null;
821 if (!method.IsStatic)
822 instance = CreateObjectInstance ();
824 ParameterInfo[] pars = method.GetParameters ();
826 ArrayList outParamInfos;
827 object[] methodArgs = GetParameterArray (pars, paramValues, out outParamInfos);
829 if (methodArgs == null)
830 throw CreateMethodException (method.Name, paramValues);
832 object result = null;
833 Hashtable outParams = null;
836 result = method.Invoke (instance, methodArgs);
837 if (outParamInfos != null) {
838 outParams = new Hashtable ();
839 foreach (ParameterInfo op in outParamInfos)
840 outParams [op.Name] = methodArgs [op.Position];
842 return new ObjectDataSourceStatusEventArgs (result, outParams, null);
844 catch (Exception ex) {
845 return new ObjectDataSourceStatusEventArgs (result, outParams, ex);
848 if (instance != null)
849 DisposeObjectInstance (instance);
853 MethodInfo GetObjectMethod (string methodName, IOrderedDictionary parameters, DataObjectMethodType methodType)
855 MemberInfo[] methods = ObjectType.GetMember (methodName, MemberTypes.Method, BindingFlags.Instance |
856 BindingFlags.Static |
857 BindingFlags.Public |
858 BindingFlags.IgnoreCase |
859 BindingFlags.FlattenHierarchy);
860 if (methods.Length > 1) {
861 // MSDN: The ObjectDataSource resolves method overloads by method name and number
862 // of parameters; the names and types of the parameters are not considered.
863 // LAMESPEC: the tests show otherwise
864 DataObjectMethodAttribute methodAttribute = null;
865 MethodInfo methodInfo = null;
866 bool hasConflict = false;
867 foreach (MethodInfo me in methods) { // we look for methods only
868 ParameterInfo [] pinfos = me.GetParameters ();
869 if (pinfos.Length == parameters.Count) {
870 object [] attrs = me.GetCustomAttributes (typeof (DataObjectMethodAttribute), true);
871 DataObjectMethodAttribute domAttr = (attrs != null && attrs.Length > 0) ? (DataObjectMethodAttribute) attrs [0] : null;
872 if (domAttr != null && domAttr.MethodType != methodType)
875 bool paramsMatch = true;
876 foreach (ParameterInfo pinfo in pinfos) {
877 if (!parameters.Contains (pinfo.Name)) {
886 if (domAttr != null) {
887 if (methodAttribute != null) {
888 if (methodAttribute.IsDefault) {
889 if (domAttr.IsDefault) {
891 break; //fail due to a conflict
894 continue; //existing matches better
897 methodInfo = null; //we override
898 hasConflict = !domAttr.IsDefault;
902 methodInfo = null; //we override
905 if (methodInfo == null) {
906 methodAttribute = domAttr;
915 if (!hasConflict && methodInfo != null)
918 else if (methods.Length == 1) {
919 MethodInfo me = methods[0] as MethodInfo;
920 if (me != null && me.GetParameters().Length == parameters.Count)
924 throw CreateMethodException (methodName, parameters);
927 MethodInfo ResolveDataObjectMethod (string methodName, IDictionary values, IDictionary oldValues, out IOrderedDictionary paramValues)
930 if (oldValues != null)
931 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType, DataObjectType });
933 method = ObjectType.GetMethod (methodName, new Type[] { DataObjectType });
936 throw new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters of type '" + DataObjectType + "' in '" + ObjectType + "'.");
938 paramValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
939 ParameterInfo[] ps = method.GetParameters ();
941 if (oldValues != null) {
942 if (FormatOldParameter (ps[0].Name) == ps[1].Name) {
943 paramValues [ps[0].Name] = CreateDataObject (values);
944 paramValues [ps[1].Name] = CreateDataObject (oldValues);
945 } else if (FormatOldParameter (ps[1].Name) == ps[0].Name) {
946 paramValues [ps[0].Name] = CreateDataObject (oldValues);
947 paramValues [ps[1].Name] = CreateDataObject (values);
949 throw new InvalidOperationException ("Method '" + methodName + "' does not have any parameter that fits the value of OldValuesParameterFormatString.");
951 paramValues [ps[0].Name] = CreateDataObject (values);
956 Exception CreateMethodException (string methodName, IOrderedDictionary parameters)
959 foreach (string p in parameters.Keys) {
962 return new InvalidOperationException ("ObjectDataSource " + owner.ID + " could not find a method named '" + methodName + "' with parameters " + s + "in type '" + ObjectType + "'.");
965 object CreateDataObject (IDictionary values)
967 object ob = Activator.CreateInstance (DataObjectType);
968 foreach (DictionaryEntry de in values) {
969 PropertyInfo p = DataObjectType.GetProperty ((string)de.Key);
970 if (p == null) throw new InvalidOperationException ("Property " + de.Key + " not found in type '" +DataObjectType + "'.");
971 p.SetValue (ob, ConvertParameter (p.PropertyType, de.Value), null);
976 object CreateObjectInstance ()
978 ObjectDataSourceEventArgs args = new ObjectDataSourceEventArgs (null);
979 OnObjectCreating (args);
981 if (args.ObjectInstance != null)
982 return args.ObjectInstance;
984 object ob = Activator.CreateInstance (ObjectType);
986 args.ObjectInstance = ob;
987 OnObjectCreated (args);
989 return args.ObjectInstance;
992 void DisposeObjectInstance (object obj)
994 ObjectDataSourceDisposingEventArgs args = new ObjectDataSourceDisposingEventArgs (obj);
995 OnObjectDisposing (args);
998 IDisposable disp = obj as IDisposable;
999 if (disp != null) disp.Dispose ();
1003 object FindValueByName (string name, IDictionary values, bool format)
1008 foreach (DictionaryEntry de in values) {
1009 string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
1010 if (name == valueName)
1011 return values [de.Key];
1013 foreach (DictionaryEntry de in values) {
1014 string valueName = format == true ? FormatOldParameter (de.Key.ToString ()) : de.Key.ToString ();
1015 valueName = valueName.ToLower ();
1016 if (name.ToLower () == valueName)
1017 return values [de.Key];
1023 /// Merge the current data item fields with view parameter default values
1025 /// <param name="viewParams">default parameters</param>
1026 /// <param name="values">new parameters for update and insert</param>
1027 /// <param name="oldValues">old parameters for update and delete</param>
1028 /// <param name="allwaysAddNewValues">true for insert, as current item is
1029 /// irrelevant for insert</param>
1030 /// <returns>merged values</returns>
1031 IOrderedDictionary MergeParameterValues (ParameterCollection viewParams, IDictionary values, IDictionary oldValues, bool allwaysAddNewValues)
1033 OrderedDictionary mergedValues = new OrderedDictionary (StringComparer.InvariantCultureIgnoreCase);
1034 foreach (Parameter p in viewParams) {
1035 bool oldAdded = false;
1036 if (oldValues != null) {
1037 object value = FindValueByName (p.Name, oldValues, true);
1038 if (value != null) {
1039 object dataValue = p.ConvertValue (value);
1040 mergedValues [p.Name] = dataValue;
1045 bool newAdded = false;
1046 if (values != null) {
1047 object value = FindValueByName (p.Name, values, false);
1048 if (value != null) {
1049 object dataValue = p.ConvertValue (value);
1050 mergedValues [p.Name] = dataValue;
1054 if ((!newAdded && !oldAdded) || allwaysAddNewValues) {
1055 object val = p.GetValue (context, owner);
1056 mergedValues [p.Name] = val;
1060 if (values != null) {
1061 foreach (DictionaryEntry de in values)
1062 if (FindValueByName ((string) de.Key, mergedValues, false) == null)
1063 mergedValues [de.Key] = de.Value;
1066 if (oldValues != null) {
1067 foreach (DictionaryEntry de in oldValues)
1068 if (FindValueByName ((string) de.Key, mergedValues, true) == null)
1069 mergedValues [FormatOldParameter ((string) de.Key)] = de.Value;
1072 return mergedValues;
1075 object[] GetParameterArray (ParameterInfo[] methodParams, IOrderedDictionary viewParams, out ArrayList outParamInfos)
1077 // FIXME: make this case insensitive
1079 outParamInfos = null;
1080 object[] values = new object [methodParams.Length];
1081 foreach (ParameterInfo mp in methodParams) {
1083 // Parameter names must match
1084 if (!viewParams.Contains (mp.Name)) return null;
1086 values [mp.Position] = ConvertParameter (mp.ParameterType, viewParams [mp.Name]);
1087 if (mp.ParameterType.IsByRef) {
1088 if (outParamInfos == null) outParamInfos = new ArrayList ();
1089 outParamInfos.Add (mp);
1095 object ConvertParameter (Type targetType, object value)
1097 return ConvertParameter (Type.GetTypeCode (targetType), value);
1100 object ConvertParameter (TypeCode targetType, object value)
1102 if (value == null) {
1103 if (targetType != TypeCode.Object && targetType != TypeCode.String)
1105 else if (ConvertNullToDBNull)
1106 return DBNull.Value;
1108 if (targetType == TypeCode.Object || targetType == TypeCode.Empty)
1111 return Convert.ChangeType (value, targetType);
1114 string FormatOldParameter (string name)
1116 string f = OldValuesParameterFormatString;
1118 return String.Format (f, name);
1123 void OnParametersChanged (object sender, EventArgs args)
1125 OnDataSourceViewChanged (EventArgs.Empty);
1128 protected virtual void LoadViewState (object savedState)
1130 object[] state = (savedState == null) ? new object [5] : (object[]) savedState;
1131 ((IStateManager)SelectParameters).LoadViewState (state[0]);
1132 ((IStateManager)UpdateParameters).LoadViewState (state[1]);
1133 ((IStateManager)DeleteParameters).LoadViewState (state[2]);
1134 ((IStateManager)InsertParameters).LoadViewState (state[3]);
1135 ((IStateManager)FilterParameters).LoadViewState (state[4]);
1138 protected virtual object SaveViewState()
1140 object[] state = new object [5];
1142 if (selectParameters != null)
1143 state [0] = ((IStateManager)selectParameters).SaveViewState ();
1144 if (updateParameters != null)
1145 state [1] = ((IStateManager)updateParameters).SaveViewState ();
1146 if (deleteParameters != null)
1147 state [2] = ((IStateManager)deleteParameters).SaveViewState ();
1148 if (insertParameters != null)
1149 state [3] = ((IStateManager)insertParameters).SaveViewState ();
1150 if (filterParameters != null)
1151 state [4] = ((IStateManager)filterParameters).SaveViewState ();
1153 foreach (object ob in state)
1154 if (ob != null) return state;
1159 protected virtual void TrackViewState()
1161 isTrackingViewState = true;
1163 if (selectParameters != null) ((IStateManager)selectParameters).TrackViewState ();
1164 if (filterParameters != null) ((IStateManager)filterParameters).TrackViewState ();
1167 protected bool IsTrackingViewState
1169 get { return isTrackingViewState; }
1173 bool IStateManager.IsTrackingViewState
1175 get { return IsTrackingViewState; }
1178 void IStateManager.TrackViewState()
1183 void IStateManager.LoadViewState (object savedState)
1185 LoadViewState (savedState);
1188 object IStateManager.SaveViewState()
1190 return SaveViewState ();