C#: What does it mean to use a variable like a type? - c#

I'm new to C#, coming from a Javascript background (so 'typing' is quite new to me).
What does the warning "... is a variable but is used like a type" mean?
I have the following code within a static function called test:
var activeCell = new ExcelReference(1, 1);
Type type = typeof(activeCell);

You can use typeof only with a type, for example Type type = typeof(ExcelReference);
If you want to know what type is this variable use Type type = activeCell.GetType();

Quite easy in fact.
typeof is used with a Class, Interface etc name, meanwhile for what you want you will need the GetType function.
Example :
public class MyObject
{
public static Type GetMyObjectClassType()
{
return typeof(MyObject);
}
public static Type GetMyObjectInstanceType(MyObject someObject)
{
return someObject.GetType();
}
public static Type GetAnyClassType<GenericClass>()
{
return typeof(GenericClass);
}
public static Type GetAnyObjectInstanceType(object someObject)
{
return someObject.GetType();
}
public void Demo()
{
var someObject = new MyObject();
Console.WriteLine(GetMyObjectClassType()); // will write the type of the class MyObject
Console.WriteLine(GetMyObjectInstanceType(someObject)); // will write the type of your instance of MyObject called someObject
Console.WriteLine(GetAnyClassType<MyObject>()); // will write the type of any given class, here MyObject
Console.WriteLine(GetAnyClassType<System.Windows.Application>()); // will write the type of any given class, here System.Windows.Application
Console.WriteLine(GetAnyObjectInstanceType("test")); // will write the type of any given instance, here some string called "test"
Console.WriteLine(GetAnyObjectInstanceType(someObject)); // will write the type of any given instance, here your instance of MyObject called someObject
}
}

Related

error "does not contain a definition for 'getProperty'" when trying to set property of generic typed object

void myFunc<M>()
{
dynamic uploadReq = (M)Activator.CreateInstance(typeof(M));
uploadReq.getProperty("Credentials").SetValue(null);
}
I have a function where I supply a type, an object of this type is created, and then a property on the object is set to null. I get an error
MyCustomType does not contain a definition for 'getProperty'
How can I fix this?
GetProperty its method of Type. Object has no it.
You can use this way:
call GetProperty from type
set value to object
public static void myFunc<M>()
{
dynamic uploadReq = (M)Activator.CreateInstance(typeof(M));
typeof(M).GetProperty("Credentials").SetValue(uploadReq, null);
}
In this specific snippet of code you don't need dynamic or reflection, because you know the type at compile time, just use the generic version of the CreateInstance method or even better the constructor of the type. This is faster and also provides compile time checks.
void myFunc<M>() where M : new()
{
M uploadReq = new M();
uploadReq.Credentials = null;
}
or
M uploadReq = Activator.CreateInstance<M>();
uploadReq.Credentials = null;

In C# how do you create an instance of ILogger<T> from a Type? [duplicate]

