ジェネリック型Store<T>
があり、Activator
を使用してこの型のインスタンスを作成します。アクティベーターを使用した後、どのようにしてobject
型の結果オブジェクトをインスタンス化された型にキャストできますか?ジェネリックのインスタンス化に使用した型を知っています。次のコードをご覧ください。
class Store<T> where T : IStorable
{}
class Beer : IStorable
{}
class BeerStore : Store<Beer>
{}
Type storeType = someObjectThatImplementsIStorable.GetType();
Type classType = typeof(Store<>);
Type[] typeParams = new Type[] { storeType };
Type constructedType = classType.MakeGenericType(typeParams);
object x = Activator.CreateInstance(constructedType, new object[] { someParameter });
私がやりたいのは次のようなものです:
var store = (Store<typeof(objectThatImplementsIStorable)>)x;
しかし、それは明らかな理由で機能しません。代わりとして、私は試しました:
var store = (Store<IStorable>)x;
おそらく私の意見では機能するかもしれませんが、InvalidCastException
を提供します。
オブジェクトx
にあることがわかっているStore<T>
メソッドに再度アクセスするにはどうすればよいですか?
実際の型T
はリフレクションを介してのみ使用できるため、リフレクションを介してStore<T>
のメソッドにもアクセスする必要があります。
Type constructedType = classType.MakeGenericType(typeParams);
object x = Activator.CreateInstance(constructedType, new object[] { someParameter });
var method = constructedType.GetMethod("MyMethodTakingT");
var res = method.Invoke(x, new object[] {someObjectThatImplementsStorable});
[〜#〜] edit [〜#〜]ジェネリックを使用せず、代わりにIStore
を使用する追加のIStorable
インターフェイスを定義することもできます。
interface IStore {
int CountItems(IStorable item);
}
class Store<T> : IStore where T : IStorable {
int CountItems(IStorable item) {
return count;
}
}
Store<T>
は汎用のままですが、CountItems
にキャストすることでIStore
にアクセスできます:
var x = (IStore)Activator.CreateInstance(constructedType, new object[] { someParameter });
var count = x.CountItems((IStorable)someObjectThatImplementsStorable);
あなたはそれを包むだけですか?
何かのようなもの
public Store<T> IConstructStore<T>(T item) where T : IStorable
{
return Activator.CreateInstance(typeof(Store<T>), new object[] { someParameter }) as Store<T>;
}
または私はあなたがやろうとしていることを逃していますか?
IE
class Program
{
static void Main(string[] args)
{
Beer b = new Beer();
var beerStore = IConstructStore(b);
Console.WriteLine(beerStore.test);
Console.WriteLine(beerStore.GetType().ToString());
}
public static Store<T> IConstructStore<T>(T item) where T : IStorable
{
return Activator.CreateInstance(typeof(Store<T>), new object[] { }) as Store<T>;
}
}
interface IStorable { }
class Store<T> where T : IStorable
{
public int test = 1;
}
class Beer : IStorable
{ }
プリント
1
ConsoleApp1.Store'1[ConsoleApp1.Beer]
私の意見で最も適切な答えは、「この方法ではできない」でしょう。
インターフェイスIStorage
を導入して、共変または反変にできます(そのオプションを見たことはありますか?)。オプションではない場合、たとえばStorage
で使用される入力と出力の両方のジェネリック型がある場合、必要なものを実装する方法はありません。その理由は、次の理由により、Storage<Beer>
をStorage<IStorable>
として安全に使用できないためです。
Storage<IStorable> store = new Storage<Beer>(); // let's pretend we can do it
store.Save(new StorableButNotBeer()); // what will happen here?
私が見るようにあなたのための唯一の可能な回避策は、このメソッドからキャストを移動し、すべての正確なタイプを知っている場所にオブジェクトをキャストすることです:
public void object CreateStore(Type istorableType)
{
// here is your activator code, but you will have to return an object
}
var beerStore = (Store<Beer>)CreateStore(typeof(Beer));
Tはtypeof(Storeの使用を回避するタイプStoreでなければなりません
SomeObjectThatImplementsIStorableのタイプがMyStorableであるとしましょう。
例えばMyStorable someObjectThatImplementsIStorable = new MyStorable(); ... //ここにコードの残りの部分。
その場合、xはStoreにキャストできませんが、Storeにキャストできます。以下が機能します:(Store)x
MyStorableはIStorableを実装していますが、StoreとStoreの間に関係はありません。これらは、互いに派生しない2つの異なるクラスです。
あなた.