How to pass a generic type parameter reference to a function in C#? - 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.

Related

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();
}
}

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

C# Passing a Generic Class As a Method Parameter

I have a CreateMessage class that is meant to handle incoming messages from a TCPClient, get the user type and return how the message should be formatted to its calling method.
In the method GetUserType, I want to pass UserBaseType as a parameter, which is a generic abstract class that takes a Type of UserType. However, it gives me the error:
Using the generic type 'UserTypeBase' requires one type argument.
I'm still trying to wrap my head around using generics and constraints, so I don't know if I'm going about this the wrong way. I've done a bit of digging to try to find a solution myself, but haven't found anything that more or less tailors to what I'm trying to do.
internal class CreateMessage
{
internal static string user;
internal static string message;
internal CreateMessage(string data)
{
user = Lists.users[data.Substring(1, 3)];
message = data.Substring(5, data.Length - 5);
}
private UserType GetUserType(UserTypeBase type)
{
return type.CreateType();
}
internal string Message()
{
UserType Type = null;
if (user.Contains("[M]"))
Type = GetUserType(UserMod);
else if (user.Contains("[B]"))
Type = GetUserType(UserVIP);
else
Type = GetUserType(UserRegular);
return Type.Message();
}
}
UserBaseType.cs
internal abstract class UserTypeBase<T> where T: UserType
{
public abstract string User { get; }
public abstract string Message { get; }
public abstract T CreateType();
}
You're going to want to make the method that takes the parameter generic as well. You're going to also want to mirror the type constraints as they appear on the parametric type to avoid compilation errors, as well as be explicit in what is and is not acceptable for the method.
private T GetUserType<T>(UserTypeBase<T> type) where T : UserType
{
return type.CreateType();
}
You can then call it with the type provided explicitly or implicitly, depending on the situation.
var someType = new UserTypeDerived<UserType>();
var resultImplicit = GetUserType(someType);
var resultExplicit = GetUserType<UserType>(someType);
Since it's a parameter that is being used generically, the compiler can implicitly determine what the expected value of T is based on the type of the parameter supplied.

Extend "object" with a null check more readable than ReferenceEquals

I tried to extend "object" to allow a more readable check if an object is null.
Now, object.ReferenceEquals really checks for a null object, (the rare times it will not apply are since the operator == can be overridden. the object.Equals(null) method can also be overridden).
But the object.ReferenceEquals(null, obj); is not too readable is it?... So, I thought, why not write an extension method to the System.object that will provide that check using object.IsNull(obj);
I've tried:
public static class MyExtClass
{
// the "IsNull" extension to "object"
public static bool IsNull(this object obj)
{
return object.ReferenceEquals(obj, null);
}
}
public SomeOtherClass
{
public static void TryUsingTheExtension()
{
object obj;
// Why does this line fail? the extension method is not recognized
// I get: 'object' does not contain a definition for "IsNull"
bool itIsANull = object.IsNull(obj);
}
}
What did I miss?
Extension methods can be invoked only on instance and not on a class that they extend. So this line of code bool itIsANull = object.IsNull(obj); is incorrect because object is type and not an instance. Change it to :
bool itIsANull = (new object()).IsNull();
Or you can call it on class MyExtClass but not on object class (which is located in mscore.lib) :
MyExtClass.IsNull(new object());
P.S.
It looks like you missed something about extension methods. The truth is that they have nothing to do with classes that they extend. It's just a convenience that is provided for us by Intellisense with use of reflection.
Object class is located in mscorelib and is immutable. You can't add something to it. But what really happens is that Intellisense searches for all public methods that are located in public static classes and accept first argument with keyword 'this' as parameter. If one is found it's 'mapped' to the class that it extends. So when we type obj.MyExtMethod() on instance of that class it is automatically converted by compiler to Helper.MyExtMethod(obj); (if helper is our static class);
Try
bool itIsANull = obj.IsNull();
You wrote an extension method, and extension methods exist in a different type but extend objects of the specified type by another method.
But when you call object.IsNull(), then you are looking for a static method that exists on the object type.
Instead, you have two ways to call your method:
// either the static method on the class
MyExtClass.IsNull(obj);
// or using the actual feature of extension methods
obj.isNull();
Because it’s an extension method, the latter form will be automatically converted into the former at compile time.
You are calling the extension method on the object itself. You should call the methd on the instance instead -
bool itIsANull = obj.IsNull()
Try:
class Program
{
static void Main(string[] args)
{
var o = new object();
if (o.IsNull())
{
Console.Write("null");
}
}
}
public static class Request
{
public static bool IsNull(this object obj)
{
return ReferenceEquals(obj, null);
}
}
public static class MyExtClass
{
// the "IsNull" extension to "object"
public static bool IsNull(this object obj)
{
return object.ReferenceEquals(obj, null);
}
}
public class SomeOtherClass
{
public static void TryUsingTheExtension()
{
object obj =null;
bool itIsANull = obj.IsNull();
}
}

Returning System.Action from static method on generic type with types defined at runtime

Below is a very paired down example of what I am trying to achieve
public class CoolClass<T>
{
public static void DoSomethingCool()
{
// Insert cool generic stuff here.
List<T> coolList = new List<T>();
}
}
public class OtherClass
{
public Action ReturnActionBasedOnStaticGenericMethodForType(Type type)
{
// Ideally this would just be
return CoolClass<type **insert magic**>.DoSomethingCool
}
}
I know if the type is known I can do following and it will return System.Action
return CoolClass<string>.DoSomethingCool
I know if all I wanted to do was invoke the method I can do
Type baseType = typeof(CoolClass<>);
Type[] typeArguments = new [] {type}
Type constructedType = baseType.MakeGenericType(typeArguments);
MethodInfo method = constructedType.GetMethod("DoSomethingCool");
method.Invoke(null,null);
I maybe down the wrong path all together. It seems like I am trying go get method to be a reference to DoSomethingCool method. I am wishing for something like (Action) method.
You're nearly there - you just need Delegate.CreateDelegate:
Action action = (Action) Delegate.CreateDelegate(typeof(action), null, method);

Categories

Resources