Changed CorrespondingTypeAttribute to allow for multiple types on an enum or a type and updated existing dependencies

pull/10/head
David Hall 2018-01-06 16:38:01 -07:00
parent 9f2d1c1c60
commit 79ba7668c8
3 changed files with 54 additions and 21 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Vanara.Extensions;
// ReSharper disable MemberCanBePrivate.Global
@ -27,13 +28,13 @@ namespace Vanara.InteropServices
/// value to determine the type to get or set.
/// </summary>
/// <seealso cref="System.Attribute"/>
[AttributeUsage(AttributeTargets.Field)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Class, AllowMultiple = true)]
public class CorrespondingTypeAttribute : Attribute
{
/// <summary>Initializes a new instance of the <see cref="CorrespondingTypeAttribute"/> class.</summary>
/// <param name="typeRef">The type that corresponds to this enumeration value.</param>
/// <param name="action">The actions allowed for the type.</param>
public CorrespondingTypeAttribute(Type typeRef, CorrepsondingAction action = CorrepsondingAction.Get | CorrepsondingAction.Set)
public CorrespondingTypeAttribute(Type typeRef, CorrepsondingAction action = CorrepsondingAction.GetSet)
{
TypeRef = typeRef;
Action = action;
@ -54,39 +55,69 @@ namespace Vanara.InteropServices
/// <value>The type that corresponds to this enumeration value.</value>
public Type TypeRef { get; }
/// <summary>Determines whether this instance can get the type for the specified enum value.</summary>
/// <param name="value">The enumeration value.</param>
/// <summary>Determines whether this instance can get the type for the specified enum value or class.</summary>
/// <param name="value">The enumeration value or class instance.</param>
/// <param name="typeRef">The type supplied by the user to validate.</param>
/// <returns><c>true</c> if this instance can get the specified type; otherwise, <c>false</c>.</returns>
public static bool CanGet(object value, Type typeRef)
{
var attr = GetAttrForEnum(value);
return attr.Action.IsFlagSet(CorrepsondingAction.Get) && attr.TypeRef == typeRef;
return GetAttrForObj(value).Any(a => a.Action.IsFlagSet(CorrepsondingAction.Get) && a.TypeRef == typeRef);
}
/// <summary>Determines whether this instance can set the type for the specified enum value.</summary>
/// <param name="value">The enumeration value.</param>
/// <summary>Determines whether this type can get the specified reference type.</summary>
/// <param name="type">The class type.</param>
/// <param name="typeRef">The type supplied by the user to validate.</param>
/// <returns><c>true</c> if this type can get the specified reference type; otherwise, <c>false</c>.</returns>
public static bool CanGet(Type type, Type typeRef)
{
return GetAttrForType(type).Any(a => a.Action.IsFlagSet(CorrepsondingAction.Get) && a.TypeRef == typeRef);
}
/// <summary>Determines whether this instance can set the type for the specified enum value or class.</summary>
/// <param name="value">The enumeration value or class instance.</param>
/// <param name="typeRef">The type supplied by the user to validate.</param>
/// <returns><c>true</c> if this instance can set the specified type; otherwise, <c>false</c>.</returns>
public static bool CanSet(object value, Type typeRef)
{
var attr = GetAttrForEnum(value);
return attr.Action.IsFlagSet(CorrepsondingAction.Set) && attr.TypeRef == typeRef;
return GetAttrForObj(value).Any(a => a.Action.IsFlagSet(CorrepsondingAction.Set) && a.TypeRef == typeRef);
}
/// <summary>Gets the corresponding type for the supplied enumeration value.</summary>
/// <param name="enumValue">The enumeration value.</param>
/// <returns>The type defined by the attribute.</returns>
public static Type GetCorrespondingType(object enumValue) => GetAttrForEnum(enumValue).TypeRef;
/// <summary>Determines whether this type can set the specified reference type.</summary>
/// <param name="type">The class type.</param>
/// <param name="typeRef">The type supplied by the user to validate.</param>
/// <returns><c>true</c> if this type can set the specified reference type; otherwise, <c>false</c>.</returns>
public static bool CanSet(Type type, Type typeRef)
{
return GetAttrForType(type).Any(a => a.Action.IsFlagSet(CorrepsondingAction.Set) && a.TypeRef == typeRef);
}
private static CorrespondingTypeAttribute GetAttrForEnum(object value)
/// <summary>Gets the corresponding types for the supplied enumeration value.</summary>
/// <param name="enumValue">The enumeration value or class.</param>
/// <returns>The types defined by the attribute.</returns>
public static IEnumerable<Type> GetCorrespondingTypes(object enumValue) => GetAttrForObj(enumValue).Select(a => a.TypeRef);
/// <summary>Gets the corresponding types for the supplied enumeration value.</summary>
/// <param name="enumValue">The enumeration value or class.</param>
/// <returns>The types defined by the attribute.</returns>
public static IEnumerable<Type> GetCorrespondingTypes(Type type) => GetAttrForType(type).Select(a => a.TypeRef);
private static IEnumerable<CorrespondingTypeAttribute> GetAttrForObj(object value)
{
if (value == null) throw new ArgumentNullException(nameof(value));
var valueType = value.GetType();
if (!valueType.IsEnum) throw new ArgumentException("Value must be an enumeration value.", nameof(value));
var attr = valueType.GetField(value.ToString()).GetCustomAttributes(typeof(CorrespondingTypeAttribute), false).Cast<CorrespondingTypeAttribute>().FirstOrDefault();
if (attr == null) throw new InvalidOperationException("Value must have the CorrespondingTypeAttribute defined.");
if (attr.Action == CorrepsondingAction.Exception) throw new Exception();
if (!valueType.IsEnum && !valueType.IsClass) throw new ArgumentException("Value must be an enumeration or class value.", nameof(value));
var attr = (valueType.IsEnum ? valueType.GetField(value.ToString()).GetCustomAttributes(typeof(CorrespondingTypeAttribute), false) : valueType.GetCustomAttributes(typeof(CorrespondingTypeAttribute), false)).Cast<CorrespondingTypeAttribute>().ToArray();
if (attr == null || attr.Length == 0) throw new InvalidOperationException("Value must have the CorrespondingTypeAttribute defined.");
if (attr.Any(a => a.Action == CorrepsondingAction.Exception)) throw new Exception();
return attr;
}
private static IEnumerable<CorrespondingTypeAttribute> GetAttrForType(Type type)
{
if (type == null) throw new ArgumentNullException(nameof(type));
var attr = type.GetCustomAttributes(typeof(CorrespondingTypeAttribute), false).Cast<CorrespondingTypeAttribute>().ToArray();
if (attr == null || attr.Length == 0) throw new InvalidOperationException("Type must have the CorrespondingTypeAttribute defined.");
if (attr.Any(a => a.Action == CorrepsondingAction.Exception)) throw new Exception();
return attr;
}
}

View File

@ -1,5 +1,6 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Text;
@ -926,7 +927,7 @@ namespace Vanara.PInvoke
/// </param>
public T GetInfo<T>(TOKEN_INFORMATION_CLASS tokenInfoClass)
{
if (CorrespondingTypeAttribute.GetCorrespondingType(tokenInfoClass) != typeof(T))
if (CorrespondingTypeAttribute.GetCorrespondingTypes(tokenInfoClass).FirstOrDefault() != typeof(T))
throw new InvalidCastException();
using (var pType = GetInfo(tokenInfoClass))
{

View File

@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Vanara.InteropServices;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
@ -1399,7 +1400,7 @@ namespace Vanara.PInvoke
/// <param name="option">Internet option to be set. This can be one of the Option Flags values.</param>
public static void InternetSetOption(this SafeInternetHandle hInternet, InternetOptionFlags option)
{
if (CorrespondingTypeAttribute.GetCorrespondingType(option) != null) throw new ArgumentException($"{option} cannot be used to set options that do not require a value.");
if (CorrespondingTypeAttribute.GetCorrespondingTypes(option).FirstOrDefault() != null) throw new ArgumentException($"{option} cannot be used to set options that do not require a value.");
var res = InternetSetOption(hInternet, option, IntPtr.Zero, 0);
if (!res) Win32Error.ThrowLastError();
}