Creating dynamic generics at runtime using Reflection - c#

I'm trying to convert a Dictionary< dynamic, dynamic > to a statically-typed one by examining the types of the keys and values and creating a new Dictionary of the appropriate types using Reflection. If I know the key and value types, I can do the following:
Type dictType = typeof(Dictionary<,>);
newDict = Activator.CreateInstance(dictType.MakeGenericType(new Type[] { keyType, valueType }));
However, I may need to create, for example, a Dictionary< MyKeyType, dynamic > if the values are not all of the same type, and I can't figure out how to specify the dynamic type, since
typeof(dynamic)
isn't viable.
How would I go about doing this, and/or is there a simpler way to accomplish what I'm trying to do?

The C# compiler emits System.Object as the type for "dynamic". "dynamic" is a language-specific construct and has no corresponding type in the Common Language Infrastructure. As such, you won't be able to use reflection to create a "dynamic" nor use "dynamic" as a generic type parameter.
A Dictionary<dynamic, dynamic> is really a Dictionary<object, object>. What "dynamic" means to the compiler is simply late-bind any member accesses for the object using reflection (the implementation of which lies in the Microsoft.CSharp assembly in case you're curious).
On a side note, the compiler will also emit an attribute, DynamicAttribute, on fields, parameters, etc. that are "dynamic"; that allows people consuming the assembly's metadata to distinguish between a System.Object and a "dynamic". This is how IntelliSense shows a method's parameter as dynamic from an assembly reference, for example.

Dictionary<MyType, Object>
Activator.CreateInstance(typeof (Dictionary<dynamic, dynamic>));
This actually creates a Dictionary<Object, Object>
The only use I can see from using dynamic instead of object is during code typing you can use dic["some"].MyDynProperty.... but if you create you object with Activator it will return Object so no use in code typing...

Related

Does a primitive type get boxed when declared as a dynamic

I'm working on a way to handle parsing strings to types without knowing what types they are being parsed to. Specifically bools/ints/dates etc.
I am considering using a Dictionary<Type, Func <string,dynamic>> to do this but want to know if there is going to be a boxing/unboxing of the value.
Yes, the value type instances you return from your funcs will be boxed (you effectively have a dictionary that stores Func<string, object>s).
When you invoke the func and try to assign it to a variable or pass it into a method, the value will be unboxed and stored in a reference of the appropriate type.

How to type cast in C# having needed type as System.Type

I need to initialize an instance of System.Collections.Generic.List<String> using Reflection. For example, the type name has been loaded from XML, and it is unknown before the program has launched. I got the type and its assembly:
Type T = Type.GetType("System.Collections.Generic.List`1[System.String]");
Assembly ass = T.Assembly;
After this I need to initialize my variable, but I don't want to write the type explicitly, so using:
var lst = ass.CreateInstance(T.FullName) as List<String>;
is inapropriate. I have already got the required type in T, so if I can do something like:
var lst = ass.CreateInstance(T.FullName) as T;
it should be fine. But I can't.
What do I have to do?
It's not possible to declare a variable of a 'variable' type. Any variable/property/method/parameter/class/whatever MUST be know beforehand, at compile-time, since C# is a strongly- typed language.
The only real way to deal with dynamically generated data types like in your example is to stay with the type-unsafe object or dynamic, which can contain anything, even unknown at compile-time.
Also remember that the varsyntax isn't anything variable really, it's just syntax sugar for avoiding writing the real type, which is obtained from the type on the right side of the =, so it's really of no help for your purpose.

C#: return stong types from reflection

In the latest version of C#, is it possible to convert a dynamic type to a strong type, if you know the type in advance?
I'm using reflection to call a method on an object, which returns to a var:
var returnVal = context.GetType().InvokeMember(MethodName, BindingFlags.InvokeMethod, null, context, lParams.ToArray());
I can easily get the type being returned to returnVal. Is it possible to cast\convert thins to a more strongly typed version?
EDIT FOR CLARITY:
In this situation, I know the type being returned but only by string. To get the type, I have to do:
diAssemblies[k].GetType(diAssemblies[k].GetName().Name + "." + returnType)
Where returnType is the name of type being returned.
Ideally, I'd like to be able to get the result of the method invocation in to a strongly typed field.
CONTEXT
I'm loading assemblies containing .edmx files from a directory, then invoking methos on those contexts. At run time, the loader won't know what assemblies it's going to be loading. However, the person using the loader will be aware of the assemblies, methods and types.
This is to create a generic wrapper around database calls through entity framework (with stored procedures), that will be reused elsewhere.
If you don't know the Type statically, how could you use a statically typed reference? What you can do is have the returned type implement an interface you do know about statically, then cast to that interface.
So, if MyStrongType implements IMyStrongBehavior, you can cast the return value to IMyStrongBehavior and use that statically. The underlying value is already strongly typed, regardless of whether you cast it.
Alternately, you can store the return value in a dynamic variable (which will allow you to invoke known methods without an actual statically-typed interface.) The disadvantage here is that you don't get any Intellisense and any mistakes you make won't show up until runtime.
No, you can't get the advantages of a concrete type such as compile time checking and intellisense. This is because you are only actually working out what the type is at run time. It is late bound, which means that it's a job for dynamic and the DLR. You can cast it to an object that you know the actual object will inherit from (e.g. object), but you can't cast to the actual type. You might want to look into generics as an alternative if you had for example:
public T GetReturnVal<T>()
{
return (T)context.GetType().InvokeMember(MethodName, BindingFlags.InvokeMethod, null, context, lParams.ToArray());
}
You would at least be returning a concrete type to callers of type T. But this type has to be set at compile time, i.e. known in advance.
I recomend you read An Introduction to C# Generics as it does exactly what, from the context you've added, you need to do.

dynamic vs object type

I have used the dynamic and the object type interchangeably. Is there any difference between these two types? Is there any performance implications of using one over the other? Which one of these is more flexible?
They're hugely different.
If you use dynamic you're opting into dynamic typing, and thus opting out of compile-time checking for the most part. And yes, it's less performant than using static typing where you can use static typing.
However, you can't do much with the object type anyway - it has hardly any members. Where do you find yourself using it? When you want to write general purpose code which can work with a variety of types, you should usually consider generics rather than object.
With the advancement in C# language, we have seen the dynamic and object types. Here are the two types, as I learned by comparing these 7 points:
Object
Microsoft introduced the Object type in C# 1.0.
It can store any value because "object" is the base class of all types in the .NET framework.
Compiler has little information about the type.
We can pass the object type as a method argument, and the method also can return the object type.
We need to cast object variables to the original type to use it and to perform desired operations.
Object can cause problems at run time if the stored value is not converted or cast to the underlying data type.
Useful when we don't have more information about the data type.
Dynamic
Dynamic was introduced with C# 4.0
It can store any type of variable, similar to how Visual Basic handles a variable.
It is not type-safe, i.e., the compiler doesn't have any information about the type of variable.
A method can both accept a Dynamic type as an argument and return it.
Casting is not required, but you need to know the properties and methods related to stored type.
The Dynamic type can cause problems if the wrong properties or methods are accessed because all the information about the stored value is resolved at run time, compared to at compilation.
Useful when we need to code using reflection or dynamic languages or with the COM objects due to writing less code.
Hopefully, this would help somebody.
In simple language:
Assume we have the following method:
public static void ConsoleWrite(string inputArg)
{
Console.WriteLine(inputArg);
}
Object: the following code has compile error unless cast object to string:
public static void Main(string[] args)
{
object obj = "String Sample";
ConsoleWrite(obj);// compile error
ConsoleWrite((string)obj); // correct
Console.ReadKey();
}
dynamic: the following code compiles successfully but if it contains a value except string it throws Runtime error
public static void Main(string[] args)
{
dynamic dyn = "String Sample";
ConsoleWrite(dyn); // correct
dyn = 1;
ConsoleWrite(dyn);// Runtime Error
Console.ReadKey();
}
There is an article explaining the different types, including object and dynamic types. The article also explains the difference between the two with a nice example.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types
I shall give a short gist of the difference explained in the article:
The object type is an alias for System.Object in .NET. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from System.Object. You can assign values of any type to variables of type object.
The dynamic type indicates that use of the variable and references to its members bypass compile-time type checking. Instead, these operations are resolved at run time. The dynamic type simplifies access to COM APIs such as the Office Automation APIs, to dynamic APIs such as IronPython libraries, and to the HTML Document Object Model (DOM).
Type dynamic behaves like type object in most circumstances. In particular, any non-null expression can be converted to the dynamic type. The dynamic type differs from object in that 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.
Summary:
What this essentially means is object is a type and all other types inherit from it.
Dynamic is not really a type, it is more like a pointer or representation of some other type, which will be resolved at run time.
Dynamic: Casting is not required but you need to know the property and methods related to stored type to avoid error in run time.
dynamic dyn = 1;
Console.WriteLine(dyn);
int a = dyn;// works fine
Console.WriteLine(a);//print 1
Console.ReadKey();
The above code will work just fine but if dyn = 1.2 is supplied then it will throw exception as 1.2 cannot converted to int
Object: Require to cast object variable explicitly.
object ob = 1;//or 1.2
Console.WriteLine(ob);
int a = ob;//Compile error because explicit casting is not done
Console.WriteLine(a);
Console.ReadKey();
Fiddle: https://dotnetfiddle.net/l5K4Cl

Anonymous Types

I have a Dictionary(TKey, TValue) like
Dictionary<int, ArrayList> Deduction_Employees =
new Dictionary<int, ArrayList>();
and later I add to that array list an anonymous type like this
var day_and_type = new {
TheDay = myDay,
EntranceOrExit = isEntranceDelay
};
Deduction_Employees[Employee_ID].Add(day_and_type);
Now how can I unbox that var and access those properties ??
First, you aren't unboxing the type. Anonymous types are reference types, not structures.
Even though you can technically create instances of the same type outside of the method they were declared in (as per section 7.5.10.6 of the C# 3.0 Language Specification, which states:
Within the same program, two anonymous
object initializers that specify a
sequence of properties of the same
names and compile-time types in the
same order will produce instances of
the same anonymous type.
) you have no way of getting the name of the type, which you need in order to perform the cast from Object back to the type you created. You would have to resort to a cast-by-example solution which is inherently flawed.
Cast-by-example is flawed because from a design standpoint, every single place you want to access the type outside the function it is declared (and still inside the same module), you have to effectively declare the type all over again.
It's a duplication of effort that leads to sloppy design and implementation.
If you are using .NET 4.0, then you could place the object instance in a dynamic variable. However, the major drawback is the lack of compile-time verification of member access. You could easily misspell the name of the member, and then you have a run-time error instead of a compile-time error.
Ultimately, if you find the need to use an anonymous type outside the method it is declared in, then the only good solution is to create a concrete type and substitute the anonymous type for the concrete type.
There are several ways.
Since the comments seems to indicate that I suggest you do this, let me make it clear: You should be creating a named type for your object since you intend to pass it around.
First, you can use Reflection, which another answer here has already pointed out.
Another way, which tricks .NET into giving you the right type is known as "cast by example", and it goes something like this: You need to pass your object through a generic method call, which will return the object as the right type, by inferring the right type to return.
For instance, try this:
private static T CastByExample<T>(T example, object value)
{
return (T)value;
}
and to use it:
var x = CastByExample(new { TheDay = ??, EntranceOrExit = ?? }, obj);
for the two ?? spots, you just need to pass something fitting the data type for those properties, the values will not be used.
This exploits the fact that multiple anonymous types containing the exact same properties, of the same type, in the same order, in the same assembly, will map to the same single type.
However, by this time you should be creating a named type instead.
An anonymous type has method scope. To pass an anonymous type, or a collection that contains anonymous types, outside a method boundary, you must first cast the type to object. However, this defeats the strong typing of the anonymous type. If you must store your query results or pass them outside the method boundary, consider using an ordinary named struct or class instead of an anonymous type.
Source: http://msdn.microsoft.com/en-us/library/bb397696.aspx
No you can't. You can only access the properties by using reflection. The compiler has no way of knowing what the type was, and since it's an anonymous type, you can't cast it either.
If you are using .NET 1.x - 3.x, you must use reflection.
If you use .NET 4.0, you could use a dynamic type and call the expected properties.
In neither case do you need to unbox; that's for value types. Anonymous types are always reference types.

Categories

Resources