an example code what I try to do will surely do better than my english:
public bool IsNumericValueInBounds (string value, Type numericType)
{
double d = double.NaN;
bool inBounds = (bool)numericType.GetMethod ("TryParse").Invoke (null, new object[] { value, d });
return inBounds;
}
Unfortunately the TryParse method needs an out parameter so this doesn't work.
any ideas how to solve this?
(ps.: would'nt this be a nice example for duck typing? - because i know every numericType has an "TryParse" or I am mistaken?)
public static bool TryParse( string text, out int number ) { .. }
MethodInfo method = GetTryParseMethodInfo();
object[] parameters = new object[]{ "12345", null }
object result = method.Invoke( null, parameters );
bool blResult = (bool)result;
if ( blResult ) {
int parsedNumber = (int)parameters[1];
}
Related
I want to create an open delegate to the method ToString(string, IFormatprovider) of a struct (Int32, DateTime, whatever):
public delegate string MyCoverter(ref DateTime from, string format, IFormatProvider provider);
...
var method = typeof(DateTime).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider)}); // Works!
var d= Delegate.CreateDelegate(typeof(MyCoverter), null, method); // Exception!
It keeps throwing the ArgumentException with message "Error binding to target method.".
I've read almost all stackoverflow articles on this subject, I have experimented with and without ref, I have added and removed the null when creating the delegate. Nothing seems to help.
Has anyone any clue?
* EDIT *
When I create my own struct with the same method, the code above (with DateTime replaced my MyStruct) works perfectly fine.
public struct MyStruct
{
public string ToString(string format, IFormatProvider provider)
{
return null;
}
}
What makes an Int32 or DateTime so different?
* EDIT *
As requested I added a complete "working" program. What I forgot to mention: I am working on .NET framework 3.5. Furthermore, as I stated before, this is all working on MyStruct. Except, when I implement the interface IFormattable, it also does not work anymore.
using System;
namespace OpenDelegates
{
public delegate string MyCoverter<T>(ref T from, string format, IFormatProvider provider)
where T : struct;
class Program
{
static void Main(string[] args)
{
var method = typeof(MyStruct).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider) });
var d = Delegate.CreateDelegate(typeof(MyCoverter<MyStruct>), null, method);
method = typeof(DateTime).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider) });
d = Delegate.CreateDelegate(typeof(MyCoverter<DateTime>), null, method);
}
}
public struct MyStruct //: IFormattable
{
public string ToString(string format, IFormatProvider provider)
{
return null;
}
}
}
* EDIT *
It all works perfectly on .NET Framework 4.x, but that is NOT a solution for me.
I don't know the answer for that specific problem but maybe you can build your own delegate:
public static Func<object, string, IFormatProvider, string> CreateConverter<T>()
where T : struct // not really needed
{
var method = typeof(T).GetMethod("ToString", new[] { typeof(string), typeof(IFormatProvider) });
if (method == null)
{
throw new InvalidOperationException(string.Format("The type {0} does not contain a suitable ToString-method.", typeof(T).FullName));
}
var instanceParameter = Expression.Parameter(typeof(object), "instance");
var formatParameter = Expression.Parameter(typeof(string), "format");
var providerParameter = Expression.Parameter(typeof(IFormatProvider), "provider");
var convertedInstance = Expression.Convert(instanceParameter, typeof(T));
var methodCall = Expression.Call(convertedInstance, method, formatParameter, providerParameter);
var lambda = Expression.Lambda<Func<object, string, IFormatProvider, string>>(methodCall, instanceParameter, formatParameter, providerParameter);
return lambda.Compile();
}
Can be used like:
var d = CreateConverter<MyStruct>();
Console.WriteLine(d(new MyStruct(), "", CultureInfo.CurrentCulture));
d = CreateConverter<DateTime>();
Console.WriteLine(d(DateTime.Now, "yyyydd", CultureInfo.CurrentCulture));
EDIT to make sure that the input is of the correct type
public static Func<T, string, IFormatProvider, string> CreateConverter<T>()
{
var method = typeof(T).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string), typeof(IFormatProvider) }, null);
if (method == null)
{
throw new InvalidOperationException(string.Format("The type {0} does not contain a suitable ToString-method.", typeof(T).FullName));
}
var instanceParameter = Expression.Parameter(typeof(T), "instance");
var formatParameter = Expression.Parameter(typeof(string), "format");
var providerParameter = Expression.Parameter(typeof(IFormatProvider), "provider");
var methodCall = Expression.Call(instanceParameter, method, formatParameter, providerParameter);
var lambda = Expression.Lambda<Func<T, string, IFormatProvider, string>>(methodCall, instanceParameter, formatParameter, providerParameter);
return lambda.Compile();
}
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")
I need to call a method, passing an int. using the following code I can fetch the method but not passing the argument. How to fix it?
dynamic obj;
obj = Activator.CreateInstance(Type.GetType(String.Format("{0}.{1}", namespaceName, className)));
var method = this.obj.GetType().GetMethod(this.methodName, new Type[] { typeof(int) });
bool isValidated = method.Invoke(this.obj, new object[1]);
public void myMethod(int id)
{
}
The new object[1] part is how you're specifying the arguments - but you're just passing in an array with a single null reference. You want:
int id = ...; // Whatever you want the value to be
object[] args = new object[] { id };
method.Invoke(obj, args);
(See the MethodBase.Invoke documentation for more details.)
Note that method.Invoke returns object, not bool, so your current code wouldn't even compile. You could cast the return value to bool, but in your example that wouldn't help at execution time as myMethod returns void.
Just pass an object with the invoke method
namespace test
{
public class A
{
public int n { get; set; }
public void NumbMethod(int Number)
{
int n = Number;
console.writeline(n);
}
}
}
class MyClass
{
public static int Main()
{
test mytest = new test();
Type myTypeObj = mytest.GetType();
MethodInfo myMethodInfo = myTypeObj.GetMethod("NumbMethod");
object[] parmint = new object[] {5};
myMethodInfo.Invoke(myClassObj, parmint);
}
}
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;
}
I'm looking for more generic/"standard" way to instantiate object of some type T from set of pairs string,object. For me it looks like there should be some well known way to do it but I cannot find it, so I come up with this piece of code.
Does anybody know something better?
// usage
public class test
{
public int field1;
public string field2;
public bool field3;
public string[] field4;
public IDictionary<string,object> field5 { get; set; }
public static IDictionary<string,object> dynamic()
{
return new Dictionary<string,object>{
{ "field1", 2 },
{ "field2", "string" },
{ "field3", true },
{ "field4", new[] { "id3", "id4", "id5" } },
{ "field5", new Dictionary<string,object>{ { "id1", "" } } }
};
}
}
...
var r = new dynamic_data_serializer<test>().create( test.dynamic() );
...
//
public class dynamic_data_serializer< T >
{
public T create( object obj )
{
var result = default(T);
if ( obj == null )
return result;
var ttype = typeof(T);
var objtype = obj.GetType();
if ( ttype.IsAssignableFrom( objtype ) ) {
result = (T)obj;
return result;
}
if ( ttype.IsClass ) { // custom classes, array, dictionary, etc.
result = Activator.CreateInstance<T>();
if ( objtype == typeof(IDictionary<string,object>) ||
objtype == typeof(Dictionary<string,object>) ) {
var obj_as_dict = obj as IDictionary<string,object>;
var fields = ttype.GetFields();
if ( fields.Length > 0 )
set_fields_from( result, fields, obj_as_dict );
var properties = ttype.GetProperties();
if ( properties.Length > 0 )
set_properties_from( result, properties, obj_as_dict );
}
}
return result;
}
private void set_fields_from( T _this_, FieldInfo[] fields, IDictionary<string,object> obj ) {
foreach ( var fld in fields ) {
var v = find( obj, fld.Name );
if ( v != null ) {
var mobj = call_deserialize( fld.FieldType, v );
fld.SetValue( _this_, mobj );
}
}
}
private void set_properties_from( T _this_, PropertyInfo[] properties, IDictionary<string,object> obj ) {
foreach ( var prop in properties ) {
var v = find( obj, prop.Name );
if ( v != null ) {
var mobj = call_deserialize( prop.PropertyType, v );
prop.SetValue( _this_, mobj, null );
}
}
}
private object find( IDictionary<string,object> obj, string name ) {
foreach ( var kv in obj )
if ( string.Compare( kv.Key, name, true ) == 0 )
return kv.Value;
return null;
}
private object call_deserialize( Type des_type, object value ) {
var gtype = typeof(dynamic_data_serializer<>);
Type desz_type = gtype.MakeGenericType( new[]{ des_type } );
object desz = Activator.CreateInstance( desz_type );
var method_type = desz_type.GetMethod( "create" );
return method_type.Invoke( desz, new[]{ value } );
}
}
}
DataContractJsonSerializer is too slow, but you're using reflection? If you have to deserialize lots of objects, I would recommend using compiled lambdas instead of reflection. A lambda can only set properties, not fields (at least in .Net 3.5), so you may have to adjust the classes you use it on, but it's worth it because it's like 1000 times faster.
Here's a function that creates a property setter given a type and a PropertyInfo for the property to set:
static Action<object, TValue> MakeSetter<TValue>(Type tclass, PropertyInfo propInfo)
{
var t = lambda.Expression.Parameter(typeof(object), "t");
var v = lambda.Expression.Parameter(typeof(TValue), "v");
// return (t, v) => ((tclass)t).prop = (tproperty)v
return (Action<object, TValue>)
lambda.Expression.Lambda(
lambda.Expression.Call(
lambda.Expression.Convert(t, tclass),
propInfo.GetSetMethod(),
lambda.Expression.Convert(v, propInfo.PropertyType)),
t,
v)
.Compile();
}
You would have a dictionary of setters for each class, and whenever you have to set a property of a class, you would look up the setter for that property in the dictionary and call it with the value to assign, like this: setters[propName](_this_, value);
I might suggest FormatterServices.PopulateObjectMembers, except a: this is still slow AFAIK, and b: I tried it (below) and it seems to want to throw an exception on the property (don't know why; didn't look too deep). Another option may be Expression, but you don't really want to do the Compile each time (better to do it once only and cache it, but that demands a known format).
public T create(object obj)
{ // simplified for illustration
var bindings = obj as IDictionary<string, object>;
Type type = typeof(T);
var func = Expression.Lambda<Func<T>>(Expression.MemberInit(
Expression.New(type),
from pair in bindings
let member = type.GetMember(pair.Key).Single()
select (MemberBinding)Expression.Bind(member, Expression.Constant(pair.Value))));
return func.Compile().Invoke();
}
Finally, you might cache a set of pre-compiled Action<object> setters (keyed against the member name). In reality this is probably your best bet. Properties are easy (you use Delegate.CreateDelegate) - fields might need DynamicMethod - but if you can't predict the layout in advance it'll have the least overhead.
For the keyed / IL approach (you won't get faster):
public class dynamic_data_serializer<T>
{
public T create(object obj)
{
T inst = Activator.CreateInstance<T>();
var bindings = obj as IDictionary<string, object>;
foreach (var pair in bindings)
{
setters[pair.Key](inst, pair.Value);
}
return inst;
}
private static readonly Dictionary<string, Action<T, object>> setters;
static dynamic_data_serializer()
{
setters = new Dictionary<string, Action<T, object>>(StringComparer.Ordinal);
foreach (PropertyInfo prop in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance)) {
setters.Add(prop.Name, CreateForMember(prop));
}
foreach (FieldInfo field in typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance)) {
setters.Add(field.Name, CreateForMember(field));
}
}
static Action<T, object> CreateForMember(MemberInfo member)
{
bool isField;
Type type;
switch (member.MemberType) {
case MemberTypes.Property:
isField = false;
type = ((PropertyInfo)member).PropertyType;
break;
case MemberTypes.Field:
isField = true;
type = ((FieldInfo)member).FieldType;
break;
default:
throw new NotSupportedException();
}
DynamicMethod method = new DynamicMethod("__set_" + member.Name, null, new Type[] { typeof(T), typeof(object) });
ILGenerator il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
if(type != typeof(object)) {
il.Emit(type.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, type);
}
if (isField) {il.Emit(OpCodes.Stfld, (FieldInfo)member);}
else { il.EmitCall(OpCodes.Callvirt, ((PropertyInfo)member).GetSetMethod(), null); }
il.Emit(OpCodes.Ret);
return (Action<T, object>)method.CreateDelegate(typeof(Action<T, object>));
}
}
DataContractJsonSerializer
Why would you make a custom serializer and not use the DataContractJsonSerializer?
EDIT
If DataContractJsonSerializer doesn't fit you, you can try JSON.Net. Implementing a serializer efficiently is not an easy task, there's a lot of pitfalls and special cases that you may not want to get into. By the way, your code sample makes heavy use of reflection which is slow, I doubt that it will perform better than DataContractJsonSerializer or JSON.Net.