Let's imagine that we have a class called A, and this class is inherited from class B, and also class B inherited from class C. We can extend this sequence as long as we want. How can we get all classes from this sequence? Like:
A
B
C
...
Try this code:
Type type = typeof(C);
while (type.BaseType!=null)
{
type = type.BaseType;
Console.WriteLine(type.Name);
}
// C
// B
// A
// Object
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
foreach (Type type in assembly.GetTypes())
{
if (typeof(A).IsAssignableFrom(type))
Console.WriteLine(type);
}
// These can be in various projects / assemblies
class A { }
class B : A { }
class C : A { }
class D : B { }
class E { }
class F : E { }
class G : D { }
Prints:
A
B
C
D
G
Related
So, I have the following structure:
public abstract class MyBase
{
public Type TargetType { get; protected set; }
}
public class A : MyBase
{
public A()
{
TargetType = GetType();//Wrong, I need B class type not C
}
}
public class B : A
{
public B() { }
}
public class C : B
{
public C() { }
}
Of course, I can receive my type in this way:
public class B : A
{
public B()
{
TargetType = typeof(B);
}
}
Actually, I have to write some code to make the example clearer:
Class1.cs
public static Dictionary<Type, Type> MyTypes = new Dictionary<Type, Type>()
{
{ typeof(B),typeof(BView) }
}
public Class1()
{
C itemC = new C();
Class2.Initialize(itemC);
}
Class2.cs
public static Initialize(MyBase myBase)
{
Type t;
Class1.MyTypes.TryGetValue(myBase.TargetType, out t);
//I need get BView but I get null because *myBase.TargetType* is C class type
}
Level structure:
Level 0:(MyBase) - 1 object
Level 1:(A) - 2 objects
Level 2:(B) - 100 objects and more
Level 3:(C) - 80 objects and more
I gave this case in brackets
I will be grateful for any help
On any instance of an object you can call .GetType() to get the type of that object.
You don't need to set the type on construction
I didn't understand completely your question, but these are some possibilities to get informations about a type:
var a = new A();
Console.WriteLine(a.GetType().Name); // Output: A
Console.WriteLine(a.GetType().BaseType?.Name); // Output: MyBase
var b = new B();
Console.WriteLine(b.GetType().Name); // Output: B
Console.WriteLine(b.GetType().BaseType?.Name); // Output: A
// A simple loop to get to visit the derivance chain
var currentType = b.GetType();
while (currentType != typeof(object))
{
Console.WriteLine(currentType.Name);
currentType = currentType.BaseType;
}
// Output: B A MyBase
Also, I suggest to read this post about the difference between GetType and typeof
Hope this helps.
Consider the following classes:
class A
{
public virtual string Name { get { return "A"; } }
}
class B : A
{
public override string Name { get { return "B"; } }
}
class C : A
{
public override string Name { get { return "C"; } }
}
And a list containing two objects of type B and one of type C:
List<A> l = new List<A>();
l.Add(new B());
l.Add(new C());
l.Add(new B());
Is there some way to force a check of the type at runtime and iterate only over the objects of type B in this list (short of writing a custom implementation of a list)? Something like:
foreach (B obj in l) // runtime error
Console.WriteLine(obj.Name);
// desired output:
// B
// B
I haven't run into this problem in a project, but the thought just occurred to me and I'm curious if this can be done. I'm aware the need for this feature could indicate a design flaw.
You can use .OfType<T>():
foreach (B obj in l.OfType<B>())
Console.WriteLine(obj.Name);
If you want only Bs, and not any subclasses of B to be listed, you can use the following:
foreach (B obj in l.Where(o => o.GetType() == typeof(B)))
Console.WriteLine(obj.Name);
foreach (A obj in l)
{
if (obj is B)
{
Console.WriteLine(obj.Name);
}
}
I have this code to get "A" as a filtered result.
public static void RunSnippet()
{
Base xbase = new Base();
A a = new A();
B b = new B();
IEnumerable<Base> list = new List<Base>() { xbase, a, b };
Base f = list.OfType<A>().FirstOrDefault();
Console.WriteLine(f);
}
I need to use IEnumerable<Base> list = new List<Base>() {xbase, a, b}; from a function as follows:
public static Base Method(IEnumerable<Base> list, Base b (????)) // I'm not sure I need Base b parameter for this?
{
Base f = list.OfType<????>().FirstOrDefault();
return f;
}
public static void RunSnippet()
{
Base xbase = new Base();
A a = new A();
B b = new B();
IEnumerable<Base> list = new List<Base>() { xbase, a, b };
//Base f = list.OfType<A>().FirstOrDefault();
Base f = Method(list);
Console.WriteLine(f);
}
What parameter do I use in '????' to get the same result from the original code?
It seems like you are looking for a generic way to do what is in Method based on different children types of Base. You can do that with:
public static Base Method<T>(IEnumerable<Base> b) where T: Base
{
Base f = list.OfType<T>().FirstOrDefault();
return f;
}
This will return the first instance from b that is of type T (which has to be a child of Base).
If you want to query on a type, you can try something like this:
public static Base Method(IEnumerable<Base> list, Type typeToFind)
{
Base f = (from l in list
where l.GetType()== typeToFind
select l).FirstOrDefault();
return f;
}
If it's not what you are searching for, please clarify.
How can I implement this:
I have 3 types (actually Interface): A , B and C
A has no methods, but B and C have some methods.
I want the type A in some situations can be cast to type B and use B methods and in other situation cast to type C and use its methods?
class Program
{
interface A { }
interface B :A { void b(); } // B inherits from A
interface C :A { void c(); } // C also inherits from A
static void Main()
{
// declare vars
A a = null;
B b = null;
C c = null;
// a can happily hold references for B.
a = b;
// To call B's methods you need to cast it to B.
((B)a).b();
// a can happily hold references for C.
a = c;
// To call C's methods you need to cast it to C.
a = c;
((C)a).c();
}
}
From your comments
class Program
{
private interface A { }
private interface B : A { string b();}
private interface C : A { string c();}
class BClass : B { public string b() { return "B"; } }
class CClass : C { public string c() { return "C"; } }
private static void Main()
{
A a = null;
B b = new BClass();
C c = new CClass();
a = b;
((B)a).b();
a = c;
((C)a).c();
}
}
You can do Type[] interfaces = typeof(MyClass).GetInterfaces(); to get a list of everything a class implements implements.
I am wondering if there is anyway to crawl the "extends" tree to see all the base types a class inherits, i.e. abstract classes etc.?
You can use Type.BaseType to traverse from the top-level type to the most base type until the base type reaches object.
Something like this:
abstract class A { }
class B : A { }
class C : B { }
public static void Main(string[] args)
{
var target = typeof(C);
var baseTypeNames = GetBaseTypes(target).Select(t => t.Name).ToArray();
Console.WriteLine(String.Join(" : ", baseTypeNames));
}
private static IEnumerable<Type> GetBaseTypes(Type target)
{
do
{
yield return target.BaseType;
target = target.BaseType;
} while (target != typeof(object));
}
I use this code to get all classes that inherits a defined Type. It searches all loaded Assemblies. Usefull if you have only the Baseclass and you will get all Classes that Extends the Baseclass.
Type[] GetTypes(Type itemType) {
List<Type> tList = new List<Type>();
Assembly[] appAssemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly a in appAssemblies) {
Module[] mod = a.GetModules();
foreach (Module m in mod) {
Type[] types = m.GetTypes();
foreach (Type t in types) {
try {
if (t == itemType || t.IsSubclassOf(itemType)) {
tList.Add(t);
}
}
catch (NullReferenceException) { }
}
}
}
return tList.ToArray();
}