cast with a Type variable - c#

The below code won't work, I wanted to know how I can dynamically cast an instance to a type determined at runtime?
Convert.ChangeType() returns an Object that still needs to be cast. So does all attempts to Invoke() a GetConstructor() or Activator.CreateInstance(), see below. At some point I need to explicitly cast in code, I'm hoping to avoid it or push it out as far as possible.
Type type = Type.GetType ("RandomChildClass");
Object obj = Activator.CreateInstance (type, new Object[]{ "argument" });
var instance = (type)obj;
I know I can create a method to accept < T >, but I'd still have the same problem of not knowing how to call it with a dynamic random type
Casting a variable using a Type variable

It is not possible to use a Type value to determine the type of an expression. (Generics type parameters are different than values as they are codified into the type-system.)
The value of the variable is from the run-time code execution, while the expression type is a compile-time construct. Needless to say, the compilation occurs before the code ever runs so using a variable for a cast is impossible.
Reflection (albiet unwieldy) or dynamic (which is basically easier-to-use-reflection) allow invoking arbitrary methods or accessing properties/fields against a generic object-typed expression - this is occasionally refered to as "late binding". However, the type of the expression upon which operations is invoked is still object.
Interfaces can be used to unify disparate class implementations for proper static typing. The newly created object can then cast to the applicable interface(s) are required. Just like with other expressions, the type is a compile-time construct (and as such the interface must be directly specified), but the code is now free from a particular class.
If creating a system such that these "dynamic classes" are to be used directly in statically typed (C#) code, and the interfaces can be guaranteed or are constrained to a small set, then using interfaces is likely the cleanest approach: e.g. var myAction = (IMyAction)obj. Otherwise, fall back to dynamic access - direct or behind a facade.

Define your variable as dynamic and it should work, I mean still you can't cast it but you can access your methods:
dynamic obj = Activator.CreateInstance (type, new Object[]{ "argument" });
For example:

Based on your comment you are trying to add it to a List<SomeDynamicClass>. My first thought is that if you can't statically access SomeDynamicClass then I'm curious how, or why, you have a List<SomeDynamicClass>. It sounds like the code would be much better off with List<object> or List<dynamic> instead.
If you are constrained to List<SomeDynamicClass> then it sounds like you should just jump directly to using reflection to call the Add method
var listType = theList.GetType();
var method = listType.GetMethod("Add");
method.Invoke(theList, obj);

If you statically know the type of the base class, cast to that type. For example:
void AddToList(List<Control> list, string typeName) {
var control = (Control)Activator.CreateInstance(typeName);
list.Add(control);
}
Then
var list = new List<Control>();
AddToList(list, "Button"):
AddToList(list, "Label"):
AddToList(list, "ListBox"):
If you need to do something type-specific later, you can test the type and cast:
foreach (Control child in list)
DoSomethingWithThe(control);
void DoSomethingWithThe(Control control)
{
Button button = control as Button;
if (button != null)
{
button.Click += Button_Click;
return;
}
Label label = control as Label;
if (label != null)
{
label.MouseOver += Label_MouseOver;
return;
}
//... etc.
}
Or use the OfType method:
foreach (Button button in list.OfType<Button>())
button.Click += Button_Click;
foreach (Label label in list.OfType<Label>())
label.MouseOver += Label_MouseOver;
You can also use reflection, but that's fairly cumbersome so I won't give an example. Reflection would be useful if you have a property with the same name that's defined on different subtypes of the base type, but not on the base type. If there are many subtypes, the type checking would get cumbersome, so reflection might be a better approach.

Related

C# how to cast object to runtime type?

How can I cast (or convert, if cast not possible or reasonable) an object into its runtime type? I can get runtimeType using reflection, but can't figure out how to get List<string> using property.GetValue - I know that I could explicitly do as List<String> but this is for a sort-of soft-code engine where the types are not known until runtime.
Any help is appreciated - thanks! (but looking for code solutions please, not "you shouldn't do it this way..." answers)
// trimmed-down example class
class Bus { public List<string> Passengers {get;set;} }
// create new instance of class
var obj = new Bus();
// get property value using reflection
var listPropertyName = "Passengers";
var property = GetType(obj).GetProperty($"{listPropertyName}");
var runtimeType = property.PropertyType;
// returns object, but I want List<string> instead
// (or whatever it is; could be different types like T, List<T>, etc.)
var val = property.GetValue(obj);
// doesn't work (assigns null), expects compile-time type
var val = property.GetValue(obj) as runtimeType;
TL;DR
You can't cast something to an unknown type specified at runtime. That would mean that within your code, you don't know what the object's properties or methods are unless you use even more reflection. In that case what would be the point of casting it?
Sometimes we deal with types that aren't known until runtime. But unless the type really doesn't matter at all, the object is useless unless we can cast it to some predetermined type that is specified in our code, not at runtime.
In this line of code:
var val = property.GetValue(obj);
the declared type of val is inferred by the compiler. That type is object because that's the type that GetValue returns. The actual type of the object could be string, int, List<Foo>, whatever. But you've got a variable val of type object.
If you could do this:
var val = property.GetValue(obj) as runtimeType;
Then what would the compile-time type of val be? How can it have any, since runTimeType is a runtime value? The object is useless unless you can call methods or inspect its properties. But you can't do that without knowing the type, unless you use more reflection. But if your're going to do that then there's no point in casting it.
Somewhere downstream from the code you've posted you'll presumably want to actually do something with the object that involves its methods or properties. That means knowing what type you think it is and casting it as that type. That would be a type specified in your code, not something determined at runtime.
For example:
var val = property.GetValue(obj); // I know this is a string
var myString = (string)val;
var findX = myString.IndexOf("X");
I think it's a string so I cast it as a string. (There could be additional checks in there.) Now that I've cast it, I've got a variable that's declared as type string, and I can use it as a string. (Unless it wasn't a string - then it will throw a runtime exception.)
That's the benefit of casting - it allows us to assign something to a strongly-typed variable with a type we specify and then use it accordingly. Casting to an unknown type wouldn't benefit us.
At the risk of adding confusion: Someone could say that generics represent types unspecified at runtime, but that's not exactly true. List<T> doesn't specify what T is, but if you create a List<T>, somehow, somewhere you're going to specify the type in your code. In the vast majority of normal scenarios we have to know something about the type of an object or else the object is useless to us.

Cast dynamic to var

I have following code:
public class Processor
{
private Query _query =
new SpecificQuery1();
//OR
//new SpecificQuery2();
public void ProcessItem(dynamic dynamicResult)
{
//Can't use intellisense on dynamicResult
var staticResult = dynamicResult as _query.GetSomeType();//Can't do it :(
//Can use intellisense on staticResult
}
}
and, surprisingly, it doesn't compile. Is there any way I could cast dynamic into var? I know it sounds insane, but this part will be edited a lot and if someone changes the QueryImplementation, he has to also change type in ProcessItem(). I want to reduce the number of steps to 1 - simply replace the SpecificQuery() and the type will change by itself.
So let me rephrase. I'd like to know if there is some way how to use intellisense on dynamicResult(or some of it's cast) based on which constructor is assigned to base class Query.
Thanks
EDIT :
I'm sorry, I probably asked incorrectly. I understand what is dynamic and var.
I didn't intent to use intellisense on dynamic.
I didn't intent to really cast dynamic to var.
What I wanted to say is, that if I have compile-time knowledge of what type the dynamic will be (it is stored in Query implementation - it can be static, const whatever I want) - is there any way I can use this knowledge to enable intellisense in ProcessItem()?
The var contextual keyword is just syntactic sugar. There is no need to "cast" anything to it, as the variable declared with it is already strongly typed.
If the type of the result of the function is dynamic, so will the variable declared with var.
staticResult is of type dynamic:
var staticResult = dynamicResult;
You can't get intellisense on a dynamic type. If you know the type that you will get, then cast to it - that will give you access to intellisense.
var staticResult = (myType)dynamicResult;
Note that the above can easily cause runtime errors and exceptions that will crash the process.
Please see this SO answer which explains the difference between var and dynamic in detail, in light of your question you should know that the compiler will know the type of var at compile time whereas dynamic can only be determined at runtime; hence, you can't assign a type casted from dynamic (to be determined at runtime) to var (to be determined at compile time).
So, why not keep it dynamic?
No, you cannot do anything like that.
To begin with, you cannot cast something to var since var is not a type. Furthermore, casting can only be done to a type that is statically known; this means that the type you are casting to must be hardcoded, and cannot be the result of evaluating an expression (such as the method call _query.GetSomeType() in your example).
you could implement somethong like
public abstract class AbstractQuery
{
AbstractQuery Create(dynamic result);
}
public class SpecificQuery1 : AbstractQuery
{
new public SpecificQuery1 Create(dynamic result)
{
...
}
}
public void ProcessItem(dynamic dynamicResult)
{
var staticResult = _query.Create(dynamicResult);
}
to convert from a dynamic to a typed result

How do create a Generic Object using Reflection

First let me say, that what I want to do is get the value of a property in a generic class that may be overriden by class that inherits from it. Think of it in the base class as a default value, that the inheritor of the class can override to set their own Default value.
I have tried to use reflection directly on the type, using the System.Reflection.FieldInfo.GetValue but this does not work for classes with generic types. So I think that I need to instantiate the class to be able to see what the value is.
The "types" I have I retrieved by reading the Dlls in the bin and using Reflection to find the types that inherit from my interface.
I am using .NET 4.5
here is documentation that seems like it explains exactly what I need to do
http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx
In this documentation the only difference I can see is how we got our types, I looked in the bin for types and they simply called typeof(), Since types are so complex it seems this may be a likely mis-match but I cannot see what is missing(if anything)
foreach (var item in types)
{
var ts = item.GetField("DefaultTimeToExpire");
Type[] typeArguments = item.GetGenericArguments();
if (ts != null)
{
var t = item.MakeGenericType(typeArguments);
var obj = Activator.CreateInstance(t);
var timespan = obj.DefaultTimeToExpire;
subscriberInfos.Add(new Tuple<string, Type, TimeSpan>(item.Name, item, timespan));
}
}
I am calling GetField to look for Items that have a field "DefaultTimeToExpire" so far this part works well to find the type I need.
Next I call GetGenericArguments which returns an expected array of the type Arguments.
then I call MakeGenericType
and finally Create instance wich gives me the error message
"Cannot create an instance of BusinessLogic.TestSubscriberXXX`1[Message] because Type.ContainsGenericParameters is true."
This looks like exactly what I am supposed to do.
Thanks
In order to instantiate a generic type, you need to know the actual values (types) that should be substituted for its type parameters. The GetGenericArguments() method, being a form of reflection, only gives you the type arguments, not their actual values. The values are up to you... that is the entire point of generics.
If item is a type like List<T> then item.GetGenericArguments() will return an array containing a fake "type" representing the type parameter T (with its IsGenericParameter property set to true). Therefore, passing that parameter type back into item.MakeGenericType() will simply create another open generic type equivalent to the original. To close the generic type so that it can be instantiated you need to provide an actual (non-parameter) type argument, such as int.
For example, typeof(List<>).MakeGenericType(typeof(int)) will return typeof(List<int>), while typeof(List<>).MakeGenericType(typeof(List<>).GetGenericArguments()) will simply return typeof(List<>) again. This is what is happening in your code.
I'm sorry if that is a bit opaque, I don't know how else to explain it. The bottom line is that a type like List<T> is only useful if you have a type you want to substitute in place of T.

Variable of indeterminate type

I have a class that contains a variable of indeterminate type, which must be overridden at runtime, how can I do this?
Sorry for the disgusting question(
Example:
public class MyClass
{
public e_Type TypeValue;
public (variable of indeterminate type) Value;
}
public enum e_Type
{
string, int, bool, byte
}
At runtime variable TypeValue should determine the type of variable Value
Depending on what you actually mean, you should use either var or dynamic.
The var keyword simply lets the compiler take care of deciding which type you are actually using. If the data you will be assigning is truly dynamic during runtime, it won't do you much good. You should mostly look at var as syntactic sugar (even if it at times can be very, very helpful sugar) - i.e. it just saves you typing.
The dynamic keyword lets you create an object that is truly dynamic, that is you will not get a compiler or runtime error no matter what you try to assign to it. The runtime errors will happen later down the road when you try to call on a property that doesn't exist on it. This is essentially you telling the compiler "Hey, look, just don't give me any fuss about this object, allow me to assign anything to it and call anything on it. If I mess up, it's my problem, not yours."
I think whenever you are thinking about using dynamic you should consider the problem at hand and see if it can be solved in a better way (interfaces, generics etc).
It sounds like you're really after generics:
class Foo<T>
{
public T Value { get; set; };
}
Then you can create instances for different types:
Foo<string> x = new Foo<string>();
x.Value = "fred";
Foo<int> y = new Foo<int>();
y.Value = 10;
This is still fixing the type at compile-time - but when the code using the type is compiled.
var is completely wrong here - var is just used for implicitly typed local variables. In particular, you can't apply it to fields.
It's possible that you want dynamic, but it's not really clear from your question at the moment.
I know that this must be done using the keyword var
Nope, that isn't what var does. There are 3 things that leap to mind that would work:
object; can store anything, but requires reflection to do anything useful
dynamic; a special-case of object, where the compiler performs voodoo such that obj.SomeMethod() (etc) is resolved at runtime
generics, i.e. have the class be SomeType<T>, with the variable typed as T; generic constraints can make this T more usable by declaring features (interfaces) that it must have
var has the purpose of referencing anything, not to declare anything. It's the other way around.
I acomplished this once leveraging the System.Dynamic.ExpandoObject (C# 4 only!), it allows for properties to be added at will without declaring them, and they will be resolved at runtime (it resembles how PHP treats objects and I'm a huge fan of it).
A quick example:
dynamic myObject = new ExpandoObject();
myObject.myProperty = "You can declare properties on-the-fly inside me !";
Console.WriteLine(myObject.myProperty);

Determining the expected type of a DynamicObject member access

Is it possible to determine what type a dynamic member access expects? I've tried
dynamic foo = new MyDynamicObject();
int x = foo.IntValue;
int y = (int)foo.IntValue;
And in the TryGetMember intercept GetMemberBinder.ReturnType is object either way. I also implemented TryConvert wondering if it might get invoked to do the conversion, but it never is hit.
Is there some other override I'm missing that lets me determine what Type the caller wants so that I can do the appropriate conversion?
In C#, when using dynamic, the compiler always sets the binder to return type of object, and then does a second dynamic implicit conversion to the expected return type. So on a DynamicObject when called from c#, GetMemberBinder.ReturnType will always be object, but that said if you return another sort of springboard dynamic object with TryConvert implemented you could get that type, except if the user does var or dynamic as the variable, then they have a proxy that won't do anything until it becomes statically typed.
ImpromptuInterface does something different but along these lines, because it also has the desire to have a dynamic implementation that changes based on return types -- just you would have to describe the dynamic object via an interface.

Categories