10

This is what I am trying to get

(IList<Foo>)listPropertyInfo.GetValue(item)

This is how I get Foo type

listPropertyInfo.GetValue(item).GetType().GenericTypeArguments[0]

This is what I tried but couldn't make it successfully

Convert.ChangeType(listPropertyInfo.GetValue(item), IList<listPropertyInfo.GetValue(item).GetType().GenericTypeArguments[0]>)

and also this;

((typeof(IList<>).MakeGenericType(listPropertyInfo.GetValue(item).GetType().GenericTypeArguments.Single())))(listPropertyInfo.GetValue(item))

this is method where I am trying to implement

public static void trigger(IList<T> result)
{
    foreach (var item in result)
    {
        foreach (var listPropertyInfo in typeof(T).GetProperties().ToList().FindAll(x => x.PropertyType.Name == typeof(IList<>).Name))
        {
             trigger((IList<Foo>)listPropertyInfo.GetValue(item));
        }
    }
}
Mert
  • 6,432
  • 6
  • 32
  • 68
  • 4
    You can make your `IList` type with `var iListFoo = typeof(IList<>).MakeGenericType(somePropertyValue.GetType().GenericTypeArguments.Single())`. However, that's not going to work with `.ChangeType`.. it's not a concrete type to convert to. Not sure what you're trying to do, maybe a wider context of how you need to use it would help. – steve16351 Jun 06 '15 at 16:17
  • I am trying to cast listPropertyInfo.GetValue(item) to iListFoo – Mert Jun 06 '15 at 16:27
  • 2
    Runtime processing of cast to interface is: check if given object implement given interface; if yes, return object unchanged; if no throw exception. So, you just want to check if `listPropertyInfo.GetValue(item)` implement `(IList)`? – user4003407 Jun 06 '15 at 16:30
  • It is PersistentGenericBag and I am trying to cast it whatever its actual type as IList – Mert Jun 06 '15 at 16:33
  • 3
    But `PersistentGenericBag` is already an `IList`. If you had `PersistentGenericBag myFoo = new PersistentGenericBag;` you can just do `IList myiFoo = myFoo;` – steve16351 Jun 06 '15 at 17:10
  • why I can't feed this method with it then? public static void trigger(IList result) { ... } – Mert Jun 06 '15 at 17:11
  • is known at run time, its generic Foo not static – Mert Jun 06 '15 at 17:17
  • @Mert maybe my answer will let you reconsider your program structure – WiiMaxx Jun 11 '15 at 13:00
  • I will check that out asap, thanks for contribute – Mert Jun 11 '15 at 13:18

3 Answers3

3

I solved like this;

IList targetList = (IList)listPropertyInfo.GetValue(item);
Type foo = targetList.GetType().GenericTypeArguments.Single();
Type unboundGenericType = typeof(READ<>);
Type boundGenericType = unboundGenericType.MakeGenericType(foo);
MethodInfo doSomethingMethod = boundGenericType.GetMethod("trigger");
object instance = Activator.CreateInstance(boundGenericType);
doSomethingMethod.Invoke(instance, new object[] { targetList, f, properties });
Mert
  • 6,432
  • 6
  • 32
  • 68
  • so you are trying to call `trigger(IList result)` via `trigger(IList result)` ? but the overload `trigger(IList result)` would be called anyway or is it private? – WiiMaxx Jun 11 '15 at 11:58
  • Its not private, If you have better/easier way to call please share your solution as an answer. – Mert Jun 11 '15 at 12:01
0

If you use IList notation, Foo must be defined at compile time, you can't use expression that evaluates at runtime for Foo.

