简体   繁体   中英

Calling a static Func from a static class using reflection

Given the static class:

public static class Converters
{
    public static Func<Int64, string> Gold = c => String.Format("{0}g {1}s {2}c", c/10000, c/100%100, c%100);
}

I am receiving the Func name from a database as a string ( regEx.Converter ). How can I invoke the Gold Func using reflection? Here is what I have so far:

var converter = typeof(Converters).GetMember(regEx.Converter);
if (converter.Count() != 1)
{
    //throw new ConverterNotFoundException;
}                    
matchedValue = converter.Invoke(null, new object[]{matchedValue}) as string;

Edit:

I should have mentioned that I plan on adding other Funcs to my Converters class that may take different parameters.

Edit2: From the replies so far, I have it working for the Gold Func below. I suppose my question now is, how do I make this work when I don't know the parameters of the Func . For example, I may want to create another converter as so: Func<string, string> . The only thing I can be certain of is that there will only be one parameter (of differing types) and the return will always be string.

var converter = typeof(Converters).GetField("w", BindingFlags.Static | BindingFlags.Public);
if (converter == null)
{
    //throw new ConverterNotFoundException;
}
var f = converter.GetValue(null) as Func<Int64, string>;
matchedValue = f.Invoke(Convert.ToInt64(matchedValue));

You need to specify BindingFlags to get static members:

var converter = typeof(Converters).GetMember(regEx.Converter,
    BindingFlags.Static | BindingFlags.Public);

You could also simplify this by using GetField if it will never be a property:

FieldInfo converter = typeof(Converters).GetField(regEx.Converter,
    BindingFlags.Static | BindingFlags.Public);

Edit:
I'm not sure it'll be much help as you'll still need to know what sort of arguments to pass the Func<> , but this will let you invoke the Func<> without casting it:

var matchedValue = converter.GetValue(null);
matchedValue.GetType().GetMethod("Invoke")
    .Invoke(matchedValue, new object[] { Convert.ToInt64(0) });

And to get the type of the argument:

matchedValue.GetType().GetGenericArguments()[0];

You should consider the possibility that it will be easier to switch on the field name and avoid reflection altogether.

Since it's not a function or a property, you cannot invoke the member like that. You should get its value first, cast it as appropriate, and only then invoke the result, like this:

var converter = typeof(Converters).GetField(regEx.Converter);
var f = converter.GetValue(null) as Func<long,string>;
var matchedValueString = f(matchedValueInt);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM