जवाबों:
Activator
रूट System
नेमस्पेस के भीतर का वर्ग बहुत शक्तिशाली है।
कंस्ट्रक्टर और इस तरह के मापदंडों को पारित करने के लिए बहुत सारे अधिभार हैं। दस्तावेज़ देखें:
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
या (नया रास्ता)
https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance
यहाँ कुछ सरल उदाहरण दिए गए हैं:
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
ObjectType instance
ओपी की स्थिति से कैसे मेल खाता है "एक हमेशा संकलन-समय पर किसी वस्तु के प्रकार को नहीं जान सकता है"? : पी
object instance = Activator.CreateInstance(...);
,।
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
Activator
वर्ग एक सामान्य संस्करण में आता है कि यह एक थोड़ा आसान है:
ObjectType instance = Activator.CreateInstance<ObjectType>();
dynamic
निर्माण जो करता है इस तरह के निर्माणों लेकिन सबसे प्रयोजनों के लिए इस सवाल का जवाब अभी भी यह शामिल किया गया है अनुमति देते हैं।
संकलित अभिव्यक्ति सबसे अच्छा तरीका है! (रनटाइम में बार-बार उदाहरण बनाने के लिए प्रदर्शन)।
static readonly Func<X> YCreator = Expression.Lambda<Func<X>>(
Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();
X x = YCreator();
सांख्यिकी (2012):
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
सांख्यिकी (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
सांख्यिकी (2015, .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
सांख्यिकी (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
सांख्यिकी (2019, x64 / .NET 4.8):
Iterations: 5000000
No args
00:00:00.3287835, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.3122015, Activator.CreateInstance(Type type)
00:00:00.8035712, ConstructorInfo.Invoke
00:00:00.0692854, Compiled expression
00:00:00.0662223, Compiled expression (type)
00:00:00.0337862, new
Single arg
00:00:03.8081959, Activator.CreateInstance(Type type)
00:00:01.2507642, ConstructorInfo.Invoke
00:00:00.0671756, Compiled expression
00:00:00.0301489, new
सांख्यिकी (2019, x64 / .NET कोर 3.0):
Iterations: 5000000
No args
00:00:00.3226895, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.2786803, Activator.CreateInstance(Type type)
00:00:00.6183554, ConstructorInfo.Invoke
00:00:00.0483217, Compiled expression
00:00:00.0485119, Compiled expression (type)
00:00:00.0434534, new
Single arg
00:00:03.4389401, Activator.CreateInstance(Type type)
00:00:01.0803609, ConstructorInfo.Invoke
00:00:00.0554756, Compiled expression
00:00:00.0462232, new
पूर्ण कोड:
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 += x.Z;
}
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 += x.Z;
}
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) {}
}
X
रनटाइम किस प्रकार का है?
Type
।
इस समस्या का एक कार्यान्वयन प्रकार के पैरामीटर-कम निर्माता को कॉल करने का प्रयास करना है:
public static object GetNewObject(Type t)
{
try
{
return t.GetConstructor(new Type[] { }).Invoke(new object[] { });
}
catch
{
return null;
}
}
यहाँ एक ही तरीका है, एक सामान्य विधि में समाहित:
public static T GetNewObject<T>()
{
try
{
return (T)typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { });
}
catch
{
return default(T);
}
}
यह बहुत आसान है। मान लें कि आपका क्लासनाम है Car
और नेमस्पेस है Vehicles
, तो उस पैरामीटर को पास करें, Vehicles.Car
जो टाइप का ऑब्जेक्ट देता है Car
। इस तरह आप गतिशील रूप से किसी भी वर्ग का कोई भी उदाहरण बना सकते हैं।
public object GetInstance(string strNamesapace)
{
Type t = Type.GetType(strNamesapace);
return Activator.CreateInstance(t);
}
यदि आपका पूरी तरह से योग्य नाम (यानी, Vehicles.Car
इस मामले में) किसी अन्य विधानसभा में है, तो Type.GetType
यह शून्य होगा। ऐसे मामलों में, आपके पास सभी विधानसभाओं के माध्यम से लूप होते हैं और पाते हैं Type
। उसके लिए आप नीचे दिए गए कोड का उपयोग कर सकते हैं
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;
}
और आप उपरोक्त विधि को कॉल करके उदाहरण प्राप्त कर सकते हैं।
object objClassInstance = GetInstance("Vehicles.Car");
यदि यह किसी ऐसी चीज के लिए है जिसे एप्लिकेशन इंस्टेंस में बहुत कुछ कहा जाएगा, तो यह एक्टिवेटर या का उपयोग करने के बजाय गतिशील कोड को संकलित करने और कैश करने के लिए बहुत तेज़ है ConstructorInfo.Invoke()
। गतिशील संकलन के लिए दो आसान विकल्प संकलित हैं Linq Expressions या कुछ सरल IL
opcodes औरDynamicMethod
। किसी भी तरह से, अंतर बहुत बड़ा है जब आप तंग छोरों या कई कॉलों में शामिल होने लगते हैं।
जेनेरिक T t = new T();
काम नहीं होगा ?
यदि आप डिफ़ॉल्ट कंस्ट्रक्टर का उपयोग करना चाहते हैं, तो System.Activator
पहले प्रस्तुत समाधान शायद सबसे सुविधाजनक है। हालांकि, यदि टाइप में डिफॉल्ट कंस्ट्रक्टर की कमी है या आपको एक नॉन-डिफॉल्ट का उपयोग करना है, तो एक विकल्प प्रतिबिंब का उपयोग करना है या System.ComponentModel.TypeDescriptor
। प्रतिबिंब के मामले में, यह केवल प्रकार का नाम (इसके नाम स्थान के साथ) जानने के लिए पर्याप्त है।
प्रतिबिंब का उपयोग करके उदाहरण:
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
:
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 }
);
args[]
वास्तव में क्या मैं इस सवाल के लिए आया था, धन्यवाद!
प्रतिबिंब के उपयोग के बिना:
private T Create<T>() where T : class, new()
{
return new T();
}
इस समस्या को देखते हुए एक्टिवेटर तब काम करेगा जब कोई पैरामीटर रहित ctor हो। यदि यह एक बाधा का उपयोग करने पर विचार करें
System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject()
public AbstractType New
{
get
{
return (AbstractType) Activator.CreateInstance(GetType());
}
}
मैं इस प्रश्न को पार कर सकता हूं क्योंकि मैं मनमाने ढंग से वर्ग के लिए एक साधारण क्लोनबॉज विधि लागू करना चाहता था (डिफ़ॉल्ट रचनाकार के साथ)
जेनेरिक विधि के साथ आप की आवश्यकता हो सकती है कि प्रकार नया लागू करता है ()।
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
गैर-जेनेरिक मान के साथ टाइप में एक डिफ़ॉल्ट कंस्ट्रक्टर होता है और यदि ऐसा नहीं होता है तो एक अपवाद को पकड़ता है।
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