I have the following function. I would like to call and convert a string to int32. How to do I call this function?
static Func GetConverter(T example)
static Func<string, T> GetConverter<T>(T example)
{
return (x) => Convert<T>(x);
}
This is the code used for converting. I got this code from StackOverflow but not sure how to use.
static T Convert<T>(string val)
{
Type destiny = typeof(T);
// See if we can cast
try
{
return (T)(object)val;
}
catch { }
// See if we can parse
try
{
return (T)destiny.InvokeMember("Parse", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public, null, null, new object[] { val });
}
catch { }
// See if we can convert
try
{
Type convertType = typeof(Convert);
return (T)convertType.InvokeMember("To" + destiny.Name, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public, null, null, new object[] { val });
}
catch { }
// Give up
return default(T);
}
If you must to use GetConverter method, you should first call it to get converter function.
Assuming GetConverter is under class named A:
int value = 0;
var converter = A.GetConverter(value);
then you can call the converter from GetConverter method like a local function:
value = converter("123");
I think you don't have to pass a parameter to GetConverter function. This implementation is better since you dont use example parameter:
static Func<string, T> GetConverter<T>()
{
return (x) => Convert<T>(x);
}
So now you can use it like:
var converter = A.GetConverter<int>();
int value = converter("123");
PS: You can use int.TryParse method instead if you know the target (int) and source (string) types. Or you can use the converter function itself without getting another function to wrap it, like: Convert< int >("123")
Related
I am using the following code to convert a string to a specified type. In this example, I have hardcoded the type as double, but it could be any type, such as int, long, bool, or others.
However, if the string is empty or null, this code will fail. Is there a way to return the default value of the specified type in this case, rather than causing an exception?"
var result = ConvertFromString(item, typeof(double));
private object ConvertFromString(string str, Type type)
{
return Convert.ChangeType(str, type);
}
You could use Activator.CreateInstance to create an instance of a value type:
private static object ConvertFromString(string str, Type type)
{
if (string.IsNullOrEmpty(str))
return type.IsValueType ? Activator.CreateInstance(type) : null;
return Convert.ChangeType(str, type);
}
ConvertFromString(null, typeof(int)) will then return 0 (or default(int)).
I would make your method generic to return the actual requested type instead of object, to be more type safe. You will find the actual answer to the default thing below too.
[TestMethod]
public void MyTestMethod()
{
// to be sure that the decimal sign below is "." and not e.g. "," like in my culture :)
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
// test
var result = ConvertFromString<double>("3.14");
Assert.AreEqual(3.14, result);
// test
result = ConvertFromString<double>("blabla");
Assert.AreEqual(0, result);
}
private TRet ConvertFromString<TRet>(string str)
{
TRet ret = default(TRet);
try
{
ret = (TRet)Convert.ChangeType(str, typeof(TRet));
}
catch (Exception ex)
{
// handle error as you wish
}
return ret;
}
I'm trying to use the Convert method on functions as well as actions, so I can avoid writing duplicate methods taking in delegates of Func type. Convert method comes from Convert Action<T> to Action<object>
public class Program
{
static void Main(string[] args)
{
var program = new Program();
var mi = program.GetType().GetMethod("Function", BindingFlags.Instance | BindingFlags.Public);
// Can be any version of Func
var funcType = typeof(Func<int, int>);
// Create action delegate somehow instead
var del = mi.CreateDelegate(funcType, null);
// Or dynamically convert the Func to a corresponding Action type (in this case Action<int>)
}
// Or find a way to pass it in as a parameter here
public Action<object> Convert<T>(Action<T> action)
{
return o => action((T)o);
}
public int Function(int five)
{
return five;
}
}
I think you are looking for something like this:
public static Action<T1> IgnoreResult<T1,T2>(Func<T1,T2> func)
{
return x => func(x);
}
But for all variants of Func<T1,T2....>
I think this would work:
public static Action<TR> IgnoreResult<TR>(Delegate f)
{
return x => f.DynamicInvoke(x);
}
With usage:
var action = IgnoreResult<int>(new Func<int,int>(program.Function));
action(5);
You'll not be able to get it to infer the parameters and return type without copy and pasting the first example for all variants of Action<T1...> and Func<T1,T2...>.
I've created a class that works with my cache to get cached items. If the items are not cached then it calls a function to get the actual value.
This class has eight methods, all with almost identical code except for the function they call. I've created a function called GetObject which takes a delegate to call if it can't find an item in the class.
I can't get my code to compile because of the following error:
Argument 2: cannot convert from
'System.Collections.Generic.List<string>' to
'MyFunction<System.Collections.Generic.List<string>>'.
Am I doing something wrong or am I'm trying to do something that can't be done?
Here's the code I'm trying.
public delegate T MyFunction<T>(string s);
public T GetCultures<T>(string s) where T : class {
return NewListOfStrings(s) as T;
}
public List<string> NewListOfStrings(string s) {
return new List<string> { s };
}
public List<string> GetListOfStrings(string sitename) {
string key = cachingService.CreateValidKey("stringvalue");
//This is the line that fails to compile
var foundItems = GetObject<List<string>>(key,
GetCultures<List<string>>(sitename));
return foundItems;
}
public T GetObject<T>(string key, MyFunction<T> f) where T : class {
T foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
lock (key) {
foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
foundItems = f as T;
if (foundItems != null) {
cachingService.SetCachedItem(key, foundItems, 5,
Constants.MINUTES);
}
}
}
}
return foundItems;
}
Solution
public T GetObject<T>(string key, Func<T> getFromRepository) where T : class {
T foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
lock (key) {
foundItems = (T)cachingService.GetCachedItem(key);
if (foundItems == null) {
foundItems = getFromRepository() as T;
if (foundItems != null) {
cachingService.SetCachedItem(key, foundItems, 5,
Constants.MINUTES);
}
}
}
}
return foundItems;
}
public AreaModels.Site GetSiteByName(string sitename) {
string key = cachingService.CreateValidKey(
string.Format("Site_{0}", sitename));
return GetObject<AreaModels.Site>(key,
() => efRepository.GetSiteByName(sitename));
}
public List<AreaModels.Culture> GetCulturesForSite(string sitename) {
string key = cachingService.CreateValidKey(
string.Format("Cultures_{0}", sitename));
return GetObject<List<AreaModels.Culture>>(key,
() => efRepository.GetCulturesForSite(sitename));
}
public List<AreaModels.Resource> Resources(string sitename, int appId) {
string key = cachingService.CreateValidKey(
string.Format("ResourcesFor{0}", sitename));
return GetObject<List<AreaModels.Resource>>(key,
() => efRepository.GetResourcesBySiteAndAppId(sitename, appId));
}
You're passing the result of the function rather than the function itself. You can use a lambda like so:
var foundItems = GetObject<List<string>>(key,
name => GetCultures<List<string>>(sitename));
You also have this line:
foundItems = f as T;
Here you're trying to cast the function itself to its return type, which won't work. Instead you could do:
foundItems = f(name);
But now your problem is that you'd have to pass the name into GetObject, because otherwise it won't be accessible where it's needed. The reason for this is there's a mismatch between MyFunction, which takes a string, and what you actually want, which is a function that can be evaluated within GetObject without needing the name parameter to be passed in.
So what you should really do is change your delegate to:
public delegate T MyFunction<T>();
Or alternatively get rid of the delegate altogether and have the f parameter be a Func<T>.
With either of these options, you can pass in the lamba with no parameter required:
var foundItems = GetObject<List<string>>(key,
() => GetCultures<List<string>>(sitename));
And evaluate it like:
foundItems = f();
Note that it's a bit roundabout to create a lambda to pass it into another method just to then evaluate it, rather than just passing the result in directly. So unless there's some reason that you need to do this in some cases, you might instead want to change the f parameter to take a type T instead. In this case I suspect you're doing it to lazily evaluate the function so that you don't have to evaluate if the result is already cached. That would probably be a valid reason, assuming you're not optimizing for performance prematurely.
You aren't creating a delegate. You are actually evaluating the method before calling GetObject. Easily fixed:
var foundItems = GetObject<List<string>>(key,
name => GetCultures<List<string>>(name));
Note also that it isn't obvious what you want to do with sitename in this scenario; you might instead mean this:
name => GetCultures<List<string>>(sitename));
Here's a complete example
public class TestDelegate
{
//You don't need generic here if you always return a list of string
public List<string> GetCulture(string s)
{
return new List<string> { s };
}
public T GetObject<T>(string key, Func<string, T> fn)
{
T foundItems = fn(key);
return foundItems;
}
public void Test()
{
List<string> test = GetObject("abc", x => GetCulture(x));
}
}
If you look at the method Test() and GetObject(), you can note 3 interesting things :
You don't have to specify the generic type on GetObject() because the compiler infer it from GetCulture()
The x parameter serves as an input to your delegate function, that way the method
GetObject can use the "key" and pass it to the delegate function.
I replace your delegate function by "Func" with a string input and a List output.
In browsing other answers, I have come up with the following extension method which works a treat:
public static T Convert<T>( this string input )
{
var converter = TypeDescriptor.GetConverter( typeof( T ) );
if ( converter != null )
{
try
{
T result = (T) converter.ConvertFromString( input );
return result;
}
catch
{
return default( T );
}
}
return default( T );
}
And I can use it like:
string s = "2011-09-21 17:45";
DateTime result = s.ConvertTo( typeof( DateTime ) );
if ( result == DateTime.MinValue )
doSomethingWithTheBadData();
Awesome! Works great. Now, I'd like to do something similar with a reflected type. I have:
public static dynamic ConvertTo( this string input, Type type )
{
var converter = TypeDescriptor.GetConverter( type );
if ( converter != null )
{
try
{
dynamic result = converter.ConvertFromString( input );
return ( result );
}
catch
{
return default( type ); // bogus
}
}
return default( type ); // bogus
}
And I'd like to use it thus:
Type someType; // will be DateTime, int, etc., but not known until runtime
DateTime result = s.ConvertTo( sometype );
if ( result == DateTime.MinValue )
doSomethingWithTheBadData();
Of course, the compiler objects to the 'bogus' lines in the ConvertTo method. What I need (ok, don't necessarily need, but it'd be nice) is a way to get the same result as in the first example so that if the conversion fails, something that can be assigned to the reflected object is returned and can be recognized in the same manner as in the first example.
Edit:
What I finished with:
public static dynamic ConvertTo( this string input, Type type, out bool success )
{
dynamic result;
var converter = TypeDescriptor.GetConverter( type );
if ( converter != null )
{
try
{
result = converter.ConvertFromString( input );
success = true;
return result;
}
catch { /* swallow the exception */ }
}
result = type.IsValueType ? Activator.CreateInstance( type ) : null;
success = false;
return result;
}
and used:
bool success;
string val = "2011-09-21 17:25";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( success )
doSomethingGood();
val = "foo";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( !success )
dealWithBadData();
Remembering that, for the purpose of demonstration, I'm hard-coding the typeof() bit. In my application, the types are all reflected.
Thanks to all for the speedy answers!
You can use
//to get default(T) from an instance of Type
type.IsValueType ? Activator.CreateInstance(type) : null;
This is because value types are guaranteed to have a default constructor, and the default value of a reference type is a null.
If you're passing in the type using typeof(Type), then obviously you could just use the first method. Assuming, then, that you're getting the type via reflection (which you say you are) then you can also use reflection to get the MethodInfo for your first version of Convert(), and then use MakeGenericMethod() to substitute your reflected type into it:
MethodInfo m = typeof(MyConvertExtensions).GetMethod("Convert");
MethodInfo invocable = m.MakeGenericMethod(myReflectedType);
invocable.Invoke(null, new[] { myString });
Untested, but maybe something like this?
public static dynamic ConvertTo(this string input, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter != null)
{
try
{
return converter.ConvertFromString(input);
}
catch
{
// ignore
}
}
if (type.IsValueType)
return Activator.CreateInstance(type);
return null;
}
My particular problem:
I have a string which specifies an aribitrary type in a configuration class
Config.numberType = "System.Foo";
where Foo is a type like Decimal or Double
I use Type.GetType(Config.numberType) to return the corresponding type.
How do I get from that type to being able to use, System.Foo.TryParse() ?
Some further related queries
TryParse() can be accessed from System.Foo.TryParse() as well as foo.TryParse(). Does this mean foo is some kind of class in C#? This seems weird to me that int, double etc are actually not just modifier keywords.
How can you declare variables under these circumstances? - var is not universally usable it seems i.e. only in local scope etc.
As many have said - there isn't a direct route. I expect one close option is TypeConverter:
Type type = typeof(double);
string text = "123.45";
object value = TypeDescriptor.GetConverter(type)
.ConvertFromInvariantString(text);
Of course, you may need try/catch to handle exceptions. Such is life.
How do I get from that type to being
able to use, System.Foo.TryParse() ?
You'll need to use reflection to look up and then invoke the static TryParse() method. Not all types implement this method - so you'll have to decide how to handle it if it's missing. You could also use System.Convert to convert a string to an arbitrary type, assuming the string is actually a valid representation of a value for that type and there's a conversion implemented for it.
TryParse() can be accessed from
System.Foo.TryParse() as well as
foo.TryParse(). Does this mean foo is
some kind of class in C#?
int, double, etc. are aliases for System.Int32, System.Double, etc. - they're part of the C# language, which would be uncomfortably verbose without them.
How can you declare variables under
these circumstances?
Without knowing the type at compile-time, you'll be forced to declare and work with your data as object / System.Object. C# 4.0 will introduce actual dynamic types that will take care of some of the tedious reflection work for you, but for now you're stuck doing it by hand. Note that if you use System.Convert in a method with a parametrized type argument and return, or TryParse() using a technique such as that linked to by Sebastian Sedlak, you can easily achieve the ability to write client code that works with static types... So long as they match or can be converted to from the types you're parsing.
EDITED: I removed the generic implementation and cleaned up this response to fit better to the originally stated problem.
NOTE: The answer by Marc Gravell is probably the most concise if you just want the parsed value given the type. The answer below shows you how to get at the method (i.e., the MethodInfo object and how to invoke it).
The following should work, at least for types that implement public static bool TryParse(string, T value):
public static class Parsing
{
static MethodInfo findTryParseMethod(Type type)
{
//find member of type with signature 'static public bool TryParse(string, out T)'
BindingFlags access = BindingFlags.Static | BindingFlags.Public;
MemberInfo[] candidates = type.FindMembers(
MemberTypes.Method,
access,
delegate(MemberInfo m, object o_ignored)
{
MethodInfo method = (MethodInfo)m;
if (method.Name != "TryParse") return false;
if (method.ReturnParameter.ParameterType != typeof(bool)) return false;
ParameterInfo[] parms = method.GetParameters();
if (parms.Length != 2) return false;
if (parms[0].ParameterType != typeof(string)) return false;
if (parms[1].ParameterType != type.MakeByRefType()) return false;
if (!parms[1].IsOut) return false;
return true;
}, null);
if (candidates.Length > 1)
{
//change this to your favorite exception or use an assertion
throw new System.Exception(String.Format(
"Found more than one method with signature 'public static bool TryParse(string, out {0})' in type {0}.",
type));
}
if (candidates.Length == 0)
{
//This type does not contain a TryParse method - replace this by your error handling of choice
throw new System.Exception(String.Format(
"Found no method with signature 'public static bool TryParse(string, out {0})' in type {0}.",
type));
}
return (MethodInfo)candidates[0];
}
public static bool TryParse(Type t, string s, out object val)
{
MethodInfo method = findTryParseMethod(t); //can also cache 'method' in a Dictionary<Type, MethodInfo> if desired
object[] oArgs = new object[] { s, null };
bool bRes = (bool)method.Invoke(null, oArgs);
val = oArgs[1];
return bRes;
}
//if you want to use TryParse in a generic syntax:
public static bool TryParseGeneric<T>(string s, out T val)
{
object oVal;
bool bRes = TryParse(typeof(T), s, out oVal);
val = (T)oVal;
return bRes;
}
}
Use the following test code:
public bool test()
{
try
{
object oVal;
bool b = Parsing.TryParse(typeof(int), "123", out oVal);
if (!b) return false;
int x = (int)oVal;
if (x!= 123) return false;
}
catch (System.Exception)
{
return false;
}
try
{
int x;
bool b = Parsing.TryParseGeneric<int>("123", out x);
if (!b) return false;
if (x != 123) return false;
}
catch (System.Exception)
{
return false;
}
try
{
object oVal;
bool b = Parsing.TryParse(typeof(string), "123", out oVal);
//should throw an exception (//no method String.TryParse(string s, out string val)
return false;
}
catch (System.Exception)
{
//should throw an exception
}
return true;
}
}
And use this in your case:
//input: string s, Config
Type tNum = Type.GetType(Config.numberType);
object oVal;
bool ok = Parsing.TryParse(tNum, s, out oVal);
//oVal is now of type tNum and its value is properly defined if ok == true
About the use of var: you may have a misconception of what var does: It is not a "variant" type (the type object already is used for that) but moves the declaration syntax for the type to the assignment's right side. The following declarations are equivalent:
var i = 1; //the compiler infers the type from the assignment, type of i is int.
int i = 1; //type of i is int via declaration
The primary use of var is allowing to create anonymous types:
var anon = new { Name = "abc", X = 123 };
And another good link to this problem. The source code on that site is very bad formatted, so i putted it here. Hopefully, the author doesn't sue me.
public static T Parse<T>(string s)
{
Type t = typeof(T);
// Attempt to execute the Parse method on the type if it exists.
MethodInfo parse = t.GetMethod("Parse", new Type[] { typeof(string) });
if (parse != null)
{
try
{
return (T)parse.Invoke(null, new object[] { s });
}
catch (Exception ex)
{
throw ex.InnerException;
}
}
else
{
throw new MethodAccessException(String.Format("The Parse method does not exist for type {0}.", t.Name));
}
}
public static bool TryParse<T>(string s, out T result)
{
return TryParse<T>(s, false, out result);
}
public static bool TryParse<T>(string s, bool throwException, out T result)
{
result = default(T);
Type t = typeof(T);
T type = default(T);
// Look for the TryParse method on the type.
MethodInfo tryParse = t.GetMethod("TryParse", new Type[] { typeof(string), Type.GetType(t.FullName + "&") });
if (tryParse != null)
{
// Try parse exists. Call it.
Object[] ps = new Object[2];
ps[0] = s;
bool isSuccess = (bool)tryParse.Invoke(type, ps);
if (isSuccess)
result = (T)ps[1];
return isSuccess;
}
else
{
// TryParse does not exist. Look for a Parse method.
try
{
result = Parse<T>(s);
return true;
}
catch
{
if (throwException)
throw;
return false;
}
}
}
this may help: http://theengineroom.provoke.co.nz/archive/2007/04/27/generic-tryparse-type-conversion.aspx