Ho lavorato a un problema per un paio d'ore e penso di essere vicino. Sto lavorando a un'app in cui potremmo avere 50-100 tipi che funzionano allo stesso modo. Così, invece di creare classi 50-100, ho cercato di rendere più generico e questo è quello che ho:Creare un tipo generico con interfaccia generica in fase di esecuzione
Questa è la classe base:
public class RavenWriterBase<T> : IRavenWriter<T> where T : class, IDataEntity
E questa è l'interfaccia:
public interface IRavenWriter<T>
{
int ExecutionIntervalInSeconds { get; }
void Execute(object stateInfo);
void Initialize(int executionIntervalInSeconds, Expression<Func<T, DateTime>> timeOrderByFunc);
}
Ed è così che lo sto usando:
private static void StartWriters()
{
Assembly assembly = typeof(IDataEntity).Assembly;
List<IDataEntity> dataEntities = ReflectionUtility.GetObjectsForAnInterface<IDataEntity>(assembly);
foreach (IDataEntity dataEntity in dataEntities)
{
Type dataEntityType = dataEntity.GetType();
Type ravenWriterType = typeof(RavenWriterBase<>).MakeGenericType(dataEntityType);
Expression<Func<IDataEntity, DateTime>> func = x => x.CicReadTime;
// This is where I'm stuck. How do I activate this as RavenWriterBase<T>?
var ravenWriter = Activator.CreateInstance(ravenWriterType);
//ravenWriter.Initialize(60, func); // I can't do this until I cast.
// More functionality here (not part of this issue)
}
}
mi sono bloccato su questa linea dall'alto:
var ravenWriter = Activator.CreateInstance(ravenWriterType);
Questa è la mia domanda:
Come posso usare che come RavenWriterBase o IRavenWriter? Qualcosa di simile:
ravenWriter.Initialize(60, func);
penso che debba essere qualcosa di simile, ma ho bisogno di specificare un tipo per IRavenWriter <> e non so ancora:
var ravenWriter = Activator.CreateInstance(ravenWriterType) as IRavenWriter<>;
Se io il mouse sopra ravenWriter, ho successo il mio oggetto:
Ma ora ho bisogno di essere in grado di usarlo in modo generico. Come lo posso fare?
Aggiornamento:
ho pensato di usare la parola chiave dinamica, e questo funziona:
dynamic ravenWriter = Activator.CreateInstance(ravenWriterType);
ravenWriter.Initialize(60);
ho barato un po 'perché mi sono reso conto che il Func è stato lo stesso per ogni IDataEntity, così non era necessario passare come parametro a Initialize(). Tuttavia, almeno ora I può chiamare Initialize(). Ma ora che Func è lo stesso, non dovrei nemmeno aver bisogno dell'interfaccia generica.
Sembra un uso improprio di farmaci generici. Quando ti stai ritrovando a dover eseguire diversi metodi in base a tipi diversi, ma i tipi sono noti solo al runtime, devi utilizzare il polimorfismo. Cosa ti stanno guadagnando i generici? Puoi eseguire i metodi così com'è senza generici in primo luogo, vale a dire con IDataEntity? – mellamokb
Sono d'accordo con mellamokb. Tuttavia, se sei impostato su generici, perché non creare una classe wrapper che puoi creare un'istanza non genetica. Il wrapper dovrebbe avere un metodo che restituisce un'istanza di RavenWriterBase a seconda del tipo passato come argomento. Quindi, creare un'istanza del wrapper e chiamare il metodo con il tipo requestedd come parametro. Ciò richiederà una dichiarazione switch di grandi dimensioni, ma almeno non 200 classi separate. –
dcow
Crei altre espressioni che non utilizzano IDataEntity per T? O è sempre un IDataEntity? E se T è sempre IDataEntity, perché usare i generici? –