按类型一般地使用显式方法包装API

时间:2015-08-27 23:22:03

标签: c# reflection casting

我正在寻找一种基于类型或类型集轻松管理决策的方法。 (例如,if是string,double等做一件事,如果是枚举做别的事等)。我有一个重要性和可维护性的横截面是至关重要的。

我正在使用强制执行以下约定的API。

double dblField;
if(!apiObj.IsNull("NameOfDOubleProperty"))
  dblefield = apiObj.GetDouble("NameOfDOubleProperty");

string stringField;
if(!apiObj.IsNull("NameOfStringProperty"))
   stringField = apiObj.GetDouble("NameOfStringProperty");

 //Repeat for each property

I LOATHE魔法字符串遍布代码。如果我在应用程序中更改某些内容我正在阅读此内容,那么我必须添加另一个内容,或者更糟糕的是记住重命名每个地方。

步骤1:启动时,获取只读静态字段(由单次反射调用生成)。我有。

第2步:我的问题 - 如果它是一个字符串,双精度或其他常见原语,我有一个我可以强制转换的通用apiobj.GetField。但是,对于某些对象,我需要特殊处理。

思想或模式?

2 个答案:

答案 0 :(得分:2)

我会考虑将你的字符串文字转换为常量..

const string NAME_OF_DOUBLE_PROPERTY = "NameOfDOubleProperty";
const string NAME_OF_STRING_PROPERTY = "NameOfStringProperty";

至少,这将有助于打字错误。

通过上面的Step1,我假设这是设置为从API接收数据的所有字段的列表。

我想我会先创建一个自定义属性来装饰字段:

[ApiProperty(NAME_OF_DOUBLE_PROPERTY)]
double dblField;

这样,api属性名称和接收字段保持在一起。 现在,基本上在一个位置,您有接收字段,api属性的名称和类型(通过Step1中的FieldInfo类及其CustomAttributes属性)。

其余部分对你来说应该是微不足道的。

答案 1 :(得分:2)

您可以使用表达式使用实际属性名称,并使用辅助方法:

    public static string GetPropertyName<T>(Expression<Func<T, object>> expression)
    {
        var body = expression.Body;
        if (body is UnaryExpression)
        {
            var unaryExpression = body as UnaryExpression;
            if (unaryExpression.Operand is MemberExpression)
                return (unaryExpression.Operand as MemberExpression).Member.Name;
        }
        if (body is MemberExpression)
        {
            return (body as MemberExpression).Member.Name;
        }
        return null;
    }

然后你可以打电话

 double dblField;
 if(!apiObj.IsNull(GetPropertyName<YourObject>(o=>o.NameOfDoubleProperty))
     dblefield = apiObj.GetDouble(GetPropertyName<YourObject>(o=>o.NameOfDoubleProperty));

或者您可以在api中使用GetPropertyName方法,即

dblefield = apiObj.GetDouble<YourObject>(o=>o.NameOfDoubleProperty);

这样你就不会有任何神奇的字符串,并且可以使用实际的属性名称,这将使重构和维护变得更加容易。

然后对于第2步,您可以:

dblefield = apiObj.GetField<YourObject, double>(o=>o.NameOfDoubleProperty);

并在GetField<TObj, TType>(.....)内:

if(gottenValue is TType)
    return (TType)gottenValue;

您可以使用以下方法从表达式中获取属性YourObject.NameOfDoubleProperty的类型:

public static Type GetPropertyType<T>(Expression<Func<T, object>> expression)
{
    var body = expression.Body;
    MemberInfo mi = null;
    if (body is UnaryExpression)
    {
        var unaryExpression = body as UnaryExpression;
        if (unaryExpression.Operand is MemberExpression)
            mi = (unaryExpression.Operand as MemberExpression).Member;
    }
    else if (body is MemberExpression)
    {
        mi = (body as MemberExpression).Member;
    }

    if(mi is PropertyInfo)
    {
        return (mi as PropertyInfo).PropertyType;
    }
    return null;
}

但是我不知道如何以有用的方式使用该类型,即你可以通过Reflection转换为返回的类型(尽管dunno关于性能)

dbleField = Convert.ChangeType(yourValue, GetPropertyType<YourObject>(o=>o.NameOfDoubleProperty);

或在api方法中使用此功能 - 但是此方法必须返回object,因为我们不知道它将是什么类型 - 这就是为什么我更喜欢使用两个通用参数的方法。< / p>