Kaip sukurti naują objekto egzempliorių iš tipo

Galbūt ne visada žinote objekto Type kompiliavimo metu, tačiau gali tekti sukurti Type . Kaip gausite naują objekto egzempliorių iš Type ?

601
03 авг. nustatyti kaip tags2k 03 rug . 2008-08-03 19:29 '08 at 7:29 pm 2008-08-03 19:29
@ 12 atsakymų

Activator klasė root System vardų erdvėje yra gana veiksminga.

Yra daug perkrovos, skirtos parametrams perduoti konstruktoriui ir pan. Patikrinkite dokumentaciją:

http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx

arba (naujas kelias)

https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance

Štai keletas paprastų pavyzdžių:

 ObjectType instance = (ObjectType)Activator.CreateInstance(objectType); ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType"); 
757
03 авг. Karl Seguino atsakymas 03 rugpjūčio 3 d. 2008-08-03 19:35 '08, 19:35, 2008-08-03 19:35
 ObjectType instance = (ObjectType)Activator.CreateInstance(objectType); 

Activator klasė turi bendrą versiją, kuri leidžia ją šiek tiek paprasčiau:

 ObjectType instance = Activator.CreateInstance<ObjectType>(); 
119
25 авг. atsakymą pateikė Konradas Rudolphas 25 d. 2008-08-25 16:33 '08 at 4:33 pm 2008-08-25 16:33

Sukurta išraiška yra geriausias būdas! (norint atlikti našumą, pakartotinai sukurkite egzempliorių vykdymo metu).

 static readonly Func<X> YCreator = Expression.Lambda<Func<X>>( Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes)) ).Compile(); X x = YCreator(); 

Statistika (2012 m.):

  Iterations: 5000000 00:00:00.8481762, Activator.CreateInstance(string, string) 00:00:00.8416930, Activator.CreateInstance(type) 00:00:06.6236752, ConstructorInfo.Invoke 00:00:00.1776255, Compiled expression 00:00:00.0462197, new 

Statistika (2015, .net 4.5, x64):

  Iterations: 5000000 00:00:00.2659981, Activator.CreateInstance(string, string) 00:00:00.2603770, Activator.CreateInstance(type) 00:00:00.7478936, ConstructorInfo.Invoke 00:00:00.0700757, Compiled expression 00:00:00.0286710, new 

Statistika (2015 m., .Net 4.5, x86):

  Iterations: 5000000 00:00:00.3541501, Activator.CreateInstance(string, string) 00:00:00.3686861, Activator.CreateInstance(type) 00:00:00.9492354, ConstructorInfo.Invoke 00:00:00.0719072, Compiled expression 00:00:00.0229387, new 

Statistika (2017, LINQPad 5.22.02 / x64 / .NET 4.6):

  Iterations: 5000000 No args 00:00:00.3897563, Activator.CreateInstance(string assemblyName, string typeName) 00:00:00.3500748, Activator.CreateInstance(Type type) 00:00:01.0100714, ConstructorInfo.Invoke 00:00:00.1375767, Compiled expression 00:00:00.1337920, Compiled expression (type) 00:00:00.0593664, new Single arg 00:00:03.9300630, Activator.CreateInstance(Type type) 00:00:01.3881770, ConstructorInfo.Invoke 00:00:00.1425534, Compiled expression 00:00:00.0717409, new 

