2016-12-01 19 views
8

czytałem rodzaj kompletów załadowanych na przykład Zadzwoń:Reflection - konstruktor z parametrami

var someType = loadedAssemblies 
      .Where(a => a != null && a.FullName.StartsWith("MY.")) 
      .SelectMany(a => a.GetTypes()) 
      .Distinct() 
      .ToArray()[0]; 

Jeśli counstructor posiada parametry, mogę je czytać:

ParameterInfo[] parameters = classType.GetConstructors()[0].GetParameters(); 

chciałbym wywołać konstruktora z domyślnymi wartości parametrów lub jeśli parametr jest wyliczany, z pierwszą wartością wyliczeniową. Jeśli jest tylko jeden parametr i jest enum, to działa tak:

object curObject = Activator.CreateInstance(classType, new object[] { parameters[0].ParameterType.GetEnumValues().GetValue(0) }); 

Jak mogę to zrobić, gdy istnieje więcej parametrów? trzeba utworzyć obiekt, aby odczytać właściwość:

var propertyInfo = someType.GetProperty("EntityType"); 
string entityType = propertyInfo.GetValue(curObject, null).ToString(); 

Odpowiedz

5

Cóż, można stworzyć swój własny zakład i napisać metodę, że kontrole konstruktorzy Type jest z ich domyślnymi parametrami:

public static class MyFactory 
{ 
    public static T MyCreateInstance<T>() 
     where T : class 
    { 
     return (T) MyCreateInstance(typeof (T)); 
    } 

    public static object MyCreateInstance(Type type) 
    { 
     var ctor = type 
      .GetConstructors() 
      .FirstOrDefault(c => c.GetParameters().Length > 0); 

     return ctor != null 
      ? ctor.Invoke 
       (ctor.GetParameters() 
        .Select(p => 
         p.HasDefaultValue? p.DefaultValue : 
         p.ParameterType.IsValueType && Nullable.GetUnderlyingType(p.ParameterType) == null 
          ? Activator.CreateInstance(p.ParameterType) 
          : null 
        ).ToArray() 
       ) 
      : Activator.CreateInstance(type); 
    } 
} 

A potem można użyć tej metody:

var classType = loadedAssemblies 
      .Where(a => a != null && a.FullName.StartsWith("MY.")) 
      .SelectMany(a => a.GetTypes()) 
      .Distinct() 
      .ToArray()[0]; 

var curObject = MyFactory.MyCreateInstance(classType); 

// This will return an array of values 

object[] values = classType 
       .GetFields() 
       .Select(f => f.GetValue(curObject)) 
       .ToArray(); 

P.S. Oto DotNet fiddle example.

Aktualizacja:

Kod zmienia się w zależności od scenariusza pracować. Teraz mamy dwie metody: jeden zwracany obiekt i inny, który można przekonwertować na typ T.

Zaktualizowałem również DotnetFiddle, proszę to sprawdzić.

+0

Cześć Fabjan, dziękuję za to rozwiązanie. Jest jeden problem. Mam tylko classType, które czytałem w czasie wykonywania. Nie wiem dla nazwy obiektu (klasy) podczas kompilacji. Twój kod: var curObject = MyFactory.MyCreateInstance (classType); nie działa ze słowem kluczowym object. – Simon

+0

Zaktualizowałem moją odpowiedź, a także przykład kodu na DotNetfiddle – Fabjan

+0

Dziękuję, działa idealnie.Czy znasz różnicę między constructor.Invoke vs Activator.CreateInstance? – Simon

2

Można dokonać metody pomocnika, aby uzyskać wartość domyślną typu:

private static object GetDefaultValue(Type type) 
{ 
    if (type.IsEnum) return type.GetEnumValues().GetValue(0); 
    if (type.IsValueType) return Activator.CreateInstance(type); 
    return null; 
} 

Następnie można uzyskać wartości domyślnych parametrów:

var parameters = constructor.GetParameters() 
          .Select(p => GetDefaultValue(p.ParameterType)) 
          .ToArray(); 

I wywołać ConstructorInfo uzyskać instancję:

var obj = constructor.Invoke(parameters); 

Jeśli parametry konstruktora mają wartości domyślne i chcesz je wykorzystać, można zrobić coś takiego:

var parameters = constructor 
    .GetParameters() 
    .Select(p => p.HasDefaultValue ? p.RawDefaultValue : GetDefaultValue(p.ParameterType)) 
    .ToArray(); 
+0

Arturo, czym różni się constructor.Invoke vs Activator.CreateInstance? Czy możesz zrobić to samo z Activator.CreateInstance? – Simon

+0

@Simon: 'Constructor.Invoke' bezpośrednio wywoła ten konstruktor. 'Activator.CreateInstance' tworzy instancję znajdującą konstruktora, który najlepiej pasuje do określonych parametrów. –