22 Kasım 2018 Perşembe

Type Sınıfı

Giriş
Bu sınıf Type ve TypeInfo olarak ikiye ayrıldı. Evolving the Reflection API yazısında açıklaması okunabilir.

Bu sınıf reflection için çokça kullanılır. Açıklaması şöyle
Reflection provides objects (of type Type) that describe assemblies, modules and types. You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object
Bu sınıfı elde etmenin yolu typeof() çağrısı yapmak. Şöyle yaparız.
typeof(Foo)

BaseType Alanı
Açıklaması şöyle
If your class is not inheriting or is only implementing interface(s) then it would return Object, otherwise your Parent Class Type.
Ata sınıfı verir.
Örnek
Şöyle yaparız.
Type type = ...;
Type parentType = type.BaseType.
Örnek
Şöyle yaparız.
public void doStuff<T>() where T : class 
{
  Type foo = typeof(T).BaseType;
}
FullName Alanı
Şöyle yaparız.
void WriteFullName(Type t)
{
  Console.WriteLine(t.FullName);
}
GetConstructor metodu
Şöyle yaparız.
var constructor = typeof(T).GetConstructor(null);
GetCustomAttributes metodu
Sınıfın tanımladığı veya kalıtımla gelen System.Attribute tipinden veriyi verir. Şöyle yaparız.
[AttributeUsage(Inherited=true)]
public class FooAttribute : System.Attribute
{
    private string name;

    public FooAttribute(string name)
    {
        this.name = name;
    }

    public override string ToString() { return this.name; }
}

[Foo("hello")]
public class BaseClass {}

public class SubClass : BaseClass {}

// outputs "hello"
Console.WriteLine(typeof(SubClass).GetCustomAttributes().First());
GetDeclaringType Alanı
Kalıtım ile gelen property'leri elemek için şöyle yaparız.
var childPropertiesOnly = typeof(Child)
  .GetProperties()
  .Where(x => x.DeclaringType != typeof(Father))
  .ToList();
GetGenericArguments metodu
Örnek
Elimizde bir liste olsun.
var listItem = new List<string> { "alex", "aa" };
Listenin generic tipini - ki örnekte string'dir - bulmak için şöyle yaparız.
var typeOfGeneric = listItem.GetType().GetGenericArguments().First<Type>();
Örnek
Elimizde bir kalıtım hiyerarşisi olsun
public class Foo<T>
{
  ...
}

public class Bar<T, F> : Foo<T>
{
  ...
}
Şöyle yaparız.
var list = new List<Foo<string>>();
list.Add(new Bar<string, int>() {...});

foreach (var x in list)
{
  Type[] types = x.GetType().GetGenericArguments();

  // Dirty check to confirm this is an Bar not a Foo
  if (types.Length == 2)
  {
    ...
  }
}
GetGenericTypeDefinition metodu
Tipin belli bir generic arayüzü gerçekleştirip gerçekleştirmediğini anlamak için şöyle yaparız.
Type type = ...;
if(
    type.IsGenericType && 
    type.GetGenericTypeDefinition() == typeof(IChild<>)
)
Şöyle de yapılabilir.
type.GetGenericTypeDefinition().IsAssignableFrom(typeof(IChild<>)));
Ata sınıfları dolaşarak belli bir generic sınıftan kalıtım olduğunu bulmak için şöyle yaparız.
Ata arayüzleri dolaşarak belli bir generic sınıftan kalıtım olduğunu bulmak için şöyle yaparız.

GetInterfaces metodu
Bir Assembly içindeki IRead<> arayüzünü gerçekleştiren tipleri bulmak için şöyle yaparız.
var types = GetType().Assembly.GetTypes()
.Select(t => new
{
  Type = t,
  MatchingInterfaces = t.GetInterfaces()
                    .Where(i => i.GetGenericTypeDefinition() == typeof(IRead<>))
})
.Where(t => t.MatchingInterfaces.Any())
GetMember metodu
Enum'larda ismi belirtilen enum hakkında bilgi döner.

