strategy for run-time de-referencing of generic parameter ?
-
edit based on Alan's suggestion below: What I am looking for is a way to convert the Interface (non-generic Interface) instances ... where the instance is a generic Class ... from the Interface instance to the generic Class instance ... using Reflection, rather than using "world-knowldege" of the specifically defined generic Class parameter Types being used at run-time. I think, at this point, since that use-case is pretty much what System.Dynamic enables through late-binding that, perhaps, it's better to go ahead snd use System.Dynamic. ... But, I'm not sure. Remember, if I weren't confused, I would not be here :) ... end edit ... assuming: 1. an Interface which is not generic
public interface ISomeInterface
{
int SomeInt { set; get; }
}2. a Class which is generic which inherits from the Interface
public class SomeClass : ISomeInterface
{
public int SomeInt { set; get; }public T SomeT { set; get; }
public SomeClass(int anint, T somet = default(T))
{
SomeInt = anint;
SomeT = somet;
}
}3. A collection of instances of SomeClass<T> as ISomeInterface
List someInstances = new List();
someInstances.Add(new SomeClass(100, 200));
someInstances.Add(new SomeClass(200, "whoop de doo"));4. at run-time you have a reference to a member of the 'someInstances list:
ISomeInterface reference = someInstances[1];
5. to detect which generic Type 'reference is:
Type t = reference.GetType().GenericTypeArguments[0];
if (t == typeof(string))
{
var refAsString = reference as SomeClass;string whoopee = refAsString.SomeT; // => "whoop de doo"
}
6. is there a better way ... assuming you have a valid need to maintain such a collection of Interface instances and de-reference them into their generic Types at run-time. Notes: 1. I don't really like doing things this way ... using reflection ... but, I do have a case where either I need to do this, or use System.Dynamic to get away with "Type murder" :) 2. I am aware of the use of 'Convert.ChangeType, and its limitations, and I believe it is not usable in this case because you need to know what Type to cast to in order to use it. Of course, when your generic parameter is a complex Type, you can't use the 'ChangType method that relies on 'TypeCode. 3. the code example shown here is, of course, simplified for discussion pu
-
edit based on Alan's suggestion below: What I am looking for is a way to convert the Interface (non-generic Interface) instances ... where the instance is a generic Class ... from the Interface instance to the generic Class instance ... using Reflection, rather than using "world-knowldege" of the specifically defined generic Class parameter Types being used at run-time. I think, at this point, since that use-case is pretty much what System.Dynamic enables through late-binding that, perhaps, it's better to go ahead snd use System.Dynamic. ... But, I'm not sure. Remember, if I weren't confused, I would not be here :) ... end edit ... assuming: 1. an Interface which is not generic
public interface ISomeInterface
{
int SomeInt { set; get; }
}2. a Class which is generic which inherits from the Interface
public class SomeClass : ISomeInterface
{
public int SomeInt { set; get; }public T SomeT { set; get; }
public SomeClass(int anint, T somet = default(T))
{
SomeInt = anint;
SomeT = somet;
}
}3. A collection of instances of SomeClass<T> as ISomeInterface
List someInstances = new List();
someInstances.Add(new SomeClass(100, 200));
someInstances.Add(new SomeClass(200, "whoop de doo"));4. at run-time you have a reference to a member of the 'someInstances list:
ISomeInterface reference = someInstances[1];
5. to detect which generic Type 'reference is:
Type t = reference.GetType().GenericTypeArguments[0];
if (t == typeof(string))
{
var refAsString = reference as SomeClass;string whoopee = refAsString.SomeT; // => "whoop de doo"
}
6. is there a better way ... assuming you have a valid need to maintain such a collection of Interface instances and de-reference them into their generic Types at run-time. Notes: 1. I don't really like doing things this way ... using reflection ... but, I do have a case where either I need to do this, or use System.Dynamic to get away with "Type murder" :) 2. I am aware of the use of 'Convert.ChangeType, and its limitations, and I believe it is not usable in this case because you need to know what Type to cast to in order to use it. Of course, when your generic parameter is a complex Type, you can't use the 'ChangType method that relies on 'TypeCode. 3. the code example shown here is, of course, simplified for discussion pu
I'm not sure I understand the reason for the complexity. The final code fragment shows the use of the 'as' operator to perform a cast, implying that the type is known at compile time. If in fact all types are known then why use reflection at all, just go with is or as.
public void CastingCouch() {
List<ISomeInterface> someInstances = new List<ISomeInterface>();
someInstances.Add(new SomeClass<int>(100, 200));
someInstances.Add(new SomeClass<string>(200, "whoop de doo"));
someInstances.Add(new SomeClass<DateTime>(300, DateTime.Now));foreach (ISomeInterface reference in someInstances) {
Console.Write("{0} ", reference.GetType());if (reference is SomeClass<string>) { Console.WriteLine("String"); } else if (reference is SomeClass<int>) { Console.WriteLine("Int"); } else { Console.WriteLine("Don't know"); }
}
}Alan.
-
I'm not sure I understand the reason for the complexity. The final code fragment shows the use of the 'as' operator to perform a cast, implying that the type is known at compile time. If in fact all types are known then why use reflection at all, just go with is or as.
public void CastingCouch() {
List<ISomeInterface> someInstances = new List<ISomeInterface>();
someInstances.Add(new SomeClass<int>(100, 200));
someInstances.Add(new SomeClass<string>(200, "whoop de doo"));
someInstances.Add(new SomeClass<DateTime>(300, DateTime.Now));foreach (ISomeInterface reference in someInstances) {
Console.Write("{0} ", reference.GetType());if (reference is SomeClass<string>) { Console.WriteLine("String"); } else if (reference is SomeClass<int>) { Console.WriteLine("Int"); } else { Console.WriteLine("Don't know"); }
}
}Alan.
Alan, thanks for your suggestion ! I've edited my question to, I hope, more accurately show what I am looking for. In many cases, what you propose is all that one needs; you could just as well have a Switch statement based on the Type Name to differentialy call whatever code you wanted based on Type at run-time. However, in this case, there may be an unknown variety of instances using different generic Types because a 3rd. party is using the library. And, I am interested in seeing how one would achieve this, at minimal "cost." cheers, Bill
«There is a spectrum, from "clearly desirable behaviour," to "possibly dodgy behavior that still makes some sense," to "clearly undesirable behavior." We try to make the latter into warnings or, better, errors. But stuff that is in the middle category you don’t want to restrict unless there is a clear way to work around it.» Eric Lippert, May 14, 2008
-
edit based on Alan's suggestion below: What I am looking for is a way to convert the Interface (non-generic Interface) instances ... where the instance is a generic Class ... from the Interface instance to the generic Class instance ... using Reflection, rather than using "world-knowldege" of the specifically defined generic Class parameter Types being used at run-time. I think, at this point, since that use-case is pretty much what System.Dynamic enables through late-binding that, perhaps, it's better to go ahead snd use System.Dynamic. ... But, I'm not sure. Remember, if I weren't confused, I would not be here :) ... end edit ... assuming: 1. an Interface which is not generic
public interface ISomeInterface
{
int SomeInt { set; get; }
}2. a Class which is generic which inherits from the Interface
public class SomeClass : ISomeInterface
{
public int SomeInt { set; get; }public T SomeT { set; get; }
public SomeClass(int anint, T somet = default(T))
{
SomeInt = anint;
SomeT = somet;
}
}3. A collection of instances of SomeClass<T> as ISomeInterface
List someInstances = new List();
someInstances.Add(new SomeClass(100, 200));
someInstances.Add(new SomeClass(200, "whoop de doo"));4. at run-time you have a reference to a member of the 'someInstances list:
ISomeInterface reference = someInstances[1];
5. to detect which generic Type 'reference is:
Type t = reference.GetType().GenericTypeArguments[0];
if (t == typeof(string))
{
var refAsString = reference as SomeClass;string whoopee = refAsString.SomeT; // => "whoop de doo"
}
6. is there a better way ... assuming you have a valid need to maintain such a collection of Interface instances and de-reference them into their generic Types at run-time. Notes: 1. I don't really like doing things this way ... using reflection ... but, I do have a case where either I need to do this, or use System.Dynamic to get away with "Type murder" :) 2. I am aware of the use of 'Convert.ChangeType, and its limitations, and I believe it is not usable in this case because you need to know what Type to cast to in order to use it. Of course, when your generic parameter is a complex Type, you can't use the 'ChangType method that relies on 'TypeCode. 3. the code example shown here is, of course, simplified for discussion pu
If you don't have a list of "known" types, how are you planning to use the "dereferenced" type? There's nothing you can cast it to other than
object
, which doesn't really give you anything interesting to play with. Also, you existing code in #5 won't work if someone implements your interface in a different class:class SomeOtherClass : ISomeInterface { ... }
class YetAnotherClass<TKey, TValue> : ISomeInterface { ... }someInstances.Add(new SomeOtherClass(42));
someInstances.Add(new YetAnotherClass<NotTheTypeYoureLookingFor, TheDroids>());You'd need more checks to ensure it's the expected type:
Type referenceType = reference.GetType();
if (referenceType.IsGenericType && referenceType.GetGenericTypeDefinition == typeof(SomeClass<>))
{
// It's a SomeClass<T>:
Type t = referenceType.GetGenericArguments()[0];
...
}
else
{
// It's something else
}
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer