Skip to content
Browse files

- added checking for generic parameter attributes (T must be a class,…

… struct or new() ) in ConversionPatternGenericCloser
  • Loading branch information...
1 parent cb9c1a0 commit 450141d37dae082e54a95b745da42d3406568fc3 @kkozmic committed Jan 29, 2012
Showing with 71 additions and 3 deletions.
  1. +71 −3 src/Cartographer/Compiler/ConversionPatternGenericCloser.cs
View
74 src/Cartographer/Compiler/ConversionPatternGenericCloser.cs
@@ -1,6 +1,8 @@
namespace Cartographer.Compiler
{
using System;
+ using System.Diagnostics;
+ using System.Reflection;
using Cartographer.Internal;
public class ConversionPatternGenericCloser: IConversionPatternGenericCloser
@@ -41,6 +43,72 @@ public Type Close(Type conversionPatternType, Type sourceType, Type targetType)
return null;
}
+ Type EnsureMeetsGenericConstraints(Type type, Type genericParameter)
+ {
+ Debug.Assert(genericParameter.IsGenericParameter, "genericParameter must really be a generic parameter.");
+ var genericConstraints = genericParameter.GenericParameterAttributes;
+ if (genericConstraints == GenericParameterAttributes.None)
+ {
+ return type;
+ }
+ if (genericConstraints.HasFlag(GenericParameterAttributes.NotNullableValueTypeConstraint))
+ {
+ if (IsNotNullableValueType(type) == false)
+ {
+ return null;
+ }
+ }
+ else
+ {
+ // no need to check for default .ctor when we have value type, since we know it'll have one anyway
+ if (genericConstraints.HasFlag(GenericParameterAttributes.DefaultConstructorConstraint))
+ {
+ if (HasDefaultConstructor(type) == false)
+ {
+ return null;
+ }
+ }
+ if (genericConstraints.HasFlag(GenericParameterAttributes.ReferenceTypeConstraint))
+ {
+ if (IsReferenceType(type) == false)
+ {
+ return null;
+ }
+ }
+ }
+ return type;
+ }
+
+ bool HasDefaultConstructor(Type type)
+ {
+ if(type.IsValueType)
+ {
+ return true;
+ }
+
+ var defaultConstructor = type.GetConstructor(Type.EmptyTypes);
+ return defaultConstructor != null;
+ }
+
+ bool IsNotNullableValueType(Type type)
+ {
+ if (type.IsValueType == false)
+ {
+ return false;
+ }
+ if (type.IsGenericType == false)
+ {
+ return true;
+ }
+ var definition = type.GetGenericTypeDefinition();
+ return definition != typeof (Nullable<>);
+ }
+
+ bool IsReferenceType(Type type)
+ {
+ return type.IsValueType == false;
+ }
+
bool TryAddParameters(Type classType, Type interfaceType, Type[] parameters, Type[] openClassArguments)
{
if (interfaceType.ContainsGenericParameters == false)
@@ -73,7 +141,7 @@ bool TryAddParameters(Type classType, Type interfaceType, Type[] parameters, Typ
{
return false;
}
- parameters[index] = classGenericArguments[i];
+ parameters[index] = EnsureMeetsGenericConstraints(classGenericArguments[i], interfaceGenericArguments[i]);
}
}
}
@@ -89,13 +157,13 @@ bool TryAddParameters(Type classType, Type interfaceType, Type[] parameters, Typ
{
return false;
}
- parameters[index] = classArrayItemType;
+ parameters[index] = EnsureMeetsGenericConstraints(classArrayItemType, interfaceArrayItemType);
}
}
}
else
{
- parameters[index] = classType;
+ parameters[index] = EnsureMeetsGenericConstraints(classType, interfaceType);
}
return true;
}

0 comments on commit 450141d

Please sign in to comment.
Something went wrong with that request. Please try again.