リフレクションを使用してC#でデフォルトコンストラクタなしタイプのインスタンスを作成します
-
23-08-2019 - |
質問
の例として、以下のクラスを取るます:
class Sometype
{
int someValue;
public Sometype(int someValue)
{
this.someValue = someValue;
}
}
私は、リフレクションを使用してこの型のインスタンスを作成したい:
Type t = typeof(Sometype);
object o = Activator.CreateInstance(t);
通常、これはSomeType
は、パラメータなしのコンストラクタを定義していないので、しかし、Activator.CreateInstance
の呼び出しは、メッセージをタイプMissingMethodException
の例外がスローされます、動作します「のこのオブジェクトのために定義されていませんパラメータなしのコンストラクタ。の」ですまだそこにこのタイプのインスタンスを作成する別の方法?すべて私のクラスにパラメータなしのコンストラクタを追加するためにちょっと嫌になると思います。
解決
私はもともと、ここで、この回答はを投稿しました<これは正確に同じ質問はありませんが、同じ答えを持っているので、/ A>が、ここに転載はあります:
FormatterServices.GetUninitializedObject()
コンストラクタを呼び出さずにインスタンスを作成します。私が使用してリフレクターとコアの一部を掘りにより、このクラスを見つけました。ネットシリアライズクラス。
私は、以下のサンプルコードを使用して、それをテストし、それは素晴らしい作品のように見えます。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Runtime.Serialization;
namespace NoConstructorThingy
{
class Program
{
static void Main(string[] args)
{
MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass)); //does not call ctor
myClass.One = 1;
Console.WriteLine(myClass.One); //write "1"
Console.ReadKey();
}
}
public class MyClass
{
public MyClass()
{
Console.WriteLine("MyClass ctor called.");
}
public int One
{
get;
set;
}
}
}
他のヒント
CreateInstanceメソッドのこのオーバーロードを使用します:
public static Object CreateInstance(
Type type,
params Object[] args
)
は、指定のインスタンスを作成し 最高のコンストラクタを使用して入力します 指定されたパラメータに一致します。
を参照してください: http://msdn.microsoft.com/en-us/ライブラリ/ wcxyzt4d.aspxする
(T)FormatterServices.GetUninitializedObject(typeof(T))
ののパフォーマンスをベンチマーク。彼らは唯一のデフォルトコンストラクタを持つタイプのために働くものの、同時にコンパイル表現はあなたの偉大な速度の向上を与えるだろう。私は、ハイブリッドアプローチを取っます:
public static class New<T>
{
public static readonly Func<T> Instance = Creator();
static Func<T> Creator()
{
Type t = typeof(T);
if (t == typeof(string))
return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();
if (t.HasDefaultConstructor())
return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();
return () => (T)FormatterServices.GetUninitializedObject(t);
}
}
public static bool HasDefaultConstructor(this Type t)
{
return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}
この作成式が効果的にキャッシュされていることを意味し、ペナルティにタイプがロードされている初回のみが発生します。効率的な方法で、あまりにも値の型を処理します。
それを呼び出します:
MyType me = New<MyType>.Instance();
の文字列のために失敗すること(T)FormatterServices.GetUninitializedObject(t)
に注意してください。したがって、文字列のための特別な処理は、空の文字列を返すために整備されている。の
良い答えが、ドットネットコンパクトなフレームワークで使用できません。ここでCF.Net ...
上で動作するソリューションですclass Test
{
int _myInt;
public Test(int myInt)
{
_myInt = myInt;
}
public override string ToString()
{
return "My int = " + _myInt.ToString();
}
}
class Program
{
static void Main(string[] args)
{
var ctor = typeof(Test).GetConstructor(new Type[] { typeof(int) });
var obj = ctor.Invoke(new object[] { 10 });
Console.WriteLine(obj);
}
}