The title is kind of obscure. What I want to know is if this is possible:
string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);
MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();
Obviously, MyGenericClass is described as:
public class MyGenericClass<T>
Right now, the compiler complains that 'The type or namespace 'myType' could not be found." There has got to be a way to do this.
You can't do this without reflection. However, you can do it with reflection. Here's a complete example:
using System;
using System.Reflection;
public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}
class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass);
}
}
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);
Unfortunately no there is not. Generic arguments must be resolvable at Compile time as either 1) a valid type or 2) another generic parameter. There is no way to create generic instances based on runtime values without the big hammer of using reflection.
Some additional how to run with scissors code. Suppose you have a class similar to
public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}
Suppose at runtime you have a FooContent
If you were able to bind at compile time you would want
var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)
However you cannot do this at runtime. To do this at runtime you would do along the lines of:
var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);
To dynamically invoke Markdown(IEnumerable<FooContent> contents)
new Encoder().Markdown( (dynamic) dynamicList)
Note the usage of dynamic in the method call. At runtime dynamicList will be List<FooContent> (additionally also being IEnumerable<FooContent>) since even usage of dynamic is still rooted to a strongly typed language the run time binder will select the appropriate Markdown method. If there is no exact type matches, it will look for an object parameter method and if neither match a runtime binder exception will be raised alerting that no method matches.
The obvious draw back to this approach is a huge loss of type safety at compile time. Nevertheless code along these lines will let you operate in a very dynamic sense that at runtime is still fully typed as you expect it to be.
My requirements were slightly different, but will hopefully help someone. I needed to read type from a config and instantiate the generic type dynamically.
namespace GenericTest
{
public class Item
{
}
}
namespace GenericTest
{
public class GenericClass<T>
{
}
}
Finally, here is how you call it. Define the type with a backtick.
var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);
If you know what types will be passed you can do this without reflection. A switch statement would work. Obviously, this would only work in a limited number of cases, but it'll be much faster than reflection.
public class Type1 { }
public class Type2 { }
public class Generic<T> { }
public class Program
{
public static void Main()
{
var typeName = nameof(Type1);
switch (typeName)
{
case nameof(Type1):
var type1 = new Generic<Type1>();
// do something
break;
case nameof(Type2):
var type2 = new Generic<Type2>();
// do something
break;
}
}
}
In this snippet I want to show how to create and use a dynamically created list. For example, I'm adding to the dynamic list here.
void AddValue<T>(object targetList, T valueToAdd)
{
var addMethod = targetList.GetType().GetMethod("Add");
addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}
var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);
AddValue(list, 5);
Similarly you can invoke any other method on the list.

How to cast Object as Generic<a, b>? [duplicate]

The title is kind of obscure. What I want to know is if this is possible:
string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);
MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();
Obviously, MyGenericClass is described as:
public class MyGenericClass<T>
Right now, the compiler complains that 'The type or namespace 'myType' could not be found." There has got to be a way to do this.
You can't do this without reflection. However, you can do it with reflection. Here's a complete example:
using System;
using System.Reflection;
public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}
class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass);
}
}
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);
Unfortunately no there is not. Generic arguments must be resolvable at Compile time as either 1) a valid type or 2) another generic parameter. There is no way to create generic instances based on runtime values without the big hammer of using reflection.
Some additional how to run with scissors code. Suppose you have a class similar to
public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}
Suppose at runtime you have a FooContent
If you were able to bind at compile time you would want
var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)
However you cannot do this at runtime. To do this at runtime you would do along the lines of:
var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);
To dynamically invoke Markdown(IEnumerable<FooContent> contents)
new Encoder().Markdown( (dynamic) dynamicList)
Note the usage of dynamic in the method call. At runtime dynamicList will be List<FooContent> (additionally also being IEnumerable<FooContent>) since even usage of dynamic is still rooted to a strongly typed language the run time binder will select the appropriate Markdown method. If there is no exact type matches, it will look for an object parameter method and if neither match a runtime binder exception will be raised alerting that no method matches.
The obvious draw back to this approach is a huge loss of type safety at compile time. Nevertheless code along these lines will let you operate in a very dynamic sense that at runtime is still fully typed as you expect it to be.
My requirements were slightly different, but will hopefully help someone. I needed to read type from a config and instantiate the generic type dynamically.
namespace GenericTest
{
public class Item
{
}
}
namespace GenericTest
{
public class GenericClass<T>
{
}
}
Finally, here is how you call it. Define the type with a backtick.
var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);
If you know what types will be passed you can do this without reflection. A switch statement would work. Obviously, this would only work in a limited number of cases, but it'll be much faster than reflection.
public class Type1 { }
public class Type2 { }
public class Generic<T> { }
public class Program
{
public static void Main()
{
var typeName = nameof(Type1);
switch (typeName)
{
case nameof(Type1):
var type1 = new Generic<Type1>();
// do something
break;
case nameof(Type2):
var type2 = new Generic<Type2>();
// do something
break;
}
}
}
In this snippet I want to show how to create and use a dynamically created list. For example, I'm adding to the dynamic list here.
void AddValue<T>(object targetList, T valueToAdd)
{
var addMethod = targetList.GetType().GetMethod("Add");
addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}
var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);
AddValue(list, 5);
Similarly you can invoke any other method on the list.

