mercredi 1 août 2018

How to invoke a generic method with generic return type using reflection

Expected:

Invoke a generic method _client.Read, which return ReadEvent and ReadEvent has a property T Value.(for more detaile about _client.Read please refer PS)

I invoke generic method successed with MakeGenericMethod, but i have not idea about how to get Value in ReadEvent.

public T Read<T>(ItemId itemId)
{
    var type = Type.GetType(itemId.NameOfType);
    ReadEvent<type> readEvent = _client.Read<type>(itemId.Tag);
    return (T) readEvent.Value;
}

Example:

string result = Read<string>(itemWithBoolValue);
// itemWithBoolValue.NameOfType == "System.Boolean"

Tried:

readEvent is object, i don't konw how to convert it to ReadEvent with correctly T.

public T Read<T>(ItemId itemId)
{
    var type = Type.GetType(itemId.NameOfType);
    var methodInfo = typeof(DaClient).GetMethod("Read");
    var generic = methodInfo.MakeGenericMethod(type);
    object readEvent = generic.Invoke(_client, new object[] { itemId.Tag });
    var propertyInfo = typeof(ReadEvent<>).GetProperty("Value");
    // System.InvalidOperationException: Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
    var value = propertyInfo.GetValue(readEvent);
    return (T)value;
}

PS:source code of DaClient Read

class DaClient;
{
    public ReadEvent<T> Read<T>(string tag)
    {
        var item = new OpcDa.Item { ItemName = tag };
        if (Status == OpcStatus.NotConnected)
        {
            throw new OpcException("Server not connected. Cannot read tag.");
        }
        var result = _server.Read(new[] { item })[0];
        T casted;
        TryCastResult(result.Value, out casted);

        var readEvent = new ReadEvent<T>();
        readEvent.Value = casted;
        readEvent.SourceTimestamp = result.Timestamp;
        readEvent.ServerTimestamp = result.Timestamp;
        if (result.Quality == OpcDa.Quality.Good) readEvent.Quality = Quality.Good;
        if (result.Quality == OpcDa.Quality.Bad) readEvent.Quality = Quality.Bad;

        return readEvent;
    }
    ...
}





Aucun commentaire:

Enregistrer un commentaire