Denis Yarkovoy
  • 1,277
  • 8
  • 16
  • yeah. I got it when it didn't run successfully. maybe this should be a comment rather than answer. – Mert Jun 06 '15 at 16:04
  • 1
    yes, I was trying to comment, but this is actually my second response on this site and my reputation allows me to comment only on my own messages. Basically I would agree with steve16351 that wider example on how exactly you plan to use the output of Convert.ChangeType could help us/me to post a more helpful response – Denis Yarkovoy Jun 06 '15 at 16:21
  • I don't want to use ChangeType, that was my try. I am trying to cast it – Mert Jun 06 '15 at 16:28
  • 3
    The type of the value returned by listPropertyInfo.GetValue(item) is already a generic type that you are trying to cast to, so the big question is Why you want to cast it to the same type? – Denis Yarkovoy Jun 06 '15 at 16:49
  • because I couldn't convert it to List using ToList() without casting IList first. – Mert Jun 06 '15 at 16:54
  • also I am trying to use it in another generic method which only accepts IList as parameter – Mert Jun 06 '15 at 16:59
  • 3
    Alright, then you can do this. var v=listPropertyInfo.GetValue(item); var typedList=((IList)v).OfType().ToList(); Now typedList will be of type IList, but you still need to know T at compile time – Denis Yarkovoy Jun 06 '15 at 17:10
  • this gives me the type typeof(IList<>).MakeGenericType(somePropertyValue.GetType().GenericTypeArguments‌​.Single()) , but how can I use it in your algorithm – Mert Jun 06 '15 at 17:16
  • 3
    It gives you the type at runtime, you cannot use it at compile time. This brings us to my original answer, it is valid for any casting method that you try to use, whether it is by Convert.ChangeType, direct casting or things like OfType().ToList(). Maybe you could post a code snippet showing why and how exactly you want to use your type – Denis Yarkovoy Jun 06 '15 at 17:23
  • 3
    Have you tried to re-write the line that does recursive call like this: trigger((IList)listPropertyInfo.GetValue(item)); – Denis Yarkovoy Jun 06 '15 at 17:33
  • return type and T isn't same – Mert Jun 06 '15 at 17:36
  • 3
    in the generic metod or class definition stands for "any type", unless explicitely restricted by the "where T: ..." clause. Let's approach from a different end. What happens when you try to complile your code as suggested in my previous comment? Do you get compilation error? What is it? Do you get runtime error? What is it? – Denis Yarkovoy Jun 06 '15 at 17:44
  • IList ? gives runtime error : Cannot cast PersistentGenericBag to IList – Mert Jun 06 '15 at 17:50
  • 1
    What is the relation between the types Foo and Boo? Are they completely different types? Is one assignable from the other? If they are different, then the problem is in the logic (for example, you are trying to cast IList to IList, which is a nonsense). If Foo is derived from Boo, then you are facing covariance issue (http://stackoverflow.com/questions/2184551/difference-between-covariance-contra-variance). Since PersistentGenericBag is not covariantly extending IList, you cannot cast (IList)InstanceOfPersistentGenericBag,although you can do (Animal)InstanceOfCat
    – Denis Yarkovoy Jun 06 '15 at 18:21
  • 1
    So one of the solutions is to move away from specific types in your generics and use PersistentGenericBag, then every time you need to obtain a generic list for the PersistentGenericBag instance, do ((IList)listPropertyInfo.GetValue(item)).OfType().ToList(), and then cast list items to the Foo or Boo type whenever you process them – Denis Yarkovoy Jun 06 '15 at 18:27
  • yes they are completely diffrent types and I am not trying to cast one to another, you asked me to cast it, it was your idea. I meant you it is waste of time, just did it because you asked me to do it. – Mert Jun 06 '15 at 19:27
  • cannot convert from 'System.Collections.Generic.IList' to 'System.Collections.Generic.IList' – Mert Jun 06 '15 at 19:34
0

After reading your comments and and the code i would argue you are trying to do it at the wrong spot.

Here an example of how you could do this

public class MyGeneric<T>
{
    public static void trigger(IList<T> result)
    {
        // do generic stuff where
        // you do not need to know T
    }
}

// this class does only explicit Foo related stuff
public class MyNONEGeneric 
{
    public static void trigger(IList<Foo> list)
    {
         // do some 
    }
}


class Program
{
    static void Main(string[] args)
    {
        PersistentGenericBag<Foo> magicBag = myMagic<Foo>();

         // call your generic which do some general list related stuff
         MyGeneric<Foo>.trigger(list);

         // call your none generic which do some foo related stuff
         MyNONEGeneric.trigger(list);
    }
}

like you can see i did some sort of "separation of concerns" / "single responsibility principle" here. Every thing does only "one" thing. so if you are in need to change something you will know exactly where.

Also if you are working in a Team you can tell Person A to do the MyGeneric<T> and Person B to do the MyNONEGeneric

WiiMaxx
  • 5,322
  • 8
  • 51
  • 89
  • I didn't have chance to test yet but IList this "Foo" shouldn't be static. I am getting Foo type at runtime. – Mert Jun 11 '15 at 13:20
  • mhh ok, and who gives you the Foo? – WiiMaxx Jun 11 '15 at 13:56
  • listPropertyInfo.GetValue(item).GetType().GenericTypeArguments.Single()))) – Mert Jun 11 '15 at 14:03
  • ok then try the following `var mytype = listPropertyInfo.GetValue(item).GetType().GenericTypeArguments.Single()` and then check if mytype == Foo like `if ( mytype == typeof(Foo)) trigger(list.OfType().ToList());` – WiiMaxx Jun 11 '15 at 14:13
  • if `if ( mytype == typeof(Foo))` does not work for you try `if (new Foo() is T)` – WiiMaxx Jun 11 '15 at 14:15
  • Foo is an example, posibile type count is infinite, so we need a generic option here – Mert Jun 11 '15 at 14:16
  • mhh but if T has infinite type count. Why do you have a `trigger(IList list)` which get called via your `trigger(IList result)` ? – WiiMaxx Jun 11 '15 at 14:19
  • I don't have that but only trigger(IList result) – Mert Jun 11 '15 at 14:26