Calling a static method of a class using reflection

I'm attempting to call a static class method via reflection and get its return value as follows:
private SA GetData()
{
Type type = Type.GetType("SA010");
Object obj = Activator.CreateInstance(type);
MethodInfo methodInfo = type.GetMethod("GetSA");
return (SA)methodInfo.Invoke(obj, null);
}
Here's the class and method I'm calling:
public class SA010
{
public static SA GetSA()
{
//do stuff
return SA.
}
}
The problem is i receive a null reference exception on the 'type' variable. GetData() and SA010.GetSA() are in the same namespace.
Any ideas why i might get this error, something to do with it being static maybe?
Your main problem is you need to specify the full namespace of SA010 when using GetType.
Type type = Type.GetType("SomeNamespace.SA010");
However if you are not dynamicly generating the name a easier solution is use typeof, this does not require you to entire the namespace in if the type is already within scope.
Type type = typeof(SA010);
2nd issue you will run in to once you fix the type, if a method is static you don't create a instance of it, you just pass null in for the instance for the Invoke call.
private SA GetData()
{
Type type = typeof(SA010);
MethodInfo methodInfo = type.GetMethod("GetSA");
return (SA)methodInfo.Invoke(null, null);
}
Try to use
Type type = typeof(SA010);
instead of
Type type = Type.GetType("SA010");
it worked for me

Typecast to a type from just the string representation of the type name

sTypeName = ... //do some string stuff here to get the name of the type
/*
The Assembly.CreateInstance function returns a type
of System.object. I want to type cast it to
the type whose name is sTypeName.
assembly.CreateInstance(sTypeName)
So, in effect I want to do something like:
*/
assembly.CreateInstance(sTypeName) as Type.GetType(sTypeName);
How do I do that? And, what do I take on the left side of the assignment expression, assuming this is C# 2.0. I don't have the var keyword.
Usually you let all classes, you want to instantiate this dynamically, implement a common interface, lets say IMyInterface. You can create an instance from the classname string like this:
Assembly asm = Assembly.GetExecutingAssembly();
string classname = "MyNamespace.MyClass";
Type classtype = asm.GetType(classname);
// Constructor without parameters
IMyInterface instance = (IMyInterface)Activator.CreateInstance(classtype);
// With parameters (eg. first: string, second: int):
IMyInterface instance = (IMyInterface)Activator.CreateInstance(classtype,
new object[]{
(object)"param1",
(object)5
});
Even if you dont have a common interface, but know the name of the method (as string) you can invoke your methods like this (very similar for properties, event and so on):
object instance = Activator.CreateInstance(classtype);
int result = (int)classtype.GetMethod("TwoTimes").Invoke(instance,
new object[] { 15 });
// result = 30
The example class:
namespace MyNamespace
{
public class MyClass
{
public MyClass(string s, int i) { }
public int TwoTimes(int i)
{
return i * 2;
}
}
}
Unfortunately there's no way in .NET to do what you want.
Possible partial solutions are:
If you know the type at compile-time (unlikely, since you're creating it at run-time from a string) then simply cast to that type:
YourType t = (YourType)Activator.CreateInstance(sTypeName);
If you know that all the possible types will implement a specific, common interface then you can cast to that interface instead:
IYourInterface i = (IYourInterface)Activator.CreateInstance(sTypeName);
If you can't do either of the above then, unfortunately, you're stuck with object and reflection.
.
Define a generic method in your class, and then you can cast like this:
public T Cast<T>(object obj)
{
return (T) obj;
}
string sTypename = "SomeClassName";
MethodInfo cast = this.GetType().GetMethod("Cast");
MethodInfo genericCast = cast.MakeGenericMethod(new Type[] { Type.GetType(sTypename) });
Object castedValue = genericCast.Invoke(this, new object[] { instanceToBeCasted });
But then I think, what is the point of such casting if you cannot store the casted value in a variable of the actual type, precisely because you don't know the actual type at the time of writing the code?

Categories

Resources