如何使用反射调用具有泛型返回类型的泛型方法

时间:2018-08-02 01:44:05

标签: c# reflection

预期:

  

调用通用方法_client.Read,该方法返回ReadEvent,并且ReadEvent具有属性T值。(有关_client.Read的更多详细信息,请参阅PS)

我成功使用MakeGenericMethod调用了泛型方法,但是我不知道如何在ReadEvent<T>中获取Value。

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

示例:

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

尝试:

readEvent是对象,我不知道如何使用正确的T将其转换为ReadEvent<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: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;
    }
    ...
}

1 个答案:

答案 0 :(得分:0)

如果用动态替换对象readEvent怎么办,因此可以轻松访问value属性并将其强制转换为T:

public T Read<T>(ItemId itemId)
{
    var type = Type.GetType(itemId.NameOfType);
    var methodInfo = typeof(DaClient).GetMethod("Read");
    var generic = methodInfo.MakeGenericMethod(type);
    dynamic readEvent = generic.Invoke(_client, new object[] { itemId.Tag });

    var value = readEvent.Value;
    return (T)value;
}