GetMembers metodu
Şöyle yaparız.
var members = typeof(class1).GetMembers(BindingFlags.Static | BindingFlags.Public);
GetMethod metodu
Şöyle yaparız. Eğer metod overload edilmiş ise System.Reflection.AmbiguousMatchException fırlatılır.
Type t = ...;
MethodInfo methodInfo = t.GetMethod("Start");
GetMethod metodu - Type Dizisi
Metod imzasındaki parametre tipleri kullanılır. Şöyle yaparız.
Type t = ...;
MethodInfo methodInfo = t.GetMethod("Start", new Type[] {typeof(DateTime)} );
GetMethods metodu
Nesneye ait public olan, kalıtımla gelmeyen metodları şöyle alırız.
var type = typeof (Foo);

MethodInfo[] methods = type
  .GetMethods(BindingFlags.Instance | 
              BindingFlags.Public | 
              BindingFlags.DeclaredOnly)
  .ToList();
Nesneye ait public ve olmayan tüm metodları şöyle alırız.
var type = typeof (Foo);

MethodInfo[] methods = type
  .GetMethods(BindingFlags.Instance | 
              BindingFlags.Public | 
              BindingFlags.NonPublic)
  .ToList();
GetProperty metodu
Sınıflarda ismi belirtilen property hakkında bilgi döner. Şöyle yaparız. Sonuç null dönebilir.
string field = ...;
Type t = ...;
PropertyInfo propertyInfo = t.GetProperty(field);
GetProperties metodu
Bir sınıfın tanımladığı ve kalıtımla devraldığı tüm public property'leri döndürür.

Örnek
Bir dizi döndüğü için dizinin metodlarını kullanarak şöyle yaparız.
Type type = ...;
int Count = type.GetProperties().Count();
Örnek
Dizi Linq ile de kullanılabilir. Şöyle yaparız.
bool isNull = type.GetProperties()
                  .All(p => p.GetValue(objRequirement) != null);
GetProperties metodu - BindingFlags
Örnek
Elimizde kalıtım olsun.
public class BaseClass
{    
  public string BaseProperty{get;set;}    
}

