How to Extend the Type Class - c#

this is my code:
bool ch=Type.IsBuiltIn("System.Int32"); // not working-> syntax error
public static class MyExtentions
{
public static bool IsBuiltIn(this Type t, string _type)
{
return (Type.GetType(_type) == null) ? false : true;
}
}
Please I want Extend Type Class by IsBuiltIn new method

You can't have static extension methods. Your extension method works on an instance of the Type class, so to call it you'd have to do something like this:
typeof(Type).IsBuiltIn("System.Int32")
The workaround for this is to just put your extension method in a utility class, e.g. like the following, and call it like a normal static function:
public static class TypeExt
{
public static bool IsBuiltIn(string _type)
{
return Type.GetType(_type) == null;
}
}
// To call it:
TypeExt.IsBuiltIn("System.Int32")
By the way, I don't think this will tell you whether the type is "built-in"; it will merely tell you whether a type with the given name has been loaded into the process.

Extension methods are intended to describe new APIs on instances, not types. In your case, that API would be something like:
Type someType = typeof(string); // for example
bool isBuiltIn = someType.IsBuiltIn("Some.Other.Type");
which... clearly isn't what you wanted; the type here adds nothing and is not related to the IsBuiltIn. There is no compiler trick for adding new static methods to existing types, basically - so you will not be able to use Type.IsBuiltIn("Some.Other.Type").

You can't extend the Type class. You need an instance of the class to create an extension method.
Edit:
See here and here.

Related

Method return type like Generic Class Type

Is possible set method return type, like type to generic class ?
I have Generic Class:
class Generic<T>
{
public static DataSet test(T input)
{
//Some logic...
}
}
Another Class, where i call my generic class.
It works for this examples:
Generic<int>.test(10);
But if i want to call different methods, with complex unknown date types, i don't know how i put their date type like Generic Type.
For Example
var data = Data.GetData(); // return List<string,int>
var data2 = Data.GetData2() // return Tuple<List<string>, List<int>>
I try use method GetType, for get returns method type, something like this, but it doesn't work.
Generic<data.GetType()>.test(data);
Is it possible, something like this ?
No, you can't specify the generic type at runtime without reflection, but there may be other ways to solve your problem. You could put the generic constraint on the method instead of the class:
class Generic
{
public static dynamic Test<T>(T input)
{
//Some logic...
}
}
which then can be inferred from the input type:
Generic.Test(data);
Return Type of a function is known in compile time.
Therefore if I understood your question correctly what you're asking for isn't possible. TL;DR You can't set return type in runtime.

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

Get name of class in C#

I need to get the name of the class that I am currently in. The problem is that I am in a static property. Any idea how I can do this without a reference to this?
If you really want it, although as TomTom points out, you might not need it:
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name
System.Reflection.MethodInfo.GetCurrentMethod().DeclaringType.Name
If you are in a static property, you should be able to make the type name a constant.
If you have a static property in a base class that is inherited, and you are trying to determine the type of the child class that you are in, you can't do this with a static property. The reason is that the static property is associated with the base class type, not any base class instance. Use a regular property instead, and use GetType().Name or similar.
The following call should give you the name of the current type...
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name
You can use something like:
public static class MyClass
{
public static string FullName
{
get { return typeof(MyClass).FullName; }
}
}
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString()
Which is mentioned over and over again, can be wrong if the Type is generic. It will not figure out the generic type.
class Generic<T>
{
public static string ClassName
{
[MethodImpl(MethodImplOptions.NoInlining)]
get
{
return System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.ToString();
}
}
}
Also if you don't use the NoInlining directive your code maybe inlined into the callsite which will definitely not yield the results you are after.
The following code will print Generic``1[T], rather than the particular instantiation it's being called from.
The solution is fairly obvious just use MakeGenericMethod with T to get the right instance.
The solution is fairly obvious just use MakeGenericMethod with T to get the right instance.
But if you want to know the name of T you cannot use the MakeGenericMethod. Another solution is to add a static class with a generic method:
public static class Helper
{
public static string GetName<T>()
{
Type type = typeof(T);
Type[] genericArguments = type.GetGenericArguments();
return string.Format("{0}<{1}>", type.Name, string.Join(",", genericArguments.Select(arg => arg.Name)));
}
}
No change the property ClassName to
public static string ClassName
{
get
{
return Helper.GetName<Generic<T>>();
}
}
then you will get the correct generic name, for example a call to Generic<DateTime>.ClassName will return
"Generic`1<DateTime>".

