1 // ***********************************************************************
2 // Copyright (c) 2008-2015 Charlie Poole
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 // ***********************************************************************
25 #define NUNIT_FRAMEWORK
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.Reflection;
33 using NUnit.Compatibility;
34 using NUnit.Framework.Interfaces;
35 using NUnit.Framework.Internal;
37 namespace NUnit.Framework
40 /// ValueSourceAttribute indicates the source to be used to
41 /// provide data for one parameter of a test method.
43 [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = false)]
44 public class ValueSourceAttribute : DataAttribute, IParameterDataSource
49 /// Construct with the name of the factory - for use with languages
50 /// that don't support params arrays.
52 /// <param name="sourceName">The name of a static method, property or field that will provide data.</param>
53 public ValueSourceAttribute(string sourceName)
55 SourceName = sourceName;
59 /// Construct with a Type and name - for use with languages
60 /// that don't support params arrays.
62 /// <param name="sourceType">The Type that will provide data</param>
63 /// <param name="sourceName">The name of a static method, property or field that will provide data.</param>
64 public ValueSourceAttribute(Type sourceType, string sourceName)
66 SourceType = sourceType;
67 SourceName = sourceName;
75 /// The name of a the method, property or fiend to be used as a source
77 public string SourceName { get; private set; }
80 /// A Type to be used as a source
82 public Type SourceType { get; private set; }
86 #region IParameterDataSource Members
89 /// Gets an enumeration of data items for use as arguments
90 /// for a test method parameter.
92 /// <param name="parameter">The parameter for which data is needed</param>
94 /// An enumeration containing individual data items
96 public IEnumerable GetData(IParameterInfo parameter)
98 return GetDataSource(parameter);
103 #region Helper Methods
105 private IEnumerable GetDataSource(IParameterInfo parameter)
107 Type sourceType = SourceType ?? parameter.Method.TypeInfo.Type;
110 if (SourceName == null)
111 return Reflect.Construct(sourceType) as IEnumerable;
113 MemberInfo[] members = sourceType.GetMember(SourceName,
114 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
116 var dataSource = GetDataSourceValue(members);
118 if (dataSource == null)
120 ThrowInvalidDataSourceException();
126 private static IEnumerable GetDataSourceValue(MemberInfo[] members)
128 if (members.Length != 1) return null;
130 MemberInfo member = members[0];
132 var field = member as FieldInfo;
136 return (IEnumerable)field.GetValue(null);
138 ThrowInvalidDataSourceException();
141 var property = member as PropertyInfo;
142 if (property != null)
144 if (property.GetGetMethod(true).IsStatic)
145 return (IEnumerable)property.GetValue(null, null);
147 ThrowInvalidDataSourceException();
150 var m = member as MethodInfo;
154 return (IEnumerable)m.Invoke(null, null);
156 ThrowInvalidDataSourceException();
162 private static void ThrowInvalidDataSourceException()
164 throw new InvalidDataSourceException("The sourceName specified on a ValueSourceAttribute must refer to a non null static field, property or method.");