Calling a static method of a class using reflection - c#

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

Related

How to pass a generic type parameter reference to a function in C#?

I am trying to create a generic function which accepts any type of object and return it after the inquiry. However, the method I am creating is calling another generic function, which also accepts any type of object, but in my case I want to reference the class/type of "obj" to the GetInquiry() function in order for it to run, but according to this design, I won't be knowing its type at compile time, hence I am unable to call the GetInquiry() function.
public T Inquiry<T>(T obj)
{
string Username = "myUser";
Task<T> myTask = Inquire<T>.GetInquiry(Username); //throws 'T' must be a reference type
obj = myTask.Result;
return obj;
}
public static class Inquire<T> where T: class
{
public static async Task<T> GetInquiry(string Username)
{
//some code
}
}
How am I supposed to pass the reference? Any other workarounds and refactoring suggestions are also appreciated.
"the method I am creating is calling another generic function, which also accepts any type of object"
This statement is not correct...the method you're calling does NOT accept any type of object; it only accepts objects which are classes. In order for you to pass your type to it, you need to apply the same constraint:
public T Inquiry<T>(T obj) where T: class
{
string Username = "myUser";
Task<T> myTask = Inquire<T>.GetInquiry(Username); //throws 'T' must be a reference type
obj = myTask.Result;
return obj;
}
public static class Inquire<T>
{
public static Task<T> GetInquiry(string username)
{
//run process
Task<T> result = new Task<T>(() => {
//do something
});
return result;
}
}
The easiest way to solve this problem is to make the Inquiry method generic, like this:
public T Inquiry<T>(T obj)
where T : class
{
string Username = "myUser";
Task<T> myTask = Inquire<T>.GetInquiry(Username);
obj = myTask.Result;
return obj;
}
This way, you can specify the type parameter T to be a reference type, which will allow you to call the GetInquiry() method without any errors.

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;

C# Determine Generic Type Parameter at Runtime

If a named class exists, I want to pass that class as the type parameter to a generic method. Otherwise I want to pass a different type. I cannot figure out how to pass the type parameter to the generic method.
// Does this type exist?
Type objType = Type.GetType(typeof(ModelFactory).Name + "." + content_type + "Model");
// if not, use this type instead
if (objType == null)
{
objType = typeof(GenericModel);
}
// what to pass as the generic type argument?
var other = query.Find<objType>().ContinueWith((t) =>
Is it possible? What do I pass to Find in the last line instead of objType?
Thanks & regards,
-John
You must use the Reflection API. Once you get the argument type for your Find method, you need to get a MethodInfo from the Find method and pass an instance of the class that defines that method and the necessary parameters for the method, an example:
public class GenericModel {}
// This class simulates the class that contains the generic Find method
public class Query {
public void Find<T>() {
Console.WriteLine("Invoking Find method...");
}
}
class Program {
static async Task Main(string[] args) {
var theType = typeof(GenericModel);
// Obtaining a MethodInfo from the Find method
var method = typeof(Query).GetMethod(nameof(Query.Find)).MakeGenericMethod(theType);
var instanceOfQuery = Activator.CreateInstance(typeof(Query));
var response = method.Invoke(instanceOfQuery, null); // Cast the method to your return type of find.
Console.ReadLine();
}
}

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

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
}
}

Returning desired type from Activator.CreateInstance() instead of object

I'm trying to create an instance of specified Type whatever user wants to have. For a quick illustration of my purpose please see the code below:
static void Main(string[] args)
{
object o = GetInstance(typeof(int));
Console.WriteLine("Created type: {0}", o.GetType().FullName);
}
public static object GetInstance(Type t)
{
Console.WriteLine("Creating instance of {0}", t.FullName);
return Activator.CreateInstance(t);
}
The problem is Activator.CreateInstance() returns object by default. There is also an overload of this method like T Activator.CreateInstance<T>() which is parameterless and returns the type you specify as T.
However, the problem is T should be hard-coded while calling this method and thus should be a fixed value. I am trying to create an instance of desired class and return it as its type.
Right now if you use this method you should write something like:
int i = GetInstance(typeof(int)) as int
I'm trying to reduce this to:
int i = GetInstance(typeof(int))
Is there a way that I can do casting inside the GetInstance and get rid of that as int repetition? By this way, my return type (and also the type I cast the object to) will be unknown at compile time.
Seemed impossible by design to me but I'd really appreciate if you figure it out.
EDIT: Where I'm stuck is e.g. while you're casting, you can do return (T) result if you are in a generic method, but you can't do Type t = ...; return (t) result this doesn't work. You cannot cast to a type which is passed to you as a parameter which is not known at compile time.
Follow a known pattern
This is not a new problem. It is a problem facing any API that allows type-specific return values. For example, a JSON parsing library like Newtonsoft (which is, to wit, the single most popular .NET package downloaded by .NET programmers in 2019) must be able to parse a string and return a type-specific object, which may or may not be known at compile time. It might make sense to follow their example.
Newtonsoft exposes three ways to specify the type when deserializing. You could do as you are currently doing:
//Cast required
var result = JsonConvert.DeserializeObject(text, typeof(MyType)) as MyType;
You can use a generic method:
//No cast required, but you have to hardcode a type as a type parameter
var result = JsonConvert.DeserializeObject<MyType>(text);
Or you can use an instance as a template, which is great for anonymous types, although you can use it with non-anonymous classes as well. This one works via generic type inference:
//No cast required and no need to specify type; the type is inferred from the argument
var result = JsonConvert.DeserializeAnonymousType(text, new MyType());
Here's how you'd do it:
So for you to make this work, your code might look like this:
public object GetInstance(Type type)
{
return Activator.CreateInstance(type);
}
int i = GetInstance(typeof(int)) as int;
public T GetInstance<T>()
{
return Activator.CreateInstance<T>();
}
int i = GetInstance<int>();
public T GetInstance<T>(T template)
{
return Activator.CreateInstance<T>();
}
int i = GetInstance(0);
If you do it this way, it's hard to imagine any programmer would have trouble using your library, as the approach should already be familiar to them.
Actually you could write GetInstance like this:
static T GetInstance<T>()
{
return Activator.CreateInstance<T>();
}
And use it:
int j = GetInstance<int>();
This might help you to create instance of desired type:
public class ConcreteFactory<T> : AbstractFactory<T>
{
public override T CreateInstance(string typeName,params object[] parameters)
{
var path = Assembly.GetExecutingAssembly().CodeBase;
var assembly = Assembly.LoadFrom(path);
var type = assembly.GetTypes().SingleOrDefault(t => t.Name == typeName);
return (T)Activator.CreateInstance(type, parameters);
}
}
Key here is generic type T can be used to cast the created instance, this can be used as a template to create instance of any type with parameterized constructor

Categories

Resources