Visas kodas:

 static X CreateY_New() { return new Y(); } static X CreateY_New_Arg(int z) { return new Y(z); } static X CreateY_CreateInstance() { return (X)Activator.CreateInstance(typeof(Y)); } static X CreateY_CreateInstance_String() { return (X)Activator.CreateInstance("Program", "Y").Unwrap(); } static X CreateY_CreateInstance_Arg(int z) { return (X)Activator.CreateInstance(typeof(Y), new object[] { z, }); } private static readonly System.Reflection.ConstructorInfo YConstructor = typeof(Y).GetConstructor(Type.EmptyTypes); private static readonly object[] Empty = new object[] { }; static X CreateY_Invoke() { return (X)YConstructor.Invoke(Empty); } private static readonly System.Reflection.ConstructorInfo YConstructor_Arg = typeof(Y).GetConstructor(new[] { typeof(int), }); static X CreateY_Invoke_Arg(int z) { return (X)YConstructor_Arg.Invoke(new object[] { z, }); } private static readonly Func<X> YCreator = Expression.Lambda<Func<X>>( Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes)) ).Compile(); static X CreateY_CompiledExpression() { return YCreator(); } private static readonly Func<X> YCreator_Type = Expression.Lambda<Func<X>>( Expression.New(typeof(Y)) ).Compile(); static X CreateY_CompiledExpression_Type() { return YCreator_Type(); } private static readonly ParameterExpression YCreator_Arg_Param = Expression.Parameter(typeof(int), "z"); private static readonly Func<int, X> YCreator_Arg = Expression.Lambda<Func<int, X>>( Expression.New(typeof(Y).GetConstructor(new[] { typeof(int), }), new[] { YCreator_Arg_Param, }), YCreator_Arg_Param ).Compile(); static X CreateY_CompiledExpression_Arg(int z) { return YCreator_Arg(z); } static void Main(string[] args) { const int iterations = 5000000; Console.WriteLine("Iterations: {0}", iterations); Console.WriteLine("No args"); foreach (var creatorInfo in new[] { new {Name = "Activator.CreateInstance(string assemblyName, string typeName)", Creator = (Func<X>)CreateY_CreateInstance}, new {Name = "Activator.CreateInstance(Type type)", Creator = (Func<X>)CreateY_CreateInstance}, new {Name = "ConstructorInfo.Invoke", Creator = (Func<X>)CreateY_Invoke}, new {Name = "Compiled expression", Creator = (Func<X>)CreateY_CompiledExpression}, new {Name = "Compiled expression (type)", Creator = (Func<X>)CreateY_CompiledExpression_Type}, new {Name = "new", Creator = (Func<X>)CreateY_New}, }) { var creator = creatorInfo.Creator; var sum = 0; for (var i = 0; i < 1000; i++) sum += creator().Z; var stopwatch = new Stopwatch(); stopwatch.Start(); for (var i = 0; i < iterations; ++i) { var x = creator(); sum += xZ; } stopwatch.Stop(); Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name); } Console.WriteLine("Single arg"); foreach (var creatorInfo in new[] { new {Name = "Activator.CreateInstance(Type type)", Creator = (Func<int, X>)CreateY_CreateInstance_Arg}, new {Name = "ConstructorInfo.Invoke", Creator = (Func<int, X>)CreateY_Invoke_Arg}, new {Name = "Compiled expression", Creator = (Func<int, X>)CreateY_CompiledExpression_Arg}, new {Name = "new", Creator = (Func<int, X>)CreateY_New_Arg}, }) { var creator = creatorInfo.Creator; var sum = 0; for (var i = 0; i < 1000; i++) sum += creator(i).Z; var stopwatch = new Stopwatch(); stopwatch.Start(); for (var i = 0; i < iterations; ++i) { var x = creator(i); sum += xZ; } stopwatch.Stop(); Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name); } } public class X { public X() { } public X(int z) { this.Z = z; } public int Z; } public class Y : X { public Y() {} public Y(int z) : base(z) {} } 
91
30 апр. atsakymas pateikiamas Serj-Tm balandžio 30 d. 2015-04-30 19:13 '15, 19:13, 2015-04-30 19:13

Vienas iš šios problemos įgyvendinimo būdų yra bandyti skambinti konstruktoriui be tipo parametrų:

 public static object GetNewObject(Type t) { try { return t.GetConstructor(new Type[] { }).Invoke(new object[] { }); } catch { return null; } } 

Čia pateikiamas toks pats metodas, kuris pateikiamas bendrame metode:

 public static T GetNewObject<T>() { try { return (T)typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { }); } catch { return default(T); } } 
38
03 авг. atsakymas pateikiamas žodžiu2k 03 rug . 2008-08-03 19:31 '08 at 7:31 pm 2008-08-03 19:31

Jei tai yra kažkas, kas bus daug vadinama programos pavyzdžiu, dinamišką kodą, o ne naudojant aktyvatorių arba ConstructorInfo.Invoke() , yra daug greičiau surinkti ir talpinti. Dvi paprastos dinaminio kompiliavimo versijos yra kompiliuojamos Linq išraiškos arba kai kurie paprasti IL DynamicMethod ir DynamicMethod . Bet kuriuo atveju, skirtumas bus didžiulis, kai pradėsite gauti griežtas kilpas ar kelis skambučius.

12
25 авг. Thomas G. Mayfield atsakymas 25 rugpjūčio mėn. 2008-08-25 16:31 '08 at 4:31 pm 2008-08-25 16:31

Tai gana paprasta. Tarkime, kad jūsų klasės pavadinimas yra „ Car o vardų sritis yra „ Vehicles , tada perduokite parametrą kaip „ Vehicles.Car . Be to, galite sukurti bet kurios klasės egzempliorių dinamiškai.

 public object GetInstance(string strNamesapace) { Type t = Type.GetType(strNamesapace); return Activator.CreateInstance(t); } 