C#: Restricting Types in method parameters (not generic parameters)

I'd like to code a function like the following
public void Foo(System.Type t where t : MyClass)
{ ... }
In other words, the argument type is System.Type, and I want to restrict the allowed Types to those that derive from MyClass.
Is there any way to specify this syntactically, or does t have to be checked at runtime?
If your method has to take a Type type as it's argument, there's no way to do this. If you have flexibility with the method call you could do:
public void Foo(MyClass myClass)
and the get the Type by calling .GetType().
To expand a little. System.Type is the type of the argument, so there's no way to further specify what should be passed. Just as a method that takes an integer between 1 and 10, must take an int and then do runtime checking that the limits were properly adhered to.
Specifying the type be MyClass, or derived from it, is a value check on the argument itself. It's like saying the hello parameter in
void Foo(int hello) {...}
must be between 10 and 100. It's not possible to check at compile time.
You must use generics or check the type at run time, just like any other parameter value check.
You can use the following:
public void Foo<T>(T variable) where T : MyClass
{ ... }
The call would be like the following:
{
...
Foo(someInstanceOfMyClass);
...
}
What you want could theoretically be done with attributes. But this is much clearer (imo) and does exactly the same thing:
public void Foo(MyClass m) {
Type t = m.GetType();
// ...
}
why don't you use
public void foo<t>();
instead?
You can also use an extension method, which will be available for all objects convertible to MyClass:
public static class MyClassExtensions
{
public static void Foo(this MyClass obj)
{
// ...
}
}
And you can use it as if it were an ordinary method of an object:
var x = new MyClass();
x.Foo();

Calling a static method on a generic type parameter

