Могу ли я использовать отражение в EventAggregator Prism?

Я пытаюсь реорганизовать некоторые из моих методов в рамках PRISM, и это не очень работает.

Мне нужно публиковать сообщения через EventAggregator, и я написал метод отражения, который будет просматривать List<Parameters>, содержащий Type, и отсюда отправлять сообщения. Но он никогда не отправляет никаких сообщений.

Оказывается, сейфкаст as PubSubEvent<object> не совпадает с public class Input: PubSubEvent<Output> {}, что означает, что returnObj?.Publish(data); это null и вызываться не будет.

public struct Parameters
{
    public string Topic;
    public Type Input;
    public Type Output;
}


private List<Parameters> _list;
...
void SomeFunction()
{
    _list.ForEach(m =>
    {
        var data = JsonConvert.DeserializeObject(dataString, m.Output);

        var eventAggType = _eventAggregator.GetType();
        var eventMethod = eventAggType.GetMethod("GetEvent");
        var genericMethod = eventMethod.MakeGenericMethod(m.Input);
        var returnObj = genericMethod.Invoke(_eventAggregator, null) as PubSubEvent<object>;
        returnObj?.Publish(data);

        // var datType = returnObj.GetType();
        // if (datType.BaseType.Name == typeof (PubSubEvent<object>).Name)
        // {
        //  var obj = Convert.ChangeType(returnObj, datType);
        //  ((PubSubEvent<object>) obj).Publish(data);
        // }
    }
}

Я попытался изменить код, посмотрев на тип, который он фактически выводит (удалите as PubSubEvent<object>), и это тот же самый BaseType. Но приведение к базовому PubSubEvent не является чем-то, что радует программу.

Exception thrown: 'System.InvalidCastException' in MyProject.ModuleA.dll

EXCEPTION: Unable to cast object of type 'MyProject.ModuleA.GlobalEvents.EventA' to type 'Microsoft.Practices.Prism.PubSubEvents.PubSubEvent`1[System.Object]'.

Как мне Publish с правильным типом? Это должно выглядеть следующим образом, если бы вы знали, с какими классами вы работаете:

_eventAggregator.GetEvent<EventA>().Publish(data);

person Rasmus Bækgaard    schedule 21.10.2015    source источник


Ответы (2)


Как насчет передачи универсального типа в void SomeFunction()

void SomeFunction<T>()
{
    // ..............

    var returnObj = genericMethod.Invoke(_eventAggregator, null) as PubSubEvent<T>;
    returnObj?.Publish(data);
}


// call it like:
SomeFunction<DataObject>();

Обновление:

Вызов универсального метода из типа можно сделать следующим образом:

void SomeFunction<T>()
{
    // ..............

    var returnObj = genericMethod.Invoke(_eventAggregator, null) as PubSubEvent<T>;
    returnObj?.Publish(data);
}


// call it like:

// this is the type you want to pass.
Type genericType = typeof(int);

// get the MethodInfo
var someFunctionMethodInfo = typeof(Program).GetMethod("SomeFunction", BindingFlags.Public);

// create a generic from it
var genericSomeFunctionMethodInfo = someFunctionMethodInfo.MakeGenericMethod(genericType);

// invoke it.
genericSomeFunctionMethodInfo.Invoke(null, new object[] { });
person Jeroen van Langen    schedule 21.10.2015
comment
Да, я должен уточнить. Когда я пытаюсь вызвать SomeFunction(), я передаю сохраненный Type из List<Parameters>. Поэтому я запускаю _list.foreach( m=> ..., где я знаю только тип из этого списка. Возможно, List<> можно переписать во что-то другое, чтобы оно подошло? - person Rasmus Bækgaard; 21.10.2015
comment
Вы должны вывести foreach за пределы функции. Затем можно вызвать метод с определенным типом. Смотрите мое обновление выше. (подобно трюку, который вы проделали выше с дженериками) - person Jeroen van Langen; 22.10.2015
comment
Да, неплохо. Так что я могу сделать больше отражений вне универсального метода, или я могу сделать еще две строки отражения внутри функции (я нашел решение). - person Rasmus Bækgaard; 22.10.2015

Дурак я. Это отражение - еще больше отражения!

void SomeFunction()
{
    _list.ForEach(m =>
    {
        //Deserialize the data
        var data = JsonConvert.DeserializeObject(dataString, m.Output);

        //Obtain the object from the EventAggregator
        var eventAggType = _eventAggregator.GetType();
        var eventMethod = eventAggType.GetMethod("GetEvent");
        var genericMethod = eventMethod.MakeGenericMethod(m.Input);
        var returnObj = genericMethod.Invoke(_eventAggregator, null);

        //Publish the data
        var publishMethod = returnObj.GetType().GetMethod("Publish");
        publishMethod.Invoke(returnObj, new[] {data});
    });
}

Таким образом, вы берете отражение returnObj и отражаете функцию Publish(...) и Invoke из вашего отраженного объекта returnObj с параметром data.

person Rasmus Bækgaard    schedule 22.10.2015