部分的な信頼:一般的なタイプの引数なしで汎用タイプをインスタンス化する方法
-
14-11-2019 - |
質問
Silverlight用の再利用可能なライブラリを作成しています。このライブラリには内部汎用タイプが含まれており、この一般的なタイプの新しいインスタンスを作成する必要がありますが、1ポイントでGeneric Type引数を使用できません。一般的な引数を表すSystem.Type
オブジェクトだけです。このクラスは内部およびSilverlightが部分的な信頼で効果的に実行されているため、インスタンスをインスタンスの作成しようとしましたが、これは失敗します。
これは私がこれまで試したものです:
private INonGenericInterface CreateInstance(Type type)
{
// Activator.CreateInstance fails
var instance = Activator.CreateInstance(
typeof(InternalGenericType<>).MakeGenericType(type));
// Invoking the default constructor of that type fails.
var producer = typeof(InternalGenericType<>)
.MakeGenericType(type)
.GetConstructor(new Type[0])
.Invoke(null);
return (INonGenericInterface)producer;
}
.
これは私の内部タイプです。何も派手な:
internal class InternalGenericType<T> : INonGenericInterface
where T : class
{
public InternalGenericType()
{
}
}
.
Nullable<T>
構造体を虐待しようとしたことさえ、内部タイプを生み出すことができる工場を作成するための工場として虐待した。ただし、デフォルトのNullable<T>
がNULL参照に変換されます。
internal static class InternalGenericTypeFactory
{
public static INonGenericInterface Create(Type serviceType)
{
var nullType = typeof(Nullable<>).MakeGenericType(
typeof(Factory<>).MakeGenericType(serviceType));
// Activator succesfully creates the instance, but .NET
// automatically converts default Nullable<T>s to null.
object nullInstance = Activator.CreateInstance(nullType);
var getValueMethod =
nullType.GetMethod("GetValueOrDefault", new Type[0]);
// Invoke fails, because nullInstance is a null ref.
var factory = getValueMethod.Invoke(nullInstance, null);
return ((IFactory)factory).CreateInstance();
}
internal interface IFactory
{
INonGenericInterface CreateInstance();
}
internal struct Factory<T> : IFactory where T : class
{
public INonGenericInterface CreateInstance()
{
return new InternalGenericType<T>();
}
}
}
.
あなたが想像できるように、私はこのタイプを公開したくない、それは私のAPIを汚染するためです。私は現在アイデアが不足しています。私のオプションは何ですか?この内部タイプを作成するにはどうすればいいですか?
解決
第三者は、内部タイプをインスピートする方法を含むある種の工場パターンをサポートすることです。そして、あなたは工場を公開したり、工場の種類の公開を行うことができます。
public class TypeFactory
{
public static object Create<T>()
{
return new MyInternalType<T>();
}
}
.
クラスを内部として離間させることができ、Reflectionを介してTypeFactoryのメソッドを呼び出すことができます。
public object CreateType(System.Type type)
{
Type typeFactory = typeof(TypeFactory);
MethodInfo m = typeFactory.GetMethod("Create").MakeGenericMethod(type);
return m.Invoke(null, null);
}
.
あなたのTypeFactoryが公開されるべきだと思います、それは内部にはできません。
他のヒント
あなたは2つの選択肢を持っています:
- タイプパブリックを作る
- 反射を使用してこれを行うには、代わりにGenericsを使用します。
保障措置が避けられなかったならば、あなたが彼らを好きではなかったからといって、それらをまったく持っている必要はないでしょう。