给定一个约束的泛型方法我可以调用非泛型方法传递泛型参数的实际类型 [英] Given a constrained generic method can I call a non-generic method passing the actual type of the generic parameter

查看:120
本文介绍了给定一个约束的泛型方法我可以调用非泛型方法传递泛型参数的实际类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

尴尬的头衔,我知道,这是最好的code解释。给定一组类:

Awkward title I know, this is best explained in code. Given a set of classes:

public abstract class MyBaseType
{
    public string Message { get; set; }
}

public class MySuperType : MyBaseType
{
    public string AdditionalInfo { get; set; }
}

public class MyOtherSuperType : MyBaseType
{
    public DateTime Started { get; set; }
    public DateTime Finished { get; set; }
}

有没有一种方法来编写调用非泛型方法传递泛型类型,而除preting传递的类型作为其实际类型而不是基本类型的通用方法。也就是说,我的需要的写是这样的:

public void OutputFormattedTypeInfo<T>(T theType) where T : MyBaseType
{
    OutputFormattedTypeInfo(theType as T);
}

public void OutputFormattedTypeInfo(MySuperType theType)
{
    System.Console.WriteLine(String.Format("{0} and {1}", theType.Message, theType.AdditionalInfo));
}

public void OutputFormattedTypeInfo(MyOtherSuperType theType)
{
    System.Console.WriteLine(String.Format("{0} - Start: {1}, End: {2}", theType.Message, theType.Started, theType.Finished));
}

但显然theType为T是PTED为基本类型间$ P $。我知道我可以使用反射像这样的:

But obviously theType as T is interpreted as the base type. I know I can use reflection like this:

Type type = typeof(MyBaseTypeDisplayFormatter);
    MethodInfo method = type.GetMethod(
                                    "FormatSpecific",
                                    BindingFlags.Instance | BindingFlags.NonPublic,
                                    null,
                                    new[] { update.GetType() },
                                    null);

    return (MyBaseTypeDataItem)method.Invoke(this, new object[] { update });

但它只是感觉不雅。有没有更好的办法?

but it just feels inelegant. Is there a better way?

推荐答案

由于Aliostad说,你努力做的事情不再是通用的,这将是最好只使用过载。它看起来像你试图做同样的模板特在C ++中,在这取决于它调用不同的方法,泛型类型的东西。

As Aliostad said, what your trying to do is no longer generic and it would be better to just use overloads. It looks like you are trying to do something similar to template specialization in C++, where depending on the generic type it calls different methods.

下面是我实现的一种使用反射一般专业化的例子,你也许可以申请一个类似的模式,如果重载方法不会为你工作。如果你可以缓存反射的结果,并只调用GetMethod的一次,然后它原来是不是太慢了。内的一类通用的被T有一个方法调用:

Here is an example where I implemented a sort of generic specialization using reflection, you might be able to apply a similar pattern if overloading method wont work for you. If you can cache the results of reflection and only call GetMethod once then it turns out to be not too slow. Inside a class generic by T there is a method that calls:

if (_serializeDataToStream == null)
    _serializeDataToStream = (Action<BinaryWriter, int, T[]>)GetTypeSpecificSerializationMethod();

_serializeDataToStream(writer, _size, _data);

当GetTypeSpecific方法使用反射来创建一个委托

Where the GetTypeSpecific method uses reflection to create a delegate

/// <summary>
/// Returns a delegate that points at the static type specific serialization method
/// </summary>
/// <returns></returns>
private Delegate GetTypeSpecificDeserializationMethod()
{
    if (typeof(T) == typeof(double))
    {
        MethodInfo method = this.GetType().GetMethod("DeserializeDouble", BindingFlags.Static | BindingFlags.NonPublic);
        return Delegate.CreateDelegate(typeof(Action<BinaryReader, int, T[]>), method);
    }
    else if (typeof(T) == typeof(ushort))
    {
        MethodInfo method = this.GetType().GetMethod("DeserializeUshort", BindingFlags.Static | BindingFlags.NonPublic);
        return Delegate.CreateDelegate(typeof(Action<BinaryReader, int, T[]>), method);
    }
    else if (typeof(T) == typeof(DateTime))
    {
        MethodInfo method = this.GetType().GetMethod("DeserializeDateTime", BindingFlags.Static | BindingFlags.NonPublic);
        return Delegate.CreateDelegate(typeof(Action<BinaryReader, int, T[]>), method);
    }
    else if (typeof(T) == typeof(bool))
    {
        MethodInfo method = this.GetType().GetMethod("DeserializeBool", BindingFlags.Static | BindingFlags.NonPublic);
        return Delegate.CreateDelegate(typeof(Action<BinaryReader, int, T[]>), method);
    }

    throw new NotImplementedException("No deserialization method has been setup for type " + typeof(T).FullName);
}

/// <summary>
/// Serialize double[] to BinaryWriter
/// </summary>
/// <param name="writer"></param>
/// <param name="size"></param>
/// <param name="data"></param>
private static void SerializeDouble(BinaryWriter writer, int size, double[] data)
{
    for (int i = 0; i < size; i++)
    {
        writer.Write(data[i]);
    }
}

这篇关于给定一个约束的泛型方法我可以调用非泛型方法传递泛型参数的实际类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