public class ChildClass: BaseClass    
{    
  public string ChildProperty{get;set;}    
}
Sadece ChildClass'ın tanımladığı property'lere erişmek için şöyle yaparız.
PropertyInfo[] infos = typeof(ChildClass).GetProperties(
  BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
Açıklaması şöyle
DeclaredOnly: Specifies that only members declared at the level of the supplied type's hierarchy should be considered. Inherited members are not considered.
Aynı şeyi şöyle de yapabiliriz.
foreach (PropertyInfo info in typeof(T).GetProperties()
        .Where(x=>x.DeclaringType == typeof(T))) // filtering by declaring type
{
  propertyNames.Add(info.Name);
}
Örnek
Şöyle yaparız.
PropertyInfo[] p = typeof(myclass).GetProperties(BindingFlags.Public | 
                                                 BindingFlags.Instance);
GetTypeIDFromProgID metodu
Activator Sınıfı yardımı ile bir COM nesnesi yaratır. Şöyle yaparız.
var t = Type.GetTypeFromProgID("Application",null);
var app1 = Activator.GetInstance(t);
Şöyle yaparız.
System.Type type = Type.GetTypeFromProgID("VisualStudio.DTE.14.0");
EnvDTE.DTE dte = (EnvDTE.DTE)System.Activator.CreateInstance(type); 
IsAssignableFrom metodu
Açıklaması şöyle.
Type.IsAssignableFrom (Type c) Returns true if any of the following conditions is true:
  1. c and the current instance represent the same type.
  2. c is derived either directly or indirectly from the current instance. c is derived directly from the current instance if it inherits from the current instance; c is derived indirectly from the current instance if it inherits from a succession of one or more classes that inherit from the current instance.
  3. The current instance is an interface that c implements.
  4. c is a generic type parameter, and the current instance represents one of the constraints of c.
and false if none of these conditions are true, or if c is null.
Örnek
Bir tipin List<T> olup olmadığını şöyle kontrol ederiz.
if (property.PropertyType.IsGenericType && 
typeof(List<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition()))
{...}
Örnek
Şöyle yaparız.
var type1 = typeof(List<object>);
var type2 = typeof(IEnumerable<object>);

//returns true
type2.IsAssignableFrom(type1);
IsGenericType Alanı
Şöyle yaparız.
if (property.PropertyType.IsGenericType) {...}
IsPrimitive Alanı
Şöyle yaparız.
Type type = ...;
if ( (type.IsPrimitive) {...} 
IsSubclassOf metodu
Örnek ver.

IsValueType Alanı
Şöyle yaparız.
Type type = ...;
if ( type.IsValueType) {...}
MakeArrayType metodu
Açıklaması şöyle
The common language runtime makes a distinction between vectors (that is, one-dimensional arrays that are always zero-based) and multidimensional arrays. A vector, which always has only one dimension, is not the same as a multidimensional array that happens to have only one dimension. You cannot use this method overload to create a vector type; if rank is 1, this method overload returns a multidimensional array type that happens to have one dimension. Use the MakeArrayType() method overload to create vector types.
SBir vector yaratmak için şöyle yaparız.
var type = typeof(object).MakeArrayType(1);
// Create an instance with length 2
var array = Activator.CreateInstance(type, 2);
Console.WriteLine(array.GetType());            // System.Object[]
Console.WriteLine(type);                       // System.Object[*]
Name Alanı
Verilen sınıfın ismini döner
Örnek
Şöyle yaparız.
Type type = typeof(string);
type.Name //Yine string alırız
Örnek
Eğer sınıf generic ise kaç tane generic parametre aldığı isme ekenir. Şöyle yaparız.
// Dictionary`2 - two generic parameters
 Console.WriteLine(typeof(Dictionary<int, string>).Name);

 // List`1 - one generic parameter
 Console.WriteLine(typeof(List<int>).Name);
Generic parametre almayan sınıflarda şu çıktıyı alırız.
// IDictionary`2 - two generic parameters
 Console.WriteLine(typeof(IDictionary<int, string>).Name);

 // IDictionary - no generic parameters
 Console.WriteLine(typeof(System.Collections.IDictionary).Name);
ToString metodu
Örnek
Şöyle yaparız.
byte b = ...;
Console.WriteLine(B.GetType()); // Outputs "Byte"
Örnek
Elimizde bir hiyerarşi olsun.
class Plant{}
class Flower:Plant{}
Şöyle yaparız.
Flower Rose = new Flower();
Plant RoseBush = (Plant)Rose;
Console.WriteLine(RoseBush.GetType()); //Outputs Flower

Plant Rose = new Flower();
Plant RoseBush = (Plant)Rose;
Console.WriteLine(RoseBush.GetType()); //Outputs Flower as well
Diğer
Generics'ten System.Type sınıfına dönmek için typeof () kullanılır. Elimizde key alanı System.Type olan bir Dictionary olsun.
public class DelegateDictionary
{
  Dictionary<Type, Delegate> dic;

  public DelegateDictionary()
  {
    dic = new Dictionary<System.Type, Delegate>();
  }

  public void Add<T>(Func<T, string, string, XmlElement> mtd)
  {
    dic.Add(typeof(T), mtd);
  }

  public XmlElement Invoke<T>(T value, string name, string namespaceURI)
  {
    if (!Lookup.TryGetValue(typeof(T), out var del))
      throw new InvalidOperationException($"No delegate registered for {typeof(T).Name}");

    var typedDel = (Func<T, string, string, XmlElement>)del;
    return typedDel(value, name, namespaceURI);
  }
}
Kullanmak için şöyle yaparız.
// example usage
{
    var dict = new DelegateDictionary();

    dict.Add<string>(ElementCreators.CreateElementForString);
    dict.Add<Decimal>(ElementCreators.CreateElementForDecimal);

    dict.Invoke("stringValue", "myName", "what-even-is-a-namespace");
    dict.Invoke(1.0m, "myName", "what-even-is-a-namespace");
}

Hiç yorum yok:

Yorum Gönder