user1618236
user1618236

Reputation:

How to get the the return type from a Func defined with a lambda?

I have a static class that is responsible for holding some default data used by integration tests, previously it was using a Dictionary<Type,object> to store these values but because I need to be able to modify the objects I get without affecting future requests for the same object I've moved to using a Dictionary<Type,Func<object>> which works great.

Now in attempt to make using this static data store easier for the end user I've added another class to wrap the dictionary:

public class FuncValueDictionary
{
    private readonly Dictionary<Type, Func<object>> _funcs;

    public FuncValueDictionary()
    {
        _funcs = new Dictionary<Type, Func<object>>();
    }

    public T Get<T>()
    {
        var key = typeof (T);
        if (_funcs.ContainsKey(key))
        {
            return (T)_funcs[key]();
        }
        throw new Exception("Dictionary does not contain a value for key: " + key);

    }

    public void Add(Func<object> value)
    {
        var key = value().GetType();
        if (_funcs.ContainsKey(key))
        {
            throw new Exception("Dictionary already contains value for key: " + key);
        }

        _funcs[key] = value;
    }
}

As is this works, but my problem with it is that it currently has to run the function when adding a new value (this is to get the return type of the function to be stored).

An example of adding a value:

var DefaultData = new FuncValueDictionary()
...
DefaultData.Add(() => new TestDataSet { SomeTestDataValue = "10.00" });

I am trying to find a method to determine this type from the function itself and I've tried value.Method.ReturnType but this is just returning object.

Is there anyway to get the correct type given the current step, or perhaps a different approach of achieving a static data store that returns a new instance everytime?

Upvotes: 1

Views: 92

Answers (1)

tolanj
tolanj

Reputation: 3724

Requires .Net >= 4.0

Replace the Add method with a Generic:

public void Add<T>(Func<T> value) where T:class
{
    if (_funcs.ContainsKey(typeof(T)))
    {
        throw new Exception("Dictionary already contains value for key: " + typeof(T));
    }

    _funcs[typeof(T)] = value;
}

Apologies for pasting the earlier reply in hastily!

Of course this isn't going to work for a value type

NB

(stolen from a since deleted reply!)

For .Net <= 4.0 you can do:

public void Add<T>(Func<T> value) where T:class
{
    if (_funcs.ContainsKey(typeof(T)))
    {
        throw new Exception("Dictionary already contains value for key: " + typeof(T));
    }

    _funcs[typeof(T)] = () => (object)value();
}

Which removes the need for Generic variance

Upvotes: 2

Related Questions