У меня есть несколько точек данных и связанный с ними процессор данных для каждой.
public interface IDataPointProcessor<T> where T : DataPointInputBase
{
DataPointOutputBase GetOutput(T input);
}
Я загружаю список точек данных из файла и хочу обработать их, используя один связанный с ним процессор.
foreach (DataPointInputBase item in input.DataPoints)
{
//assuming item coming in is of type 'X' how do I get correct processor
var type = typeof(IDataPointProcessor<X>);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p) && !p.IsAbstract);
IDataPointProcessor<X> matchedType = ??
}
Как решить для «X», чтобы я могсоздать экземпляр и обработать ввод?
Update # 1 Объединяя ответы Славы и Лаки снизу, я получаю следующее, но выдает исключение - «Объект не соответствует типу цели».хотя в отладчике все выглядит нормально.Можно ли приводить как IDataPointProcessor <> и вызывать метод интерфейса чисто, то есть: instance.GetOutput (item);
foreach (DataPointInputBase item in input.DataPoints)
{
Type typeGenArg = item.GetType();
Type typeInterfaceGen = typeof(IDataPointProcessor<>).MakeGenericType(typeGenArg);
Type type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => typeInterfaceGen.IsAssignableFrom(x) && !x.IsAbstract)
.FirstOrDefault();
Type genericType = typeof(IDataPointProcessor<>);
Type dependedGenericType = genericType.MakeGenericType(typeof(DataPointInputBase));
var method = dependedGenericType.GetMethod("GetOutput");
var instance = Activator.CreateInstance(type);
//currently throws:System.Reflection.TargetException: 'Object does not match target type.'
var result = method.Invoke(instance, new object[] { item });
//Ideally I want to do this and avoid the magic strings etc
//var temp_output = instance.GetOutput(item);
}
Обновление # 2 Чтобы сохранить движение, мне сложнозакодировал тип Age_Input для проверки работоспособности.Чего мне не хватает, чтобы динамически вызывать жестко закодированный бит?
Я должен иметь возможность привести экземпляр к IDataPointProcessor<IDataPointInput>
и вызвать GetOutput()
на интерфейсе
foreach (IDataPointInput item in input.DataPoints)
{
Type typeGenArg = item.GetType();
Type typeInterfaceGen = typeof(IDataPointProcessor<>).MakeGenericType(typeGenArg);
Type type = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(x => typeInterfaceGen.IsAssignableFrom(x) && !x.IsAbstract)
.FirstOrDefault();
Type genericType = typeof(IDataPointProcessor<>);
Type dependedGenericType = genericType.MakeGenericType(typeof(IDataPointInput));
var instance = Activator.CreateInstance(type);
if (instance is IDataPointProcessor<Age_Input>)//hard-coded
{
var processor = instance as IDataPointProcessor<Age_Input>;
Age_Input temp = item as Age_Input;
var result = processor.GetOutput(temp);
}
if (instance is DataPointProcessorBase<DataPointInputBase>)
{
//false
}
if (instance is IDataPointProcessor<DataPointInputBase>)
{
//false
}
if (instance is IDataPointProcessor<IDataPointInput>)
{
//false - shouldn't this work?
}
}
Age_Input - тривиальнокласс, унаследованный от тупого базового класса и пустого интерфейса
public class Age_Input : DataPointInputBase, IDataPointInput
{
public int AgeExact { get; set; }
}
public class DataPointInputBase : IDataPointInput
{
}
public interface IDataPointInput
{
}
Класс процессора аналогично прост
public abstract class DataPointProcessorBase<T> : IDataPointProcessor<T> where T : IDataPointInput, new()
{
//public abstract DataPointOutputBase GetOutput(DataPointInputBase input);
public abstract DataPointOutputBase GetOutput(T input);
}
public interface IDataPointInput
{
}
public interface IDataPointProcessor<IDataPointInput>
{
DataPointOutputBase GetOutput(IDataPointInput input);
}