2012-05-22 13 views
6

Şu anda bir nesne oluşturmak ve özellikleri değerlerle doldurmak gibi bazı dinamik yöntemler yapmak için Generic'i kullanıyorum.Bir türden genel değişkenler oluşturma - How? Veya Activator.CreateInstance() parametrelerini() yerine {} özellikleriyle birlikte kullanın?

Türü bilmeden "dinamik olarak" Genel oluşturmak için herhangi bir yolu var mı? Örneğin:

List<String> = new List<String>() 

bir predefinied yoldur, ama

List<(object.GetType())> = new List<(object.GetType()>() 

çalışma ... Ama can değil mi? nasıl bir "Type" almaya ve Genellemelere kullanmadan o bir nesneyi oluşturun:

Bu

(? çalışan bir benzer bir yaklaşım var mı)

public T CreateObject<T>(Hashtable values) 
    { 
     // If it has parameterless constructor (I check this beforehand) 
     T obj = (T)Activator.CreateInstance(typeof(T)); 

     foreach (System.Reflection.PropertyInfo p in typeof(T).GetProperties()) 
     { 
      // Specifically this doesn't work 
      var propertyValue = (p.PropertyType)values[p.Name]; 
      // Should work if T2 is generic 
      // var propertyValue = (T2)values[p.Name]; 

      obj.GetType().GetProperty(p.Name).SetValue(obj, propertyValue, null); 
     } 
    } 

Yani, kısacası çalışmıyor? Şu ana kadar sadece Generics'i kullandım, ama aynı şekilde değişkenler üzerinde kullanmak mümkün mü? Yöntemden önce bir Genel (T) tanımlamalıyım, bu yüzden onları "oluşturmadan" önce değişkenler üzerinde de yapabilir miyim?

... veya Parametreler yerine Özellikler ile bir nesne oluşturmak için "Etkinleştirici" nasıl kullanılır. Burada yaptığınız gibi: parametrelerle

// değerleri

özellikleri

Test t = new Test { Argument1 = "Hello", Argument2 = 123 }; 

cevap

13

kullanabilirsiniz MakeGenericType:

Type openListType = typeof(List<>); 
Type genericListType = openListType.MakeGenericType(obj.GetType()); 
object instance = Activator.CreateInstance(genericListType); 
+0

Bu durumda "Liste" yi kullanmak istemiyorum, herhangi bir nesne olmalı. "Type openListType = typeof (bilinmeyen tip);" – Deukalion

+0

Bu cevabın OP'yi nasıl çözdüğünü anlamıyorum. "Activator.CreateInstance() özelliğini {} yerine"() parametresiyle birlikte kullanın. " – Avishek

1

ile

Test t = new Test("Argument1", Argument2); 

// Eğer nesne başlatıcı, sadece bir varsayılan kurucu kullanıyor (hayır parametreleri) kullandığınızda, Nesne oluşturulduktan sonra bireysel özellikleri ayarlayarak.

Yukarıdaki kod yakındır - ancak var burada çalışmayacaktır, çünkü bu yalnızca bir derleme zamanı türünün çıkarımıdır. Zaten yansıma kullandığınız için, sadece System.Object kullanabilirsiniz:

object propertyValue = values[p.Name]; 

SetValue çağrı System.Object ile iyi çalışır.

+0

Peki nasıl "Nesne ile Activator.CreateInstance kullanabilirsiniz başlatıcı "argüman olarak? "Bu nesne için tanımlanmış hiçbir parametresiz kurucu yok" şeklinde bir hata alıyorum. Değer eklemeye çalıştığım özellik türleri şunlardır: String, Double, enum, bool. Başarısız olduğu tür "Dize" dir. Parametresiz bir kurucu yoktur, bu yüzden bir String oluşturamıyorum ve buna değer ekleyemem, ancak tanımlayabildiğimden bu nasıl olabilir: String str; veya String str = "Bu bir dizedir"; – Deukalion

+0

@Deukalion Oluşturduğunuz türün parametresiz bir kurucusu yok - dolayısıyla bu tekniği onunla kullanamazsınız ... –

+0

'String str =" Foo ";' sözdizimi bir C# dilidir, bir CLR özelliği. –

5

Belirli bir tip argüman için genel tür almak için MakeGenericType yöntemi kullanabilirsiniz:

var myObjListType = typeof(List<>).MakeGenericType(myObject.GetType()); 
var myObj = Activator.CreateInstance(myObjListType); 
// MyObj will be an Object variable whose instance is a List<type of myObject> 
+0

Ama yarattığım nesnenin bir "String, boolean, int, float ..." olduğunu ve mutlaka bir ders olmadığını söyle. Nesneler özelliğini değere ayarlamadan önce ona bir değer ayarlamanız gerekirse. – Deukalion

+0

Değer türleri için bir değer ayarlamanız gerekmez; bunlar otomatik olarak geçerli bir varsayılan değere sahiptir. Örneğin, 'bool' türünde bir alanın 'false' olarak başlatılması gerekmez, çünkü bu otomatik olarak gerçekleşir. Dizeler için sıfırdan başlarlar. "Fred" gibi başka bir değere sahip olmalarını istiyorsanız, onların değerini "Fred" olarak ayarlamanız gerekir. Person.FirstName = yeni String ("Fred") değil; –

İlgili konular