উত্তর:
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,। নেট 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,। নেট 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, লিনকিউপ্যাড 5.22.02 / এক্স 64 /। নেট 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 /। নেট 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 /। নেট কোর 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()
। ডায়নামিক সংকলনের জন্য দুটি সহজ বিকল্প লিনক এক্সপ্রেশন বা কিছু সাধারণ IL
অপকোড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();
}
এই সমস্যাটি দেওয়া অবস্থায় অ্যাক্টিভেটর যখন প্যারামিটারলেস কর্টর থাকে তখন কাজ করবে। এটি যদি সীমাবদ্ধ থাকে তবে ব্যবহার বিবেচনা করুন
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
জেনারিক হিসাবে ধরে নিলে ধরণের ডিফল্ট নির্মাতা রয়েছে এবং যদি এটি না ঘটে তবে একটি ব্যতিক্রম ধরুন catch
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