是否可以为Dapper创建通用的SqlMapper.ITypeHandler?

时间:2016-05-08 19:56:01

标签: c# generics dapper

我有一个非常类似于Nullable的泛型类,名为Optional,它是一个具有一些属性和Value(T)属性的泛型结构。

我已经创建了一个可以处理所有这些类型的SqlMapper.ITypeHandler,但我无法使用SqlMapper.AddTypeHandler(Typeof(Optional<>), new OptionalHandler());向Dapper注册它,因为它会引发异常,更糟糕的是,我看到Dapper使用Dictionary来存储类型转换器使用注册类型作为键,因此它必须是具体类型才能使其工作。

我尝试创建自定义的Type实现并覆盖==运算符和Equals函数,但是当我尝试使用此类SqlMapper.AddTypeHandler(new OpType(), new OptionalHandler());这样的新类型时,它会抛出System.NotSupportedException, the specified method is not compatible

所以问题是,是否有可能为Dapper分配一个ITypeHandler来处理从泛型派生的所有类型?

这是我创建的Type类,如果有人知道如何修复它,它可以是一个很好的答案。

public class OpType : Type
{
    public static Type baseType = typeof(Optional<>);
    public override Assembly Assembly
    {
        get
        {
            return baseType.Assembly;
        }
    }

    public override string AssemblyQualifiedName
    {
        get
        {
            return baseType.AssemblyQualifiedName;
        }
    }

    public override Type BaseType
    {
        get
        {
            return baseType.BaseType;
        }
    }

    public override string FullName
    {
        get
        {
            return baseType.FullName;
        }
    }

    public override Guid GUID
    {
        get
        {
            return baseType.GUID;
        }
    }

    public override Module Module
    {
        get
        {
            return baseType.Module;
        }
    }

    public override string Name
    {
        get
        {
            return baseType.Name;
        }
    }

    public override string Namespace
    {
        get
        {
            return baseType.Namespace;
        }
    }

    public override Type UnderlyingSystemType
    {
        get
        {
            return baseType.UnderlyingSystemType;
        }
    }

    public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr)
    {
        return baseType.GetConstructors(bindingAttr);
    }

    public override object[] GetCustomAttributes(bool inherit)
    {
        return baseType.GetCustomAttributes(inherit);
    }

    public override object[] GetCustomAttributes(Type attributeType, bool inherit)
    {
        return baseType.GetCustomAttributes(attributeType, inherit);
    }

    public override Type GetElementType()
    {
        return baseType.GetElementType();
    }

    public override EventInfo GetEvent(string name, BindingFlags bindingAttr)
    {
        return baseType.GetEvent(name, bindingAttr);
    }

    public override EventInfo[] GetEvents(BindingFlags bindingAttr)
    {
        return baseType.GetEvents(bindingAttr);
    }

    public override FieldInfo GetField(string name, BindingFlags bindingAttr)
    {
        return baseType.GetField(name, bindingAttr);
    }

    public override FieldInfo[] GetFields(BindingFlags bindingAttr)
    {
        return baseType.GetFields(bindingAttr);
    }

    public override Type GetInterface(string name, bool ignoreCase)
    {
        return baseType.GetInterface(name, ignoreCase);
    }

    public override Type[] GetInterfaces()
    {
        return baseType.GetInterfaces();
    }

    public override MemberInfo[] GetMembers(BindingFlags bindingAttr)
    {
        return baseType.GetMembers(bindingAttr);
    }

    public override MethodInfo[] GetMethods(BindingFlags bindingAttr)
    {
        return baseType.GetMethods(bindingAttr);
    }

    public override Type GetNestedType(string name, BindingFlags bindingAttr)
    {
        return baseType.GetNestedType(name, bindingAttr);
    }

    public override Type[] GetNestedTypes(BindingFlags bindingAttr)
    {
        return baseType.GetNestedTypes(bindingAttr);
    }

    public override PropertyInfo[] GetProperties(BindingFlags bindingAttr)
    {
        return baseType.GetProperties(bindingAttr);
    }

    public override object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
    {
        return baseType.InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
    }

    public override bool IsDefined(Type attributeType, bool inherit)
    {
        return IsDefined(attributeType, inherit);
    }

    protected override TypeAttributes GetAttributeFlagsImpl()
    {
        return baseType.Attributes;
    }

    protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
    {
        return baseType.GetConstructor(bindingAttr, binder, callConvention, types, modifiers);
    }

    protected override MethodInfo GetMethodImpl(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
    {
        return baseType.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
    }

    protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
    {
        return baseType.GetProperty(name, bindingAttr, binder, returnType, types, modifiers);
    }

    protected override bool HasElementTypeImpl()
    {
        return HasElementType;
    }

    protected override bool IsArrayImpl()
    {
        return IsArray;
    }

    protected override bool IsByRefImpl()
    {
        return IsByRef;
    }

    protected override bool IsCOMObjectImpl()
    {
        return IsCOMObject;
    }

    protected override bool IsPointerImpl()
    {
        return IsPointer;
    }

    protected override bool IsPrimitiveImpl()
    {
        return IsPrimitive;
    }

    public static bool operator ==(OpType t1, Type t2)
    {

        if (t1 == null && t2 == null) return true;

        if ((t1 == null) ^ (t2 == null)) return false;

        return IsSubclassOfRawGeneric(typeof(Optional<>), t2);
    }

    public static bool operator !=(OpType t1, Type t2)
    {
        return !(t1 == t2);
    }

    public override bool Equals(Type o)
    {
        return IsSubclassOfRawGeneric(typeof(Optional<>), o);
    }

    static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
    {
        while (toCheck != null && toCheck != typeof(object))
        {
            var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
            if (generic == cur)
            {
                return true;
            }
            toCheck = toCheck.BaseType;
        }
        return false;
    }
} 

0 个答案:

没有答案