0

2つ以上の拡張メソッドを別のメソッドにパラメータとして渡して値を返す方法を理解しようとしています。私は、各データ型が値またはデフォルト値と値またはヌル値と値を返す、またはエラーをスローする拡張メソッドを持っています。コードにはこれらのそれぞれが必要なシナリオがありますが、以下の例では3つのテストでこれらの結果を組み合わせたシナリオもあります。c#ジェネリックメソッドはパラメータとして関数を取る

public static int IntOrError(this object val, string fieldName) 
{ 
    int test; 

    if (string.IsNullOrEmpty(val.ToString())) 
    { 
     throw new Exception("I threw it"); 
    } 
    else if (int.TryParse(val.ToString(), out test) == false) 
    { 
     throw new Exception("Bad Int Value"); 
    } 
    else 
    { 
     return test; 
    } 
} 

public static int IntOrDefault(this object val) 
{ 
    int test; 

    if (int.TryParse(val.ToString(), out test)) 
    { 
     return test; 
    } 
    else 
    { 
     return -1; 
    } 
} 

public static int? IntOrNull(this object val) 
{ 
    int test; 

    if (int.TryParse(val.ToString(), out test)) 
    { 
     return test; 
    } 
    else 
    { 
     return -1; 
    } 
} 

私は、この例ではIntOrNull、IntOrDefaultとIntOrErrorの中に取って処理し、int型のバックパスやエラーを投げることができ、再利用可能なメソッドを作成しようとしてきました。これまで私はこれを動作させることしかできなかった。私はすべてのデータ型に対してもこのメソッドを作成しないようにしています。

public static int IntDefaultValidated(this object val, string fieldName) 
{ 
    return val.IntOrNUll() != null 
     ? val.IntOrDefaultError(fieldName) 
     : val.IntOrDefault(); 
} 

拡張メソッドをparamsとして受け取り、値を返す汎用メソッドまたはメソッドの機能スタイルを取得しようとしています。

可能であれば、反射を避けることを望んでいます。

//just a psuedo example 
var intVal = ""; 
var valRet = DefaultValidated(intVal.IntOrNull(), intVal.IntOrdefault(), intVal.IntOrDefaultError("intVal")); 
//or maybe like this, or some combination of extension, generic, functional 
var valRet = intVal.DefaultOrValidated(IntOrNull(intVal), IntOrDefault(intVal), IntOrDefaultError(intVal, "intVal")); 

答えて

0

IntOrDefault、IntOrNullとIntDefaultValidatedのあなたの論理は本当に意味がないので、私はそれだけで使用例だと思います。
これ以外にも、私のアドバイスは、あなたの関数を汎用的な拡張として実装することです。

public static class MyExtensions 
{ 
    public static T ValueOrError<T>(this object val) 
    { 
     try 
     { 
      // http://stackoverflow.com/a/8633/2534462 
      return (T)Convert.ChangeType(val, typeof(T)); 
     } catch 
     { 
      throw new Exception("Throw your own exception if you really want to"); 
     } 
    } 

    public static T ValueOrDefault<T>(this object val, T defaultValue) 
    { 
     try 
     { 
      return val.ValueOrError<T>(); 
     } 
     catch 
     { 
      return defaultValue; // usally use: return default(T); 
     } 
    } 

    public static T ValueOrNull<T>(this object val) 
    { 
     try 
     { 
      return val.ValueOrError<T>(); 
     } 
     catch 
     { 
      // check for nullable type 
      //https://msdn.microsoft.com/de-de/library/ms366789.aspx 
      var type = typeof(T); 
      if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
      { 
       return default(T); // null on nullable types 
      } else { 
       throw new Exception("Callable only on Nullable types"); 
       // my return another default value ??? .. -1 ??? 
      } 
     } 
    } 


    public static T ValueDefaultValidated<T>(this object val, T defaultValue) 
    { 
     return val.ValueOrNull<T>() != null 
      ? val.ValueOrError<T>() 
      : val.ValueOrDefault<T>(defaultValue); 
    } 
} 

使用

string aNumber = "10"; 
var intNumber = aNumber.ValueDefaultValidated(-1); // int 
var decNumber = aNumber.ValueDefaultValidated(-1m); // decimal 

string naNumber = "whatever"; 
var defaultInt = naNumber.ValueOrDefault(-1); // int 
var defaultDecimal = naNumber.ValueDefaultValidated<decimal?>(-1m); 
// ValueOrNull ist undefined on Non-Nullable-Type. 
var undefined = naNumber.ValueDefaultValidated<decimal>(-1m); 
+0

私は、エラー処理が同じに動作するようにこれを調整する必要があります。オリジナルでは、誰かが123aの悪いintで過去の場合。 Error拡張メソッドは、それが無効な形式であるという例外メッセージをスローします。ここでの答えロジックは、代わりにValueOrNull Exceptionメッセージをスローします。したがって、完全な1対1置換ではありません。 – langc334

0

このようなことはありますか?

public static T Convert<T>(this object input) 
{ 
    if (typeof (T) == input.GetType()) 
     return (T) input; 

    var stringValue = input.ToString(); 
    var converter = TypeDescriptor.GetConverter(typeof(T)); 
    if (converter.CanConvertFrom(typeof(string))) 
    { 
     return (T)converter.ConvertFrom(stringValue); 
    } 
    return default(T); 
} 

このテストに合格します。これは正確にあなたが必要とするものではありませんが、依然としてです。

[Fact] 
public void TestMethod1() 
{ 
    object testInt = 1; 
    object testString = "123"; 
    double testDouble = 1.0; 
    string testWrong = "abc"; 

    int resultInt = testInt.Convert<int>(); 
    string resultString = testString.Convert<string>(); 
    int resultIntString = testString.Convert<int>(); 
    int dbl2int = testDouble.Convert<int>(); 

    Assert.Throws<Exception>(() => testWrong.Convert<int>()); 

    Assert.Equal(1, resultInt); 
    Assert.Equal("123", resultString); 
    Assert.Equal(123, resultIntString); 
    Assert.Equal(1, dbl2int); 
}