খুব পুরানো প্রশ্ন, তবে নতুন উত্তর ;-)
এক্সপ্রেশনট্রি সংস্করণ : (আমি মনে করি দ্রুততম এবং পরিষ্কার সমাধান)
যেমন ওয়েলির তম্বুনান বলেছিলেন, "আমরা বস্তুটি তৈরি করতে অভিব্যক্তি গাছও ব্যবহার করতে পারি"
এটি প্রদত্ত প্রকার / পরামিতিগুলির জন্য একটি 'কনস্ট্রাক্টর' (ফাংশন) উত্পন্ন করবে। এটি কোনও প্রতিনিধিকে ফিরিয়ে দেয় এবং প্যারামিটারের ধরণেরগুলিকে অবজেক্টের অ্যারে হিসাবে গ্রহণ করে।
এটা এখানে:
// this delegate is just, so you don't have to pass an object array. _(params)_
public delegate object ConstructorDelegate(params object[] args);
public static ConstructorDelegate CreateConstructor(Type type, params Type[] parameters)
{
// Get the constructor info for these parameters
var constructorInfo = type.GetConstructor(parameters);
// define a object[] parameter
var paramExpr = Expression.Parameter(typeof(Object[]));
// To feed the constructor with the right parameters, we need to generate an array
// of parameters that will be read from the initialize object array argument.
var constructorParameters = parameters.Select((paramType, index) =>
// convert the object[index] to the right constructor parameter type.
Expression.Convert(
// read a value from the object[index]
Expression.ArrayAccess(
paramExpr,
Expression.Constant(index)),
paramType)).ToArray();
// just call the constructor.
var body = Expression.New(constructorInfo, constructorParameters);
var constructor = Expression.Lambda<ConstructorDelegate>(body, paramExpr);
return constructor.Compile();
}
মাইক্লাস উদাহরণ:
public class MyClass
{
public int TestInt { get; private set; }
public string TestString { get; private set; }
public MyClass(int testInt, string testString)
{
TestInt = testInt;
TestString = testString;
}
}
ব্যবহার:
// you should cache this 'constructor'
var myConstructor = CreateConstructor(typeof(MyClass), typeof(int), typeof(string));
// Call the `myConstructor` function to create a new instance.
var myObject = myConstructor(10, "test message");
আর একটি উদাহরণ: অ্যারে হিসাবে প্রকারগুলি পাস করা
var type = typeof(MyClass);
var args = new Type[] { typeof(int), typeof(string) };
// you should cache this 'constructor'
var myConstructor = CreateConstructor(type, args);
// Call the `myConstructor` fucntion to create a new instance.
var myObject = myConstructor(10, "test message");
এক্সপ্রেশন ডিবাগভিউ
.Lambda #Lambda1<TestExpressionConstructor.MainWindow+ConstructorDelegate>(System.Object[] $var1) {
.New TestExpressionConstructor.MainWindow+MyClass(
(System.Int32)$var1[0],
(System.String)$var1[1])
}
এটি উত্পন্ন কোডের সমতুল্য:
public object myConstructor(object[] var1)
{
return new MyClass(
(System.Int32)var1[0],
(System.String)var1[1]);
}
ছোট ডাউনসাইড
সমস্ত ভ্যালুটিটাইপ প্যারামিটারগুলি যখন বস্তু অ্যারের মতো পাস করা হয় তখন বাক্স হয়।
সাধারণ পারফরম্যান্স পরীক্ষা:
private void TestActivator()
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1024 * 1024 * 10; i++)
{
var myObject = Activator.CreateInstance(typeof(MyClass), 10, "test message");
}
sw.Stop();
Trace.WriteLine("Activator: " + sw.Elapsed);
}
private void TestReflection()
{
var constructorInfo = typeof(MyClass).GetConstructor(new[] { typeof(int), typeof(string) });
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1024 * 1024 * 10; i++)
{
var myObject = constructorInfo.Invoke(new object[] { 10, "test message" });
}
sw.Stop();
Trace.WriteLine("Reflection: " + sw.Elapsed);
}
private void TestExpression()
{
var myConstructor = CreateConstructor(typeof(MyClass), typeof(int), typeof(string));
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1024 * 1024 * 10; i++)
{
var myObject = myConstructor(10, "test message");
}
sw.Stop();
Trace.WriteLine("Expression: " + sw.Elapsed);
}
TestActivator();
TestReflection();
TestExpression();
ফলাফল:
Activator: 00:00:13.8210732
Reflection: 00:00:05.2986945
Expression: 00:00:00.6681696
ব্যবহার Expressions
করা চালানোর চেয়ে +/- 8 গুণ বেশি ConstructorInfo
এবং +/- 20 বারের চেয়ে 20 গুণ বেশি দ্রুতActivator