Jei jūsų visiškai kvalifikuotas pavadinimas (t. Y. Vehicles.Car priemonės.karjeras šiuo atveju) yra kitoje surinkimo Type.GetType , Type.GetType bus nulinis. Tokiais atvejais pereikite per visas sąrankas ir suraskite Type . Tam galite naudoti toliau pateiktą kodą.

 public object GetInstance(string strFullyQualifiedName) { Type type = Type.GetType(strFullyQualifiedName); if (type != null) return Activator.CreateInstance(type); foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) { type = asm.GetType(strFullyQualifiedName); if (type != null) return Activator.CreateInstance(type); } return null; } 

Ir galite gauti pavyzdį skambindami aukščiau nurodytu būdu.

 object objClassInstance = GetInstance("Vehicles.Car"); 
12
03 нояб. Atsakymą pateikė Sarath Avanavu 03.11 . 2014-11-03 09:11 '14, 9:11 AM 2014-11-03 09:11

Nenaudojant atspindžio:

 private T Create<T>() where T : class, new() { return new T(); } 
9
30 июня '15 в 15:51 2015-06-30 15:51 atsakymas pateiktas vartotojo887983 birželio 30 d., 15 val. 15:51 2015-06-30 15:51

Jei norite naudoti numatytąjį konstruktorių, tuomet sprendimas „ System.Activator , pateiktas anksčiau, tikriausiai yra patogiausias. Tačiau, jei nėra numatytojo tipo konstruktoriaus arba turite naudoti nestandartinį, tuomet parinktis turi naudoti atspindį arba System.ComponentModel.TypeDescriptor . Atspindėjimo atveju pakanka žinoti tik tipo pavadinimą (su jo vardų erdve).

Refleksijos pavyzdys:

 ObjectType instance = (ObjectType)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance( typeName: objectType.FulName, // string including namespace of the type ignoreCase: false, bindingAttr: BindingFlags.Default, binder: null, // use default binder args: new object[] { args, to, constructor }, culture: null, // use CultureInfo from current thread activationAttributes: null ); 

TypeDescriptor naudojimo TypeDescriptor :

 ObjectType instance = (ObjectType)System.ComponentModel.TypeDescriptor.CreateInstance( provider: null, // use standard type description provider, which uses reflection objectType: objectType, argTypes: new Type[] { types, of, args }, args: new object[] { args, to, constructor } ); 
7
23 июля '13 в 0:03 2013-07-23 00:03 atsakymą pateikė „ BSharp “ liepos 23 d. 13 val. 0:03 2013-07-23 00:03

Nėra paplitęs T t = new T(); ?

7
17 авг. Atsakymas suteikiamas Brady Moritz 17 rugpjūčio mėn. 2010-08-17 17:30 „10, 5:30 val. 2010-08-17 17:30

Atsižvelgiant į šią problemą, aktyvatorius veiks, kai nėra ctoro parametrų. Jei šis apribojimas, naudokite

 System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject() 
5
30 июня '15 в 19:35 2015-06-30 19:35 Atsakymą Thulani Chivandikwa pateikė birželio 15 d. 15 val. 19:35 2015-06-30 19:35
 public AbstractType New { get { return (AbstractType) Activator.CreateInstance(GetType()); } } 
3
10 сент. Atsakymą pateikė vikram nayak 10 Sep. 2012-09-10 02:08 '12, 02:08 2012-09-10 02:08

Galiu išspręsti šį klausimą, nes ieškojau paprasto „CloneObject“ metodo įgyvendinimo savavališkai klasei (su standartiniu konstruktoriumi)

Naudojant bendrąjį metodą, galite reikalauti naujo () tipo.

 Public Function CloneObject(Of T As New)(ByVal src As T) As T Dim result As T = Nothing Dim cloneable = TryCast(src, ICloneable) If cloneable IsNot Nothing Then result = cloneable.Clone() Else result = New T CopySimpleProperties(src, result, Nothing, "clone") End If Return result End Function 

Darant prielaidą, kad tipas turi netinkamą konstruktorių ir išskirtinę sugavimo išimtį, jei tai nėra.

 Public Function CloneObject(ByVal src As Object) As Object Dim result As Object = Nothing Dim cloneable As ICloneable Try cloneable = TryCast(src, ICloneable) If cloneable IsNot Nothing Then result = cloneable.Clone() Else result = Activator.CreateInstance(src.GetType()) CopySimpleProperties(src, result, Nothing, "clone") End If Catch ex As Exception Trace.WriteLine("!!! CloneObject(): "  ex.Message) End Try Return result End Function 
3
24 марта '15 в 21:10 2015-03-24 21:10 atsakymas pateikiamas Darrel Lee kovo 24 d. 15 val. 21:10 2015-03-24 21:10

Kiti klausimai apie arba Užduoti klausimą