C# 编写一个泛型方法来替换一系列遗留API方法

C# 编写一个泛型方法来替换一系列遗留API方法,c#,generics,C#,Generics,我正在使用遗留API编写代码,我无法更改其代码。支持的数据类型(int、double、bool、string、APIObject)有一系列方法在API中执行操作。它们采用与方法名称中指示的数据类型相同的参数。示例用法如下所示 GetIntExp(5) GetStringExp("Hello") GetDoubleExp(1.2) GetDateExp(DateTime.Now) GetAPIObjectExp(myObject) 返回类型分别为IntExp、StringExp、DoubleEx

我正在使用遗留API编写代码,我无法更改其代码。支持的数据类型(int、double、bool、string、APIObject)有一系列方法在API中执行操作。它们采用与方法名称中指示的数据类型相同的参数。示例用法如下所示

GetIntExp(5)
GetStringExp("Hello")
GetDoubleExp(1.2)
GetDateExp(DateTime.Now)
GetAPIObjectExp(myObject)
返回类型分别为IntExp、StringExp、DoubleExp、DateExp和ObjectExp。所有返回类型都继承自一个类(有趣的是它是一个泛型类型)
StaticOperator
,其中T是数据类型


是否可以在我的代码库中编写一个通用方法,根据传入的数据类型将调用重定向到合适的API方法?

类似于

private Dictionary<Type, Func<object, object>> _funcMapping = new Dictionary<Type, Func<object, object>> {
    {typeof(Int), (input) => GetIntExp((int)input)},
    {typeof(string), (input) => GetStringExp((string)input)},
    ...
};

public StaticOperator<TType> GetExp<TType>(TType target) {
    Func<object, object> func;
    if (!_funcMapping.TryGetValue(typeof(TType), out func))
        throw new NotImplementedException();
    return (StaticOperator<TType>)func(target);
} 
private Dictionary\u funcMapping=新字典{
{typeof(Int),(input)=>GetIntExp((Int)input)},
{typeof(string),(input)=>GetStringExp((string)input)},
...
};
公共静态运算符GetExp(TType目标){
Func Func;
if(!\u funcMapping.TryGetValue(typeof(TType),out func))
抛出新的NotImplementedException();
返回(静态运算符)函数(目标);
} 
这是完全可能的,但肯定有结垢问题和相当不安全,因为需要大量铸造


当然,如果..您可以使用
重写它。。艾尔塞夫。。艾尔塞夫。。艾尔塞夫。。否则
,但总而言之,这只是检查我们是否有合适的方法。

在我看来,您根本不需要通用方法,只需要为每个受支持的参数类型提供包装器方法:

public IntExp GetExpression(int value)
{
    return GetIntExp(value);
}

public StringExp GetExpression(string value)
{
    return GetStringExp(value);
}

依此类推(假设您的目标是在所有获得表达式的方法中使用相同的名称)。

这样的事情怎么样:

public T GetExp<T>(T obj)
{
    Type type = typeof(T);

    if (type == typeof(int))
        return GetIntExp(obj);
    if (type == typeof(string))
        return GetStringExp(obj);
    if (type == typeof(double))
        return GetDoubleExp(obj);
    if (type == typeof(DateTime))
        return GetDateExp(obj);
    if (type == typeof(APIObject))
        return GetAPIObjectExp(obj);

    throw new Exception("Invalid Type");
}
public T GetExp(T obj)
{
类型=类型(T);
if(type==typeof(int))
返回GetIntExp(obj);
if(type==typeof(string))
返回GetStringExp(obj);
if(type==typeof(double))
返回GetDoubleExp(obj);
if(type==typeof(DateTime))
返回GetDateExp(obj);
if(type==typeof(APIObject))
返回GetAPIObjectExp(obj);
抛出新异常(“无效类型”);
}
“是否可以在我的代码库中编写一个通用方法,根据传入的数据类型将调用重定向到合适的API方法。”

