リフレクションか何かを使用してそうする例をどこかで見たのを確かに覚えています。それはSqlParameterCollection
、ユーザーが作成できないものと関係がありました (私が間違っていなければ)。残念ながら、もう見つけることができません。
誰でもここでこのトリックを共有できますか? それが開発における有効なアプローチだとは考えていませんが、これを行う可能性に非常に興味があります。
リフレクションか何かを使用してそうする例をどこかで見たのを確かに覚えています。それはSqlParameterCollection
、ユーザーが作成できないものと関係がありました (私が間違っていなければ)。残念ながら、もう見つけることができません。
誰でもここでこのトリックを共有できますか? それが開発における有効なアプローチだとは考えていませんが、これを行う可能性に非常に興味があります。
これを行うには、 Activator.CreateInstanceのオーバーロードの 1 つを使用できます。Activator.CreateInstance(Type type, bool nonPublic)
引数に使用true
しnonPublic
ます。true
パブリックまたは非パブリックの既定のコンストラクターに一致するため。false
パブリックの既定のコンストラクターのみに一致します。
例えば:
class Program
{
public static void Main(string[] args)
{
Type type=typeof(Foo);
Foo f=(Foo)Activator.CreateInstance(type,true);
}
}
class Foo
{
private Foo()
{
}
}
// the types of the constructor parameters, in order
// use an empty Type[] array if the constructor takes no parameters
Type[] paramTypes = new Type[] { typeof(string), typeof(int) };
// the values of the constructor parameters, in order
// use an empty object[] array if the constructor takes no parameters
object[] paramValues = new object[] { "test", 42 };
TheTypeYouWantToInstantiate instance =
Construct<TheTypeYouWantToInstantiate>(paramTypes, paramValues);
// ...
public static T Construct<T>(Type[] paramTypes, object[] paramValues)
{
Type t = typeof(T);
ConstructorInfo ci = t.GetConstructor(
BindingFlags.Instance | BindingFlags.NonPublic,
null, paramTypes, null);
return (T)ci.Invoke(paramValues);
}
クラスがあなたのものではない場合、API はこれを防ぐために意図的に作成されたように思えます。つまり、あなたのアプローチが API 作成者が意図したものではない可能性があることを意味します。ドキュメントを見て、このクラスを使用するための推奨されるアプローチがあるかどうかを確認してください。
クラスを制御していて、このパターンを実装したい場合は、通常、クラスの静的メソッドを介して実装されます。これも Singleton パターンを構成する重要な概念です。
例えば:
public PrivateCtorClass
{
private PrivateCtorClass()
{
}
public static PrivateCtorClass Create()
{
return new PrivateCtorClass();
}
}
public SomeOtherClass
{
public void SomeMethod()
{
var privateCtorClass = PrivateCtorClass.Create();
}
}
SqlCommandParameter が良い例です。彼らは、次のようなものを呼び出してパラメーターを作成することを期待しています:
var command = IDbConnnection.CreateCommand(...);
command.Parameters.Add(command.CreateParameter(...));
私の例は、コマンド パラメーター プロパティの設定やパラメーター/コマンドの再利用を示していないため、優れたコードではありませんが、アイデアは理解できます。
あなたType
がprivate
またはの場合にも役立ちますinternal
:
public static object CreatePrivateClassInstance(string typeName, object[] parameters)
{
Type type = AppDomain.CurrentDomain.GetAssemblies().
SelectMany(assembly => assembly.GetTypes()).FirstOrDefault(t => t.Name == typeName);
return type.GetConstructors()[0].Invoke(parameters);
}