I was hoping to do something like this, but it appears to be illegal in C#:
public Collection MethodThatFetchesSomething<T>()
where T : SomeBaseClass
{
return T.StaticMethodOnSomeBaseClassThatReturnsCollection();
}
I get a compile-time error:
'T' is a 'type parameter', which is not valid in the given context.
Given a generic type parameter, how can I call a static method on the generic class? The static method has to be available, given the constraint.
In this case you should just call the static method on the constrainted type directly. C# (and the CLR) do not support virtual static methods. So:
T.StaticMethodOnSomeBaseClassThatReturnsCollection
...can be no different than:
SomeBaseClass.StaticMethodOnSomeBaseClassThatReturnsCollection
Going through the generic type parameter is an unneeded indirection and hence not supported.
To elaborate on a previous answer, I think reflection is closer to what you want here. I could give 1001 reasons why you should or should not do something, I'll just answer your question as asked. I think you should call the GetMethod method on the type of the generic parameter and go from there. For example, for a function:
public void doSomething<T>() where T : someParent
{
List<T> items=(List<T>)typeof(T).GetMethod("fetchAll").Invoke(null,new object[]{});
//do something with items
}
Where T is any class that has the static method fetchAll().
Yes, I'm aware this is horrifically slow and may crash if someParent doesn't force all of its child classes to implement fetchAll but it answers the question as asked.
You can do what I call a surrogate singleton, I've been using it as a sort of "static inheritance" for a while
interface IFoo<T> where T : IFoo<T>, new()
{
ICollection<T> ReturnsCollection();
}
static class Foo<T> where T : IFoo<T>, new()
{
private static readonly T value = new();
public static ICollection<T> ReturnsCollection() => value.ReturnsCollection();
}
// Use case
public ICollection<T> DoSomething<T>() where T : IFoo<T>, new()
{
return Foo<T>.ReturnsCollection();
}
The only way of calling such a method would be via reflection, However, it sounds like it might be possible to wrap that functionality in an interface and use an instance-based IoC / factory / etc pattern.
It sounds like you're trying to use generics to work around the fact that there are no "virtual static methods" in C#.
Unfortunately, that's not gonna work.
I just wanted to throw it out there that sometimes delegates solve these problems, depending on context.
If you need to call the static method as some kind of a factory or initialization method, then you could declare a delegate and pass the static method to the relevant generic factory or whatever it is that needs this "generic class with this static method".
For example:
class Factory<TProduct> where TProduct : new()
{
public delegate void ProductInitializationMethod(TProduct newProduct);
private ProductInitializationMethod m_ProductInitializationMethod;
public Factory(ProductInitializationMethod p_ProductInitializationMethod)
{
m_ProductInitializationMethod = p_ProductInitializationMethod;
}
public TProduct CreateProduct()
{
var prod = new TProduct();
m_ProductInitializationMethod(prod);
return prod;
}
}
class ProductA
{
public static void InitializeProduct(ProductA newProduct)
{
// .. Do something with a new ProductA
}
}
class ProductB
{
public static void InitializeProduct(ProductB newProduct)
{
// .. Do something with a new ProductA
}
}
class GenericAndDelegateTest
{
public static void Main()
{
var factoryA = new Factory<ProductA>(ProductA.InitializeProduct);
var factoryB = new Factory<ProductB>(ProductB.InitializeProduct);
ProductA prodA = factoryA.CreateProduct();
ProductB prodB = factoryB.CreateProduct();
}
}
Unfortunately you can't enforce that the class has the right method, but you can at least compile-time-enforce that the resulting factory method has everything it expects (i.e an initialization method with exactly the right signature). This is better than a run time reflection exception.
This approach also has some benefits, i.e you can reuse init methods, have them be instance methods, etc.
You should be able to do this using reflection, as is described here
Due to link being dead, I found the relevant details in the wayback machine:
Assume you have a class with a static generic method:
class ClassWithGenericStaticMethod
{
public static void PrintName<T>(string prefix) where T : class
{
Console.WriteLine(prefix + " " + typeof(T).FullName);
}
}
How can you invoke this method using relection?
It turns out to be very easy… This is how you Invoke a Static Generic
Method using Reflection:
// Grabbing the type that has the static generic method
Type typeofClassWithGenericStaticMethod = typeof(ClassWithGenericStaticMethod);
// Grabbing the specific static method
MethodInfo methodInfo = typeofClassWithGenericStaticMethod.GetMethod("PrintName", System.Reflection.BindingFlags.Static | BindingFlags.Public);
// Binding the method info to generic arguments
Type[] genericArguments = new Type[] { typeof(Program) };
MethodInfo genericMethodInfo = methodInfo.MakeGenericMethod(genericArguments);
// Simply invoking the method and passing parameters
// The null parameter is the object to call the method from. Since the method is
// static, pass null.
object returnValue = genericMethodInfo.Invoke(null, new object[] { "hello" });
As of now, you can't. You need a way of telling the compiler that T has that method, and presently, there's no way to do that. (Many are pushing Microsoft to expand what can be specified in a generic constraint, so maybe this will be possible in the future).
Here, i post an example that work, it's a workaround
public interface eInterface {
void MethodOnSomeBaseClassThatReturnsCollection();
}
public T:SomeBaseClass, eInterface {
public void MethodOnSomeBaseClassThatReturnsCollection()
{ StaticMethodOnSomeBaseClassThatReturnsCollection() }
}
public Collection MethodThatFetchesSomething<T>() where T : SomeBaseClass, eInterface
{
return ((eInterface)(new T()).StaticMethodOnSomeBaseClassThatReturnsCollection();
}

Categories

Resources