您可以编写一些IL代码来精确地实现这一点。再说一次,你可能不会玩得很开心。我在家里读过一篇关于codeplex的文章。我想我是通过谷歌搜索“运行时替换方法”找到的

也许这就是你到底在寻找的,尽管它可能是解决你实际问题最困难的方法


这是我使用@J0HN和@Prescott的建议编译和工作得到的

private StaticOperator<T> GetValue<T>(T comparandValue)
{
    Type type = typeof(T);

    if (type == typeof(int))
    {
        return GetIntVal((dynamic)comparandValue);
    }

    if (type == typeof(double))
    {
        return GetDoubleVal((dynamic)comparandValue);
    }

    if (type == typeof(string))
    {
        return GetStringVal((dynamic)comparandValue);
    }

    if (type == typeof(DateTime))
    {
        return GetDateVal((dynamic)comparandValue);
    }

    if (type == typeof(APIbject))
    {
        return GetObjectVal(comparandValue as APIObject);
    }
    throw new NotSupportedException("The given type is not supported");
}
private StaticOperator GetValue(T comparandValue)
{
类型=类型(T);
if(type==typeof(int))
{
返回GetIntVal((动态)comparandValue);
}
if(type==typeof(double))
{
返回GetDoubleVal((动态)comparandValue);
}
if(type==typeof(string))
{
返回GetStringVal((动态)comparandValue);
}
if(type==typeof(DateTime))
{
返回GetDateVal((动态)comparandValue);
}
if(type==typeof(apobject))
{
返回GetObjectVal(comparandValue作为APIObject);
}
抛出新的NotSupportedException(“不支持给定类型”);
}

您已经显示了四个。。。但是列出了五个。它真的可以用于任何对象吗?它对每个操作都执行相同的操作吗?返回类型是什么?很抱歉打断一下,有三个问题,只有一个答案:)是否应该考虑“是,是,是”?公开泛型方法的问题是,它允许您传递任何数据类型。甚至自定义类。在这些情况下,代码应该做什么?被调用的方法只是创建一个在服务器上执行的表达式。支持的类型仅为列出的5种,object有点误导,因为它引用的是APIObject的实例,而不是任何对象。该方法不会被任何其他类型调用,如果发生这种情况,它会抛出异常。我将使用命令模式。它将解决您的问题,甚至可能在将来的扩展等方面帮助您。谢谢J0hn,让我试试这个。@J0hn
Func
将导致每个方法执行的装箱和拆箱,不是吗?@YuvalItzchakov是的,但这可能是一个阻碍,也可能不是一个阻碍,因为对此没有任何疑问。我相信可以避免装箱拆箱,但我不够聪明,无法在合理的时间对其进行编程:)@J0HN,我使用了您的第一个解决方案和Prescott的解决方案的组合来获得一个工作版本。谢谢。
GetIntExp
GetStringExp
。。。返回
StaticOperator
,而不仅仅是
T
,我认为这不会编译。编译器无法确认
GetFooExp
方法是否返回正确的类型。铸造可能会修复它。我稍微编辑了一下,让它编译,但这在原则上是有效的。这有点不雅观,有点干巴的违反,但在这种情况下,我认为这是最好的解决方案。好吧,这或者只是直接调用API方法,但是我假设OP有理由想要添加额外的抽象层,虽然这在很多情况下都可以工作,但在我的例子中,这个方法将用于一个通用方法,它形成一个要在服务器上执行的图查询。实际上,我认为这是一个非常好的解决方案,因为类型重载将在编译时解决这个问题。甚至可以添加
GetExpression((动态)myObject)调用。您可以添加泛型重载,如果其他操作失败,它将作为回退+1岁的我。拉乌米斯拉很好地考虑了普雷斯科特的回答,然后稍加调整,使之。compiles@RahulMisra我不认为进行图形查询有什么问题;JustSearch API a