Assign dynamically deserialized value to dynamically created instance - c#

At runtime, I find the type of an object from which I want to create an instance:
string typeName = "myNamespace.type, assembly";
Type theType = Type.GetType(typeName);
// the type features a constructor w/o arguments:
object theInstance = Acivator.CreateInstance(theType);
This works fine and in the debugger I can see all attribute values -- I do assume the debugger uses reflection?
I also have a dynamically deserialized object of type object, for which I know that it in fact of type theType:
// pseudo code on the rhs of the "="
object deserialized = decoder.decode(serializedObject.body);
Is there a way to assign deserializedto theInstance, without looping over the attributes of the type using reflection? Since this will be time critical: assuming the only way to do this is reflection, is there a way to minimize the performance penalty? I do expect many of these objects in short time.
(This is .Net 3.5, so if Type dynamic could solve this it is of no use in this case).

The simplest way would be to write a method that copies the attributes from one object of this type to another:
static void CopyAttributesOnto(theType dest, theType source)
{
dest.a = source.a;
dest.b = source.b;
// ...
}
// Then you can just do this:
CopyAttributesOnto((theType)theInstance, (theType)deserialized);
Another option would be to build a DynamicMethod at runtime and create a delegate from it. You will pay once for the cost of reflection and JIT compilation of the new method, but every invocation of the method will have no more overhead than the use of any other delegate.

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.

not able to create object with Activator.CreateInstance

I am trying to load the old version of farpoint dll in my project by using below code
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(#"FarPoint.Web.Spread.dll");
System.Type MyDLLFormType = assembly.GetType("FarPoint.Web.Spread.FpSpread");
var c = Activator.CreateInstance(MyDLLFormType);
The problem is after the instance is created, all the available methods of farpoint are not available
[ for example - if i create the object directly the methods like saveExcel or savechanges are available with the instance]
FpSpread fpProxyObject = new FpSpread();
fpProxyObject.SaveExcel();
They are available, just not at compile time. Activator.CreateInstance() returns an object. You could of course cast the object:
var c = Activator.CreateInstance(...)
FpSpread fpProxyObject = (FpSpread)c;
But that would probably beat the whole purpose of using reflection to create the instance.
You can access all members of the result object by using reflection, ie:
MethodInfo saveExcelMethod = c.GetType().GetMethod("SaveExcel");
if (saveExcelMethod == null) throw new ApplicationException("Incorrect version of FarPoint");
saveExcelMethod.Invoke(c);
Intellisense is not working, because, as said #C.Evenhuis, Activator.CreateInstance returns object, so you should cast it to appropriate type.
If type is not known at compile time, but you have access to a code-base, you could try to add interface for it, and implement it by your class. Then cast object to that interface and use it. (I don't know your purpose, but interface could be treated as a contract for all the types, that you will load dynamically).
If type is not known at compile time and you have no access to a code-base, you could use reflection for method invocation or use dynamic instead.
dynamic c = Activator.CreateInstance(MyDLLFormType);
c.SaveExcel(); // this method invocation will be bound in runtime.
By the way be carefull, while using Assembly.LoadFile. You may get more details from this article.

cast with a Type variable

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.

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.

Is dynamic is same as Object

In "CLR via C#" book it's mentioned that dynamic keyword corresponding FCL type is System.Object. please clarify this .
It's not the same thing from the C#'s point of view at all... but in the compiled code, a variable declared as type dynamic will usually (possibly always) correspond with a CLR field or local variable of type object.
The C# compiler is responsible for making sure that any source code using that value has the dynamic behaviour applied to it. object is simply the compiler the representation uses for storage. It also applies the [Dynamic] attribute where appropriate, so that other code knows it's to be treated dynamically.
For example, consider this:
public class Foo
{
public dynamic someField;
}
I believe that will be compiled into IL equivalent to:
public class Foo
{
[Dynamic]
public object someField;
}
now if you write:
Foo foo = new Foo();
foo.someField = "hello";
Console.WriteLine(foo.someField.Length);
the compiler uses the attribute to know that foo.someField is dynamic, so the Length property should be dynamically bound.
From MSDN:
The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object.
And:
Type dynamic behaves like type object in most circumstances. However, operations that contain expressions of type dynamic are not resolved or type checked by the compiler. The compiler packages together information about the operation, and that information is later used to evaluate the operation at run time. As part of the process, variables of type dynamic are compiled into variables of type object. Therefore, type dynamic exists only at compile time, not at run time.
(emphasis mine)
Since a dynamic reference needs to be able to take any type, it is in effect of the type object (or at least to all appearances and uses), but the compiler will not perform certain type checks on it.

Categories