I am trying to cast an object using generic arguments in C# like
(foo<mypara>)obj where the mypara is a generic argument.
public class foo<T>
{
public string name {get;set;}
public func<T> value {get;set;}
}
var mypara = myfoo.GetType().GetGenericArguments();
where the value of mypara.Name is "int" or "string", which is actually a string representation of the type.
But how can I get the real type of mypara?
A code example would be helpful, however I think all you need is obj.GetType()? That is how you get the type of an object.
Use reflection. GetType() on any object will get the name of the type. More reflections are necessary to make it that object type.
You can do it like this:
if (value != null)
{
if (value.GetType().IsGenericType == true
&& value.GetType().GetGenericArguments().Length >= 0)
{
IList _valuesList = null;
if (value.GetType().GetGenericArguments()[0].ToString().ToLower().Contains("int"))
{
_valuesList = value as List<int>;
}
else if (value.GetType().GetGenericArguments()[0].ToString().ToLower().Contains("decimal"))
{
_valuesList = value as List<decimal>;
}
else if (value.GetType().GetGenericArguments()[0].ToString().ToLower().Contains("double"))
{
_valuesList = value as List<double>;
}
else if (value.GetType().GetGenericArguments()[0].ToString().ToLower().Contains("string"))
{
_valuesList = value as List<string>;
}
}
}
Ref:
Get generic instance generic type using reflection
Reflection a properties of type of generic list
Reflection and generic types
Related
I have a class which uses generic properties. For example:
class Person
{
public MyGenericProperty<string> Field1
{
get { return field1; }
set { field1 = value; }
}
private MyGenericProperty<string> field1= new MyInheritedGenericProperty<string>("Alan1");
}
I want to use this class with reflection at another class and i have a method like that
public void DoSomethingWithProperty(object sourceobject)
{
foreach (var aProperty in sourceobject.GetType().GetProperties())
{
*if(aProperty.PropertyType == typeof(MyGenericProperty<>))*
{
*var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);*
}
}
return null;
}
I have two problem
1- How can do type check of generic property. In that example code of if(aProperty.PropertyType == typeof(MyGenericProperty<>)) does not work.
2- T of MyGenericProperty could be any class and how can cast MyGenericProperty class without knowing T by reflection as
var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);
Thank for helps.
Firstly, it's important to understand that you don't have a "generic property" - there's no such thing. You have a property whose type is a generic type... and that's not the same thing. (Compare that with a generic type or a generic method, each of which is genuinely generic in terms of introducing new type parameters.)
You can test it using this code:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
But as for the casting - it depends on what you want to do with the value afterwards. You may want to declare a non-generic base type of MyGenericProperty<> containing all the members which don't depend on the type parameter. I'd typically give that the same name as the generic type (e.g. MyGenericProperty) just without giving it type parameters. Then if you only need one of those members, you can use:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
But then in that case you could use Type.IsAssignableFrom anyway:
if (typeof(MyGenericProperty).IsAssignableFrom(aProperty.PropertyType))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
If these hints don't help you, please give more details of what you're trying to do.
public class MyList : List<MyClass>
How can I get the type MyClass through reflection if I have an object that contains an instance of MyList? The list can be empty, so I can't do something like myList[0].GetType().
p.s. I can't just stop using MyList and directly use the generic List instead (the situation is a bit more complicated, and there are reasons for "hiding" the generic argument), so I can't pick up MyClass through GetGenericArguments().
var elementType = (
from iface in myList.GetType().GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() == typeof(IList<>)
select iface.GetGenericArguments()[0])
.Single();
I use IList<T> instead of list. This is more generic. However, there is also the change of a type implementing multiple ILis<T> versions (such as IList<string> and IList<int>).
You can get the base type, which will be List<MyClass>; from it you can get the generic type argument with GetGenericArguments.
MyList list = new MyList();
Type baseTypeGenericArgument = list.GetType().BaseType.GetGenericArguments()[0];
string argumentTypeName = baseTypeGenericArgument.GetType().FullName;
Is your class implements generic interfaces? you can use the following code:
Type argument = GetGenericArgument(typeof(MyList), typeof(IList<>));
//...
static Type GetGenericArgument(Type type, Type genericTypeDefinition) {
Type[] interfaces = type.GetInterfaces();
for(int i = 0; i < interfaces.Length; i++) {
if(!interfaces[i].IsGenericType) continue;
if(interfaces[i].GetGenericTypeDefinition() == genericTypeDefinition)
return interfaces[i].GetGenericArguments()[0];
}
return null;
}
Without interfaces you can try the following:
class A { }
class B { }
class G<T> { }
class G1<T> : G<A> { }
class G2 : G1<B> { }
//...
Type argument1 = GetGenericArgument(typeof(G2)); // B
Type argument2 = GetGenericArgument(typeof(G2),1 ); // A
//...
static Type GetGenericArgument(Type type, int level = 0) {
do {
if(type.IsGenericType && 0 == level--)
return type.GetGenericArguments()[0];
type = type.BaseType;
}
while(type != null);
return null;
}
In some part of my code I am passed a collection of objects of type T. I don't know which concrete colletion I will be passed, other than it impements IEnumerable.
At run time, I need to find out which type T is (e.g. System.Double, System.String, etc...).
Is there any way to find it out?
UPDATE: I should maybe clarify a bit more the context I am working in (a Linq Provider).
My function has a signature like the following, where I get the type of the collection as a parameter:
string GetSymbolForType(Type collectionType)
{
}
Is there any way from collectionType to get the contained objects type?
From Matt Warren's Blog:
internal static class TypeSystem {
internal static Type GetElementType(Type seqType) {
Type ienum = FindIEnumerable(seqType);
if (ienum == null) return seqType;
return ienum.GetGenericArguments()[0];
}
private static Type FindIEnumerable(Type seqType) {
if (seqType == null || seqType == typeof(string))
return null;
if (seqType.IsArray)
return typeof(IEnumerable<>).MakeGenericType(seqType.GetElementType());
if (seqType.IsGenericType) {
foreach (Type arg in seqType.GetGenericArguments()) {
Type ienum = typeof(IEnumerable<>).MakeGenericType(arg);
if (ienum.IsAssignableFrom(seqType)) {
return ienum;
}
}
}
Type[] ifaces = seqType.GetInterfaces();
if (ifaces != null && ifaces.Length > 0) {
foreach (Type iface in ifaces) {
Type ienum = FindIEnumerable(iface);
if (ienum != null) return ienum;
}
}
if (seqType.BaseType != null && seqType.BaseType != typeof(object)) {
return FindIEnumerable(seqType.BaseType);
}
return null;
}
}
myCollection.GetType().GetGenericArguments()
will return an array of the type args.
Type t = null
foreach(object o in list)
{
o.GetType();
}
will get you the type of the object.
Then you should probably test for your desired types:
if(t == typeof(myClass))
{
dosomething();
}
else if (t == typeof(myOtherClass))
{
dosomethingelse();
}
I use dynamic alot and this is an issue from time to time.
Matt Davis nailed it but you need the index :)
public static void PopulateChildCollection<T>(T currentObject, string singlePropertyName)
{
dynamic currentObjectCollection = ReflectionTools.GetPropertyValue(currentObject, singlePropertyName);
Type collectionType = currentObjectCollection.GetType().GetGenericArguments()[0];
The type will be what you would expect, it is the type of the object contained in the collection and not any of the generic types surrounding it.
Cant you just use t.GetType() to do this.
Why not just implement an IEnumerable<T> instead? EG:
public void MyFunc<T>(IEnumerable<T> objects)
Other than that, you'd be better off checking the type of each individual object using is or .GetType rather than trying to work it out from the container itself.
If that's not an option though and you really need to know the type of the base container you'd basically have to check using is to see what interfaces it implements (EG: IList<int> etc). Odds are the type of your array is going to be a generic which means trying to work back from it's name down to it's data type will be quite messy.
Well I am way way late here but shouldn't this work :
public static bool ThatCollectionIsOfType<T>(IEnumerable<T> collection, Type got)
{
if (**typeof(T)** == got) //this line should be good to go...
{
return true;
}
}
I need to pass a generic type parameter to an interface. I have a string with the name of the type.
I have something like this:
string type = "ClassType";
Type t = Type.GetType("ClassType");
IProvider<t> provider = (IProvider<t>)someObject;
This doesn't work for me. What is the correct way to do it? Thanks.
What' you're trying to do is not really possible in the C# (and CLR) version of generics. When specifying a generic parameter it must be either ...
A Concrete type in code
Another generic parameter
This information must be bound in the metadata of the assembly. There is no way to express a type name from string in metadata in this fashion.
It is possible to bind a generic at runtime based on string names but this requires reflection.
I believe this is what you are looking for =>Type.MakeGenericType
Here is a sample using reflection to load a generic type.
using System;
namespace GenericCastRuntime
{
class Program
{
static void Main(string[] args)
{
string type = "GenericCastRuntime.Program+Provider`1";
Type t = Type.GetType(type);
string genericType = "System.String";
Type gt = Type.GetType(genericType);
var objType = t.MakeGenericType(gt);
var ci = objType.GetConstructor(Type.EmptyTypes);
var obj = ci.Invoke(null);
IProvider provider = obj as IProvider;
}
public class Provider<T> : IProvider<T>
{
public T Value { get; set; }
object IProvider.Value
{
get { return this.Value; }
set
{
if (!(value is T)) throw new InvalidCastException();
this.Value = (T)value;
}
}
}
public interface IProvider { object Value { get; set; } }
public interface IProvider<T> : IProvider { T Value { get; set; } }
}
}
Here's a simple example:
public static object DynamicallyCreateGeneric(Type GenericTypeSource, Type SpecificTypeSource)
{
System.Type SpecificType =
GenericTypeSource.MakeGenericType(
new System.Type[] { SpecificTypeSource }
);
return Activator.CreateInstance(SpecificType);
}
...then, for example:
string type = "System.String";
Type t = Type.GetType(type);
var DynamicallyCreatedGeneric = DynamicallyCreateGeneric(typeof(List<>), t);
System.Diagnostics.Debugger.Break();
Adapt to suit your implementation and to taste. Of course, this method is not ideal. One of the best parts of generics is type compiler level type safety.
I have a class that I want to use to store "properties" for another class. These properties simply have a name and a value. Ideally, what I would like is to be able to add typed properties, so that the "value" returned is always of the type that I want it to be.
The type should always be a primitive. This class subclasses an abstract class which basically stores the name and value as string. The idea being that this subclass will add some type-safety to the base class (as well as saving me on some conversion).
So, I have created a class which is (roughly) this:
public class TypedProperty<DataType> : Property
{
public DataType TypedValue
{
get { // Having problems here! }
set { base.Value = value.ToString();}
}
}
So the question is:
Is there a "generic" way to convert from string back to a primitive?
I can't seem to find any generic interface that links the conversion across the board (something like ITryParsable would have been ideal!).
I am not sure whether I understood your intentions correctly, but let's see if this one helps.
public class TypedProperty<T> : Property where T : IConvertible
{
public T TypedValue
{
get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
set { base.Value = value.ToString();}
}
}
lubos hasko's method fails for nullables. The method below will work for nullables. I didn't come up with it, though. I found it via Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Credit to "Tuna Toksoz"
Usage first:
TConverter.ChangeType<T>(StringValue);
The class is below.
public static class TConverter
{
public static T ChangeType<T>(object value)
{
return (T)ChangeType(typeof(T), value);
}
public static object ChangeType(Type t, object value)
{
TypeConverter tc = TypeDescriptor.GetConverter(t);
return tc.ConvertFrom(value);
}
public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
{
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
For many types (integer, double, DateTime etc), there is a static Parse method. You can invoke it using reflection:
MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );
if (m != null)
{
return m.Invoke(null, new object[] { base.Value });
}
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)
TypeDescriptor is class having method GetConvertor which accept a Type object and then you can call ConvertFrom method to convert the value for that specified object.
With inspiration from the Bob's answer, these extensions also support null value conversion and all primitive conversion back and fourth.
public static class ConversionExtensions
{
public static object Convert(this object value, Type t)
{
Type underlyingType = Nullable.GetUnderlyingType(t);
if (underlyingType != null && value == null)
{
return null;
}
Type basetype = underlyingType == null ? t : underlyingType;
return System.Convert.ChangeType(value, basetype);
}
public static T Convert<T>(this object value)
{
return (T)value.Convert(typeof(T));
}
}
Examples
string stringValue = null;
int? intResult = stringValue.Convert<int?>();
int? intValue = null;
var strResult = intValue.Convert<string>();
You could possibly use a construct such as a traits class. In this way, you would have a parameterised helper class that knows how to convert a string to a value of its own type. Then your getter might look like this:
get { return StringConverter<DataType>.FromString(base.Value); }
Now, I must point out that my experience with parameterised types is limited to C++ and its templates, but I imagine there is some way to do the same sort of thing using C# generics.
Check the static Nullable.GetUnderlyingType.
- If the underlying type is null, then the template parameter is not Nullable, and we can use that type directly
- If the underlying type is not null, then use the underlying type in the conversion.
Seems to work for me:
public object Get( string _toparse, Type _t )
{
// Test for Nullable<T> and return the base type instead:
Type undertype = Nullable.GetUnderlyingType(_t);
Type basetype = undertype == null ? _t : undertype;
return Convert.ChangeType(_toparse, basetype);
}
public T Get<T>(string _key)
{
return (T)Get(_key, typeof(T));
}
public void test()
{
int x = Get<int>("14");
int? nx = Get<Nullable<int>>("14");
}
I used lobos answer and it works. But I had a problem with the conversion of doubles because of the culture settings. So I added
return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
public class TypedProperty<T> : Property
{
public T TypedValue
{
get { return (T)(object)base.Value; }
set { base.Value = value.ToString();}
}
}
I using converting via an object. It is a little bit simpler.
Yet another variation. Handles Nullables, as well as situations where the string is null and T is not nullable.
public class TypedProperty<T> : Property where T : IConvertible
{
public T TypedValue
{
get
{
if (base.Value == null) return default(T);
var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
return (T)Convert.ChangeType(base.Value, type);
}
set { base.Value = value.ToString(); }
}
}
You can do it in one line as below:
YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));
Happy coding ;)