Using reflection, I'm attempting to find the set of types which inherit from a given base class. It didn't take long to figure out for simple types, but I'm stumped when it comes to generics.
For this piece of code, the first IsAssignableFrom returns true, but the second returns false. And yet, the final assignment compiles just fine.
class class1 { }
class class2 : class1 { }
class generic1<T> { }
class generic2<T> : generic1<T> { }
class Program
{
static void Main(string[] args)
{
Type c1 = typeof(class1);
Type c2 = typeof(class2);
Console.WriteLine("c1.IsAssignableFrom(c2): {0}", c1.IsAssignableFrom(c2));
Type g1 = typeof(generic1<>);
Type g2 = typeof(generic2<>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
generic1<class1> cc = new generic2<class1>();
}
}
So how do I determine at run time whether one generic type definition is derived from another?
From the answer to another question:
public static bool IsAssignableToGenericType(Type givenType, Type genericType)
{
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
{
if (it.IsGenericType && it.GetGenericTypeDefinition() == genericType)
return true;
}
if (givenType.IsGenericType && givenType.GetGenericTypeDefinition() == genericType)
return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return IsAssignableToGenericType(baseType, genericType);
}
The exact code you posted does not return surprising results.
This says "false":
Type g1 = typeof(generic1<>);
Type g2 = typeof(generic2<>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
This says "true":
Type g1 = typeof(generic1<class1>);
Type g2 = typeof(generic2<class1>);
Console.WriteLine("g1.IsAssignableFrom(g2): {0}", g1.IsAssignableFrom(g2));
The difference is that open generic types cannot have instances, so one is not "assignable" to the other.
From the docs:
Returns true if c and the current
Type represent the same type, or if
the current Type is in the
inheritance hierarchy of c, or if
the current Type is an interface
that c implements, or if c is a
generic type parameter and the current
Type represents one of the
constraints of c. false if none of
these conditions are true, or if c
is null.
In this case, clearly none of these conditions are true. And there's an extra note:
A generic type definition is not
assignable from a closed constructed
type. That is, you cannot assign the
closed constructed type
MyGenericList<int> (MyGenericList(Of Integer) in Visual Basic) to a
variable of type MyGenericList<T>.
In the following case use the method Konrad Rudolph provided could be wrong, like: IsAssignableToGenericType(typeof(A), typeof(A<>));// return false
I think here's a better answer
public static bool IsAssignableFrom(Type extendType, Type baseType)
{
while (!baseType.IsAssignableFrom(extendType))
{
if (extendType.Equals(typeof(object)))
{
return false;
}
if (extendType.IsGenericType && !extendType.IsGenericTypeDefinition)
{
extendType = extendType.GetGenericTypeDefinition();
}
else
{
extendType = extendType.BaseType;
}
}
return true;
}
the test case, see Using IsAssignableFrom with C# generics for detail
using System;
/**
* Sam Sha - yCoder.com
*
* */
namespace Test2
{
class MainClass
{
public static void Main (string[] args)
{
string a = "ycoder";
Console.WriteLine(a is object);
A aa = new A();
//Console.WriteLine(aa is A<>);//con't write code like this
typeof(A<>).IsAssignableFrom(aa.GetType());//return false
Trace(typeof(object).IsAssignableFrom(typeof(string)));//true
Trace(typeof(A<>).IsAssignableFrom(typeof(A)));//false
AAA aaa = new AAA();
Trace("Use IsTypeOf:");
Trace(IsTypeOf(aaa, typeof(A<>)));
Trace(IsTypeOf(aaa, typeof(AA)));
Trace(IsTypeOf(aaa, typeof(AAA<>)));
Trace("Use IsAssignableFrom from stackoverflow - not right:");
Trace(IsAssignableFrom(typeof(A), typeof(A<>))); // error
Trace(IsAssignableFrom(typeof(AA), typeof(A<>)));
Trace(IsAssignableFrom(typeof(AAA), typeof(A<>)));
Trace("Use IsAssignableToGenericType:");
Trace(IsAssignableToGenericType(typeof(A), typeof(A<>)));
Trace(IsAssignableToGenericType(typeof(AA), typeof(A<>)));
Trace(IsAssignableToGenericType(typeof(AAA), typeof(A<>)));
}
static void Trace(object log){
Console.WriteLine(log);
}
public static bool IsTypeOf(Object o, Type baseType)
{
if (o == null || baseType == null)
{
return false;
}
bool result = baseType.IsInstanceOfType(o);
if (result)
{
return result;
}
return IsAssignableFrom(o.GetType(), baseType);
}
public static bool IsAssignableFrom(Type extendType, Type baseType)
{
while (!baseType.IsAssignableFrom(extendType))
{
if (extendType.Equals(typeof(object)))
{
return false;
}
if (extendType.IsGenericType && !extendType.IsGenericTypeDefinition)
{
extendType = extendType.GetGenericTypeDefinition();
}
else
{
extendType = extendType.BaseType;
}
}
return true;
}
//from stackoverflow - not good enough
public static bool IsAssignableToGenericType(Type givenType, Type genericType) {
var interfaceTypes = givenType.GetInterfaces();
foreach (var it in interfaceTypes)
if (it.IsGenericType)
if (it.GetGenericTypeDefinition() == genericType) return true;
Type baseType = givenType.BaseType;
if (baseType == null) return false;
return baseType.IsGenericType &&
baseType.GetGenericTypeDefinition() == genericType ||
IsAssignableToGenericType(baseType, genericType);
}
}
class A{}
class AA : A{}
class AAA : AA{}
}
I have a different Approach that resolves this issue, Here are my classes
public class Signal<T>{
protected string Id {get; set;} //This must be here, I use a property because MemberInfo is returned in an array via GetMember() reflection function
//Some Data and Logic And stuff that involves T
}
public class OnClick : Signal<string>{}
Now if I have an instance of type OnClick but I dont know that, and I want to find out if I have an instance of anything which inherits from Signal<> of any type? I do this
Type type = GetTypeWhomISuspectMightBeAGenericSignal();
PropertyInfo secretProperty = type.GetProperty("Id", BindingFlags.NonPublic | BindingFlags.Instance);
Type SpecificGenericType = secretProperty.DeclaringType; //This is the trick
bool IsMyTypeInheriting = SpecificGenericType.IsGenericType && SpecificGenericType.GetGenericTypeDefinition() == typeof(Signal<>); //This way we are getting the genericTypeDefinition and comparing it to any other genericTypeDefinition of the same argument length.
So this works for me, its not recursive, and it uses a trick via a designated property. It has limitations that its hard to write a function that checks assignability for all generics ever. But for a specific type it works
Obviously you need to check if() conditions better and stuff, but these are the Raw lines required to evaluate assignability of a type to its base generic, this way.
Hope this helps
My two cents. IMHO it doesn't make much sense to separate implements, derives or the original functionality of IsAssignableFrom,
Constructing from the answers previously given, this is how I do it:
public static bool ImplementsOrDerives(this Type #this, Type from)
{
if(from is null)
{
return false;
}
else if(!from.IsGenericType)
{
return from.IsAssignableFrom(#this);
}
else if(!from.IsGenericTypeDefinition)
{
return from.IsAssignableFrom(#this);
}
else if(from.IsInterface)
{
foreach(Type #interface in #this.GetInterfaces())
{
if(#interface.IsGenericType && #interface.GetGenericTypeDefinition() == from)
{
return true;
}
}
}
if(#this.IsGenericType && #this.GetGenericTypeDefinition() == from)
{
return true;
}
return #this.BaseType?.ImplementsOrDerives(from) ?? false;
}
You need to compare the contained type. See: How to get the type of T from a member of a generic class or method?
In other words, I think you need to check whether the type being contained by the generic class is assignable rather than the generic class itself.
#konrad_ruldolph's answer is mostly correct, but it requires you to know the base type/interface is an open generic. I propose an improvement that combines a non-generic test with a loop to test for generic match.
public static class Ext
{
public static bool IsAssignableToGeneric(
this Type assignableFrom,
Type assignableTo)
{
bool IsType(Type comparand)
=> assignableTo.IsAssignableFrom(comparand)
|| (comparand.IsGenericType
&& comparand.GetGenericTypeDefinition() == assignableTo);
while (assignableFrom != null)
{
if (IsType(assignableFrom)
|| assignableFrom
.GetInterfaces()
.Any(IsType))
{
return true;
}
assignableFrom = assignableFrom.BaseType;
}
return false;
}
}
Creating an extension method and using link you can do this :
public static bool IsAssignableFromGenericInterface(this Type type, Type genericInterface) => type.GetInterfaces().Any(#interface => #interface.IsAssignableFrom(genericInterface));
I also would like to share my code with you. Here the generic arguments are checked for any compatibility and is working with interfaces.
public static bool IsAssignableToGeneric(this Type sourceType, Type targetType)
{
bool IsAssignable(Type comperand)
{
if (comperand.IsAssignableTo(targetType))
return true;
if (comperand.IsGenericType && targetType.IsGenericType && comperand.GetGenericTypeDefinition() == targetType.GetGenericTypeDefinition())
{
for (int i = 0; i < targetType.GenericTypeArguments.Length; i++)
{
Type comperandArgument = comperand.GenericTypeArguments[i];
Type targetArgument = targetType.GenericTypeArguments[i];
// suggestion for improvement: forward the type check recursivley also here
if (!comperandArgument.IsGenericTypeParameter && !targetArgument.IsGenericTypeParameter && !comperandArgument.IsAssignableTo(targetArgument))
return false;
}
return true;
}
return false;
}
if (IsAssignable(sourceType))
return true;
if (targetType.IsInterface && sourceType.GetInterfaces().Any(IsAssignable))
return true;
return false;
}
I have generic function which returns List of generic type, but in some case I want to return stored list of elements of type A. I got "Cannot implicitly convert type List<A> to List<tableType>":
private List<A> allGroupsHolder = null;
public List<tableType> GetAllObjects<tableType>() where tableType : class
{
if (typeof(tableType) == typeof(Group))
{
if (groupHolderState)
{
groupHolderState = true;
var t = db.GetTable<Group>();
allGroupsHolder = t.ToList();
}
return allGroupsHolder;
}
var table = db.GetTable<tableType>();
return table.ToList();
}
#MarkH and #Blablablaster helped me solve this with comments.
I had to change returned type to IEnumerable and use Cast
private List<A> allGroupsHolder = null;
public IEnumerable<tableType> GetAllObjects<tableType>() where tableType : class
{
if (typeof(tableType) == typeof(Group))
{
if (groupHolderState)
{
groupHolderState = true;
var t = db.GetTable<Group>();
allGroupsHolder = t.ToList();
}
return allGroupsHolder.Cast<tableType>();
}
var table = db.GetTable<tableType>();
return table.ToList();
}
Thank you fellows.
How do you determine if a parameter has a custom attribute attached to it?
I thought this test case would pass:
[TestCase("")]
public void TestParameterAttribute([NotRequired]string theString)
{
var result = false;
foreach (var attribute in theString.GetType().GetCustomAttributes(true))
{
if (attribute.GetType() == (typeof(NotRequiredAttribute)))
{
result = true;
}
}
Assert.That(result, Is.True);
}
It requires a little bit more work.
[TestCase("")]
public void TestParameterAttribute([NotRequired]string theString)
{
var method = MethodInfo.GetCurrentMethod();
var parameter = method.GetParameters()[0];
var result = false;
foreach (var attribute in parameter.GetCustomAttributes(true))
{
if (attribute.GetType() == (typeof(NotRequiredAttribute)))
{
result = true;
}
}
Assert.That(result, Is.True);
}
theString.GetType() gets a reference to the Type representing a string. Calling GetCustomAttributes on it will look in the string class for those attributes.
What you want to do.. is get the attributes for the parameters in the current method. Maybe something like this:
var result = false;
foreach (var parameter in MethodInfo.GetCurrentMethod().GetParameters())
{
if (parameter.GetCustomAttributes().Any(x => x.GetType() == typeof (NotRequiredAttribute)))
result = true;
}
Also you can use Generic version of GetCustomAttribute method:
parameter.GetCustomAttribute<NotRequiredAttribute>() != null
I have an extension method that is working ok to cast string values into various types, which looks something like this:
public static T ToType<T> (this string value, T property)
{
object parsedValue = default(T);
Type type = property.GetType();
try
{
parsedValue = Convert.ChangeType(value, type);
}
catch (ArgumentException e)
{
parsedValue = null;
}
return (T)parsedValue;
}
I'm unhappy about the way this looks when calling the method, however:
myObject.someProperty = stringData.ToType(myObject.someProperty);
Specifying the property just to obtain the property's type seems redundant. I would rather use a signature like this:
public static T ToType<T> (this string value, Type type) { ... }
and have T end up to be the Type of type. This would make calls much cleaner:
myObject.someProperty = stringData.ToType(typeof(decimal));
When I try to call this way, however, the editor complains that the return type of the extension method can't be infered from usage. Can I link T to the Type argument?
What am I missing?
Thanks
Is this what you are looking for? I've added an extra catch for cases where the cast isn't valid also
Decimal i = stringName.ToType<Decimal>();
public static T ToType<T>(this string value)
{
object parsedValue = default(T);
try
{
parsedValue = Convert.ChangeType(value, typeof(T));
}
catch (InvalidCastException)
{
parsedValue = null;
}
catch (ArgumentException)
{
parsedValue = null;
}
return (T)parsedValue;
}
Edit
a shortcut approach to fix Anton's comment
if (typeof(T).IsValueType)
return default(T);
Why use property at all? Just change how you're setting your type variable to the type of your generic.
public static T ToType<T>(this string value)
{
object parsedValue = default(T);
Type type = typeof(T);
try
{
parsedValue = Convert.ChangeType(value, type);
}
catch (ArgumentException e)
{
parsedValue = null;
}
return (T) parsedValue;
}
Usage:
myObject.someProperty = stringData.ToType<decimal>()
I'm using this for a generic conversion:
public bool ConvertTo<T>(object from, out T to) {
to = default(T);
if (from is T) { to = (T)from; return true; }
Type t = typeof(T);
//TypeConverter converter = p.converter == null ? TypeDescriptor.GetConverter(t) : p.converter;
TypeConverter converter = TypeDescriptor.GetConverter(t);
if ((converter != null) && (converter.CanConvertTo(t))) {
try { to = (T)converter.ConvertTo(null, culture, from, t); return true; }
catch { }
}
try { to = (T)Convert.ChangeType(from, t, culture); return true; }
catch { }
return false;
}
public bool ConvertTo(object from, out object to, Type type) {
to = null;
if (from.GetType() == type) { to = from; return true; }
TypeConverter converter = TypeDescriptor.GetConverter(type);
if ((converter != null) && (converter.CanConvertTo(type))) {
try { to = converter.ConvertTo(null, culture, from, type); return true; }
catch { }
}
try { to = Convert.ChangeType(from, type, culture); return true; }
catch { }
return false;
}
Before calling Convert.ChangeType, this checks if there is a TypeConverter for the given variable.
Call it this way:
int i = 123;
string s;
if (ConvertTo<string>(i, out s) {
// use s
}
I need to define a method to compare two different objects of a same type. The type of objects is not specific. The objects may be a DLL type, so I can't override Equals method. I have to do this by reflection. This code works if all the members of objects are of primitive type. But it doesn't work when an object has a field that isn't primitive. How can I do it by reflection?
public bool Equals(object obj1, object obj2)
{
List<FieldInfo> fieldInfos = obj1.GetType().GetFields().ToList();
return (fieldInfos.Select(fieldInfo => new {fieldInfo, type = fieldInfo.GetType()})
.Where(#t => #t.type.IsPrimitive || #t.type == typeof(string) || #t.type == typeof(Decimal))
.Select(#t => #t.fieldInfo)).All(fieldInfo => fieldInfo.GetValue(obj1).Equals(fieldInfo.GetValue(obj2)));
}
I have recently been told about this lib that will do exactly what you are wanting
http://comparenetobjects.codeplex.com/releases/view/47978
I want the utility function to compare any 2 objects. All of the type I want to cover is
Primitive Type
Any class that Implement IEnumerable (Like Dict or List)
Any Class
so I use generic and reflection to do so. I code it like this.
public static bool CompareObjects<T>(T expectInput, T actualInput)
{
// If T is primitive type.
if (typeof(T).IsPrimitive)
{
if (expectInput.Equals(actualInput))
{
return true;
}
return false;
}
if (expectInput is IEquatable<T>)
{
if (expectInput.Equals(actualInput))
{
return true;
}
return false;
}
if (expectInput is IComparable)
{
if (((IComparable)expectInput).CompareTo(actualInput) == 0)
{
return true;
}
return false;
}
// If T is implement IEnumerable.
if (expectInput is IEnumerable)
{
var expectEnumerator = ((IEnumerable)expectInput).GetEnumerator();
var actualEnumerator = ((IEnumerable)actualInput).GetEnumerator();
var canGetExpectMember = expectEnumerator.MoveNext();
var canGetActualMember = actualEnumerator.MoveNext();
while (canGetExpectMember && canGetActualMember && true)
{
var currentType = expectEnumerator.Current.GetType();
object isEqual = typeof(Utils).GetMethod("CompareObjects").MakeGenericMethod(currentType).Invoke(null, new object[] { expectEnumerator.Current, actualEnumerator.Current });
if ((bool)isEqual == false)
{
return false;
}
canGetExpectMember = expectEnumerator.MoveNext();
canGetActualMember = actualEnumerator.MoveNext();
}
if (canGetExpectMember != canGetActualMember)
{
return false;
}
return true;
}
// If T is class.
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
var expectValue = typeof(T).GetProperty(property.Name).GetValue(expectInput);
var actualValue = typeof(T).GetProperty(property.Name).GetValue(actualInput);
if (expectValue == null || actualValue == null)
{
if (expectValue == null && actualValue == null)
{
continue;
}
return false;
}
object isEqual = typeof(Utils).GetMethod("CompareObjects").MakeGenericMethod(property.PropertyType).Invoke(null, new object[] { expectValue, actualValue });
if ((bool)isEqual == false)
{
return false;
}
}
return true;
}