@ -21,26 +21,72 @@ namespace ImageSharp.Tests
protected readonly PixelTypes PixelTypes ;
protected ImageDataAttributeBase ( PixelTypes pixelTypes , object [ ] additionalParameters )
protected ImageDataAttributeBase ( string memberName , PixelTypes pixelTypes , object [ ] additionalParameters )
{
this . PixelTypes = pixelTypes ;
this . AdditionalParameters = additionalParameters ;
this . MemberName = memberName ;
}
public string MemberName { get ; private set ; }
public Type MemberType { get ; set ; }
public override IEnumerable < object [ ] > GetData ( MethodInfo testMethod )
{
TypeInfo type = testMethod . GetParameters ( ) . First ( ) . ParameterType . GetTypeInfo ( ) ;
if ( ! type . IsGenericType | | type . GetGenericTypeDefinition ( ) ! = typeof ( TestImageProvider < > ) )
IEnumerable < object [ ] > addedRows = Enumerable . Empty < object [ ] > ( ) ;
if ( ! string . IsNullOrWhiteSpace ( this . MemberName ) )
{
Type type = this . MemberType ? ? testMethod . DeclaringType ;
Func < object > accessor = GetPropertyAccessor ( type ) ? ? GetFieldAccessor ( type ) ; // ?? GetMethodAccessor(type);
if ( accessor ! = null )
{
object obj = accessor ( ) ;
if ( obj is IEnumerable < object > memberItems )
{
addedRows = memberItems . Select ( x = > x as object [ ] ) ;
if ( addedRows . Any ( x = > x = = null ) )
{
throw new ArgumentException ( $"Property {MemberName} on {MemberType ?? testMethod.DeclaringType} yielded an item that is not an object[]" ) ;
}
}
}
}
if ( ! addedRows . Any ( ) )
{
yield return this . AdditionalParameters ;
addedRows = new [ ] { new object [ 0 ] } ;
}
bool firstIsprovider = FirstIsProvider ( testMethod ) ;
IEnumerable < object [ ] > dataItems = Enumerable . Empty < object [ ] > ( ) ;
if ( firstIsprovider )
{
return InnerGetData ( testMethod , addedRows ) ;
}
else
{
foreach ( KeyValuePair < PixelTypes , Type > kv in this . PixelTypes . ExpandAllTypes ( ) )
{
Type factoryType = typeof ( TestImageProvider < > ) . MakeGenericType ( kv . Value ) ;
return addedRows . Select ( x = > x . Concat ( this . AdditionalParameters ) . ToArray ( ) ) ;
}
}
private bool FirstIsProvider ( MethodInfo testMethod )
{
TypeInfo dataType = testMethod . GetParameters ( ) . First ( ) . ParameterType . GetTypeInfo ( ) ;
return dataType . IsGenericType & & dataType . GetGenericTypeDefinition ( ) = = typeof ( TestImageProvider < > ) ;
}
private IEnumerable < object [ ] > InnerGetData ( MethodInfo testMethod , IEnumerable < object [ ] > memberData )
{
foreach ( KeyValuePair < PixelTypes , Type > kv in this . PixelTypes . ExpandAllTypes ( ) )
{
Type factoryType = typeof ( TestImageProvider < > ) . MakeGenericType ( kv . Value ) ;
foreach ( object [ ] originalFacoryMethodArgs in this . GetAllFactoryMethodArgs ( testMethod , factoryType ) )
foreach ( object [ ] originalFacoryMethodArgs in this . GetAllFactoryMethodArgs ( testMethod , factoryType ) )
{
foreach ( object [ ] row in memberData )
{
object [ ] actualFactoryMethodArgs = new object [ originalFacoryMethodArgs . Length + 2 ] ;
Array . Copy ( originalFacoryMethodArgs , actualFactoryMethodArgs , originalFacoryMethodArgs . Length ) ;
@ -50,9 +96,10 @@ namespace ImageSharp.Tests
object factory = factoryType . GetMethod ( this . GetFactoryMethodName ( testMethod ) )
. Invoke ( null , actualFactoryMethodArgs ) ;
object [ ] result = new object [ this . AdditionalParameters . Length + 1 ] ;
object [ ] result = new object [ this . AdditionalParameters . Length + 1 + row . Length ] ;
result [ 0 ] = factory ;
Array . Copy ( this . AdditionalParameters , 0 , result , 1 , this . AdditionalParameters . Length ) ;
Array . Copy ( row , 0 , result , 1 , row . Length ) ;
Array . Copy ( this . AdditionalParameters , 0 , result , 1 + row . Length , this . AdditionalParameters . Length ) ;
yield return result ;
}
}
@ -71,5 +118,56 @@ namespace ImageSharp.Tests
}
protected abstract string GetFactoryMethodName ( MethodInfo testMethod ) ;
Func < object > GetFieldAccessor ( Type type )
{
FieldInfo fieldInfo = null ;
for ( Type reflectionType = type ; reflectionType ! = null ; reflectionType = reflectionType . GetTypeInfo ( ) . BaseType )
{
fieldInfo = reflectionType . GetRuntimeField ( MemberName ) ;
if ( fieldInfo ! = null )
break ;
}
if ( fieldInfo = = null | | ! fieldInfo . IsStatic )
return null ;
return ( ) = > fieldInfo . GetValue ( null ) ;
}
//Func<object> GetMethodAccessor(Type type)
//{
// MethodInfo methodInfo = null;
// var parameterTypes = Parameters == null ? new Type[0] : Parameters.Select(p => p?.GetType()).ToArray();
// for (var reflectionType = type; reflectionType != null; reflectionType = reflectionType.GetTypeInfo().BaseType)
// {
// methodInfo = reflectionType.GetRuntimeMethods()
// .FirstOrDefault(m => m.Name == MemberName && ParameterTypesCompatible(m.GetParameters(), parameterTypes));
// if (methodInfo != null)
// break;
// }
// if (methodInfo == null || !methodInfo.IsStatic)
// return null;
// return () => methodInfo.Invoke(null, Parameters);
//}
Func < object > GetPropertyAccessor ( Type type )
{
PropertyInfo propInfo = null ;
for ( Type reflectionType = type ; reflectionType ! = null ; reflectionType = reflectionType . GetTypeInfo ( ) . BaseType )
{
propInfo = reflectionType . GetRuntimeProperty ( MemberName ) ;
if ( propInfo ! = null )
break ;
}
if ( propInfo = = null | | propInfo . GetMethod = = null | | ! propInfo . GetMethod . IsStatic )
return null ;
return ( ) = > propInfo . GetValue ( null , null ) ;
}
}
}