I have the following utility routine which determine whether a type derives from a specific type:
private static bool DerivesFrom(Type rType, Type rDerivedType)
{
while ((rType != null) && ((rType != rDerivedType)))
rType = rType.BaseType;
return (rType == rDerivedType);
}
(actually I don't know whether there is a more convenient way to test the derivation...)
The problem is I want to determine whether a type derives from a generic type, but without specify the generic arguments.
For example I can write:
DerivesFrom(typeof(ClassA), typeof(MyGenericClass<ClassB>))
but what I need is the following
DerivesFrom(typeof(ClassA), typeof(MyGenericClass))
How can I achieve it?
Based on the example of Darin Miritrov, this is a sample application:
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace ConsoleApplication1
{
public class MyGenericClass<T> { }
public class ClassB {}
public class ClassA : MyGenericClass<ClassB> { }
class Program
{
static void Main()
{
bool result = DerivesFrom(typeof(ClassA), typeof(MyGenericClass<>));
Console.WriteLine(result); // prints **false**
}
private static bool DerivesFrom(Type rType, Type rDerivedType)
{
return rType.IsSubclassOf(rDerivedType);
}
}
}
You could leave the generic parameter open:
DerivesFrom(typeof(ClassA), typeof(MyGenericClass<>));
should work. Example:
public class ClassA { }
public class MyGenericClass<T>: ClassA { }
class Program
{
static void Main()
{
var result = DerivesFrom(typeof(MyGenericClass<>), typeof(ClassA));
Console.WriteLine(result); // prints True
}
private static bool DerivesFrom(Type rType, Type rDerivedType)
{
return rType.IsSubclassOf(rDerivedType);
}
}
Also notice the usage of IsSubClassOf method which should simplify your DerivesFrom method and kind of defeat its purpose. There's also the IsAssignableFrom method you may take a look at.
Related
Say I have a class CoolStorageClass, which inherits from StorageClassBase:
public abstract class StorageClassBase
{
}
public class CoolStorageClass : StorageClassBase
{
}
Then I have a generic abstract BaseClass<T>. It is important, that T can only be of type StorageClassBase.
public abstract class BaseClass<T> where T : StorageClassBase
{
}
Then I have the implementation of the BaseClass with T as CoolStorageClass in the form of CoolClass:
public class CoolClass : BaseClass<CoolStorageClass>
{
}
I want to select all of my object, which are implementing the BaseClass<StorageClassBase> abstract class.
does it make sense to check the generic of BaseClass? I mean, I could have classes, which inherit from BaseClass<DifferentStorageClassBase>... I ask this, because the linked answer below does not care about the generic parameter of the generic type, only the type itself.
how do I check if a Type implements BaseClass<StorageClassBase>? I have found following answer, but it does not check the type of the generic parameter. So I modified it into this:
public static class TypeExtensions
{
//https://stackoverflow.com/a/457708
public static bool HasBaseClassOf(this Type t, Type toCheck, Type genericParameter)
{
while ((t != null) && (t != typeof(object)))
{
var cur = t.IsGenericType ? t.GetGenericTypeDefinition() : t;
if (toCheck == cur)
{
//also check whether the generic types match
if (t.GenericTypeArguments[0].IsSubclassOf(genericParameter))
{
return true;
}
}
t = t.BaseType;
}
return false;
}
}
But this only checks for one generic type, and I don't understand why I have to check t.GenericTypeArguments instead of cur.GenericTypeArguments.
What is the correct way to check for all the generic type arguments and the BaseClass?
Currently I have to call the function like this: o.GetType().HasBaseClassOf(typeof(BaseClass<StorageClassBase>), typeof(StorageClassBase)). How should I modify the function to be able to call it like this: o.GetType().HasBaseClassOf(typeof(BaseClass<StorageClassBase>))?
Minimal reproducible example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MinimalReproducibleExample
{
public abstract class StorageClassBase
{
//does something
}
public class CoolStorageClass : StorageClassBase
{
}
public abstract class BaseClass<T> where T : StorageClassBase
{
}
public class CoolClass : BaseClass<CoolStorageClass>
{
}
public static class TypeExtensions
{
//https://stackoverflow.com/a/457708
public static bool HasBaseClassOf(this Type t, Type toCheck, Type genericParameter)
{
while ((t != null) && (t != typeof(object)))
{
var cur = t.IsGenericType ? t.GetGenericTypeDefinition() : t;
if (toCheck == cur)
{
//also check whether the generic types match
if (t.GenericTypeArguments[0].IsSubclassOf(genericParameter))
{
return true;
}
}
t = t.BaseType;
}
return false;
}
}
class Program
{
static void Main(string[] args)
{
List<object> myObjects = new List<object>();
myObjects.Add(new CoolClass());
myObjects.Add(new CoolClass());
myObjects.Add(new object());
myObjects.Add(new object());
var t1 = myObjects.Where(o => o.GetType().HasBaseClassOf(typeof(BaseClass<>), typeof(StorageClassBase))).ToList();
Console.ReadKey();
}
}
}
Not sure if this is clear to you or not, but GetGenericTypeDefinition returns a so called open generic type, i.e. baseClass<>. This can be useful if you do not care about the generic arguments for a type. But that does not seem to do quite what you want to.
To simplify the problem statement a bit, lets declare a bunch of shorter types that we can use, simply so we do not have to write BaseClass so many times.
public class T1{}
public class T2 : T1{}
public class Tx : T1{}
public class U1<T> where T : T1{}
public class U2 : U1<T2>{}
public class U2a : U2{}
public class Ux : U1<T1>{}
If I understand your requirements correctly you want to check if a object inherit from a specificed open generic type, and if the type argument is assignable from some other type.
I.e. the following statements should hold:
[Test]
public void Test()
{
Assert.IsTrue(Test<U2>(new U2a()));
Assert.IsTrue(Test<U1<T1>>(new U2()));
Assert.IsTrue(Test<U1<T2>>(new U2()));
Assert.IsTrue(Test<U1<T2>>(new U2a()));
Assert.IsFalse(Test<U1<Tx>>(new U2a()));
Assert.IsFalse(Test<Ux>(new U2a()));
}
The following test should fulfill these statements:
public bool Test<T>(object obj)
{
var tType = typeof(T);
if (tType.IsGenericType)
{
var genericType = tType.GetGenericTypeDefinition();
var genericArguments = tType.GenericTypeArguments;
return obj.GetType().BaseTypes().Any(IsMatchingGenericType);
bool IsMatchingGenericType(Type t)
{
if (!t.IsGenericType)
return false;
if (t.GetGenericTypeDefinition() != genericType)
return false;
if (t.GenericTypeArguments.Length != genericArguments.Length)
{
return false;
}
for (int i = 0; i < genericArguments.Length; i++)
{
if (!genericArguments[i].IsAssignableFrom(t.GenericTypeArguments[i]))
{
return false;
}
}
return true;
}
}
else
{
return tType.IsInstanceOfType(obj);
}
}
This uses IsAssignableFrom rather than IsSubclassOf of, there is some differences between the two if you are using interfaces.
Note that the following does not compile U1<T1> t1 = new U1<T2>(), since the generic type is not covariant. For this you would need to declare a covariant interface, and if you do that, you can just is IsAssignableFrom instead of that large cumbersome method.
I also wonder if you are approaching this in the correct way. It is usually better to put common functionality in separate classes rather than using inheritance. In most cases you want to avoid checking types, and let put the logic in the class instead. If you want to make the logic type-dependent but still separate from the classes, the visitor pattern can often be used.
I'm trying to extend a generic type class, but I can't get VS to see the extension methods.
Of course there would be many ways around this and it sure isn't best practice in all situations, but I can't figure out why, of the two apparently identical cases below, the first one works and the other doesn't.
First, an example of a successful attempt to extend the List class (just to prove I can handle the basics):
namespace Sandbox.ExtensionsThatWork
{
public static class ListExtensions
{
public static List<TheType> ExtendedMethod<TheType>(this List<TheType> original)
{
return new List<TheType>(original);
}
}
public class ExtensionClient
{
public void UseExtensionMethods()
{
List<string> a = new List<string>();
List<string> b = a.ExtendedMethod();
}
}
}
However, the object I want to extend is something like this
namespace Sandbox.Factory
{
public class Factory<T>
{
public static Thing<T> Create()
{
return new Thing<T>();
}
}
public class Thing<T>{}
public static class FactoryExtensions
{
internal static Thing<FactoryType> CreateFake<FactoryType>(this Factory<FactoryType> original)
{
return new FakeThing<FactoryType>();
}
}
public class FakeThing<T> : Thing<T>{}
}
And in this case I can't for the life of me get the compiler to see the extension method.
namespace Sandbox.FactoryClients
{
public class FactoryClient
{
public void UseExtensionMethods()
{
Factory.Thing<int> aThing = Factory.Factory<int>.Create();
///THE COMPILER WON'T FIND THE CreateFake METHOD
Factory.Thing<int> aFakeThing = Factory.Factory<int>.CreateFake<int>();
}
}
}
What am I missing?
Thank you all for your time.
Your problem has nothing to do with generics.
You're calling the extension as if it were a static method of Factory.Factory<int>, which it cannot be.
C# does not support extension static methods (meaning extension methods that act like static methods of the type of the this parameter) on any type.
You need an instance to call the extension method on (like you do in your "working" example):
using Sandbox.Factory;
public void UseExtensionMethods()
{
Thing<int> aThing = Factory<int>.Create();
Thing<int> aFakeThing = new Factory<int>().CreateFake();
}
I have this custom attribute here where it does some logics
[AttributeUsage(AttributeTargets.All)]
public class CustomAttribute : Attribute
{
public CustomAttribute ()
{
bool foo = false;
if (foo)
Console.WriteLine ("TRUE");
}
}
then i want to use it in my component class like this
[Custom]
public class Component
{
public void Test()
{
console.log("test");
}
}
so what i want is every time i created an instance of that component class, it will basically call or execute that code in my attribute to do some logic, but the problem is, it doesn't execute the code inside my custom attribute class. I know I'm doing it wrong, anyone has idea how to do it?
When the class is instantiated, it will not inherently call any code tied to your attribute, or even instantiate it. Attributes are only instantiated when you call them using reflection. If you would want the attributes to be processed when a class is constructed, you would have to call a method in a constructor on your Component class that uses reflection to analyze the attributes on your class.
The ideal approach would be instead to inherit from a base class that has constructor logic:
public class Component : CustomBase
{
public void Test()
{
console.log("test");
}
}
public abstract class CustomBase
{
public CustomBase()
{
bool foo = false;
if (foo)
Console.WriteLine ("TRUE");
}
}
You need to call:
object[] attributes = typeof(MyClass).GetCustomAttributes(true);
somewhere, because this is the code that triggers the attributes constructor to run.
You can make a method in your attribute class, that calls this line, and in your Component, call the attribute method.
As Jason and Cristina said , you need to take account of reflection to code with custom attributes. If you read the code below (from line 18 to 24) you can see some commented out code that list all the CustomAttributes associated with a type.
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributeTest
{
class Program
{
static void Main(string[] args)
{
var customCompo = new Component();
customCompo.Test();
//System.Reflection.MemberInfo info = typeof(Component);
//object[] attributes = info.GetCustomAttributes(true);
//for (int i = 0; i < attributes.Length; i++)
//{
// System.Console.WriteLine(attributes[i]);
//}
Console.ReadLine();
}
}
[CustomAttribute(true)]
public class Component
{
public void Test()
{
System.Console.WriteLine("Component contructed");
var member = typeof(Component);
foreach (object attribute in member.GetCustomAttributes(true))
{
if (attribute is CustomAttribute)
{
//noop
}
}
}
}
[AttributeUsage(AttributeTargets.All)]
public class CustomAttribute : Attribute
{
private bool _value;
//this constructor specifes one unnamed argument to the attribute class
public CustomAttribute(bool value)
{
_value = value;
Console.WriteLine(this.ToString());
}
public override string ToString()
{
string value = "The boolean value stored is : " + _value;
return value;
}
}
}
Faced interesting problem. C# runtime throws "Not Supported" exception when I attempt to call a generic method constructed with TypeDelegator argument. Here is the example:
using System;
using System.Reflection;
using System.Linq.Expressions;
namespace ConsoleApplication2
{
public class Arg { }
public class MyTypeDelegator : TypeDelegator
{
protected override bool HasElementTypeImpl() { return false; }
}
public static class Extension
{
public static int Method<T>(this Arg arg) { return 0; }
}
class Program
{
static void Main(string[] args)
{
var methodInfo = typeof(Extension).GetMethod("Method").MakeGenericMethod(new MyTypeDelegator());
// System.NotSupportedException here:
methodInfo.Invoke(new Arg(), new Object[] { });
// and here:
var call = Expression.Call(methodInfo, new Expression[] {Expression.Constant(new Arg(), typeof(Arg)) });
}
}
}
What would be a workaround or solution for this?
PS: I cannot drop MyTypeDelegator, because it serves as a type alias for dynamic soft classes, coming from 3rd party lib. Signature and implementation of real generic Method depend on the specific data stored in the MyTypeDelegator.
First of all I know that the title is not so good but the thing is I dont even know how to explain my question; I'll just show an example below on what I'm trying to do:
EDIT: I should have given a better example to begin with; let's try again:
// MyAppComponentModel.dll
namespace MyAppComponentModel {
using System.Collections;
interface IResource { }
interface IStringResource : IResource { }
interface IIconResource : IResource { }
interface IDialogResource : IResource { }
interface IResourceProvider {
void GetResource<T>(out T result, IDictionary criteria = null) where T : IResource;
}
}
// ThirdPartyLib.dll
namespace ResourceProviderLibA {
using System.Collections;
using System.ComponentModel.Composition;
using MyAppComponentModel.
public sealed class StringResource : IStringResource { ... }
public sealed class IconResource : IIconResource { ... }
[Export(typeof(IResourceProvider))]
public sealed class StringAndIconResourceProvider : IResourceProvider {
void IResourceProvider.Get<T>(out T result, IDictionary criteria) {
if (typeof(T) == typeof(IDialogResource))
throw new NotSupportedException();
this.InternalGet(out result, criteria);
}
void InternalGet(out IStringResource result, IDictionary criteria) {
result = new StringResource();
...
}
void InternalGet(out IIconResource result, IDictionary criteria) {
result = new IconResource();
...
}
}
}
// MyMefTestApp.exe
namespace MyMefTestApp {
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using MyAppComponentModel.
static class Program {
[ImportMany(typeof(IResourceProvider))]
private IEnumerable<IResourceProvider> mProviders;
static void Main(String[] args) {
foreach (var provider in this.mProviders) {
...
}
}
}
}
I know it's somehow possible and I strongly believe I did something like this once just dont remember how. Anyone?
I already know that this can be done via Reflection so please skip those solutions - thanks.
This is not possible as T can be anything (the compiler error actually is cannot convert from 'out T' to 'out string'), not just a string or int.
Just expose the privateFoo overloads as public Foo and be done with it, there is no other way as you can't restrict a generic to string or int (both are sealed, and a generic type constraint needs an interface or non sealed class).
edit (changed question)
If your Resource implementation only have parameterless constructors, I would use this (condensed example):
interface IHostProvider
{
void Get<T> (out T result) where T : IHost, new();
}
public interface IHost
{
}
public class Something : IHost
{
}
public class Provider : IHostProvider
{
public void Get<T> (out T result) where T: IHost, new()
{
result = new T();
}
}
If they require parameters however... phew, no idea this late at night. At first I had a static factory method in mind, but as you can't require a static method in an interface nor mark it abstract, this won't work either.
Your sample seems to me impossible. Compiler can infer type arguments of method from known actual parameter types. For example:
void DoSomething<T>(T item)
{
...
}
IFoo foo = default(IFoo);
DoSomething(foo); // void DoSomething<IFoo>(IFoo item);
But compiler can't do opposite. Compiler can't guess T's actual type and that's why it can't select applicable method overload.
void DoSomething(IFoo foo)
{
...
}
T item = default(T);
DoSomething(item); // won't compile unless it is known that T is IFoo (where T : IFoo)