开发者

references to Func's of different types

开发者 https://www.devze.com 2023-02-14 09:20 出处:网络
I have a singleton that can register a func to resolve an id value for each type: public void RegisterType<T>(Func<T, uint> func)

I have a singleton that can register a func to resolve an id value for each type:

public void RegisterType<T>(Func<T, uint> func)

for example:

RegisterType<Post>(p => p.PostId );
RegisterType<Comment>(p => p.CommentId );

and then i want to resolve the id for an object, like these:

GetObjectId(myPost);

where GetObjectId definition is

public uint GetObjectId(object obj)

The question is, how can i store a reference for each func to invoke it lately. The problem is that each func has a different T type, and I can't do something like this:

开发者_如何学Goprivate Dictionary<Type, Func<object, uint>> _typeMap;

How can resolve it? Expression trees?

regards Ezequiel


You don't need Expression Trees to do it the way you are suggesting, just need to nest the function when registering it.

public void RegisterType<T>(Func<T, uint> func){
             _typeMap.Add(typeof(T), obj=>func((T)obj));
}


You have two options:

  1. Change GetObjectId to a generic function that takes a T.
    You can then store the Func<T, uint>s in a generic static class and call them by writing FuncStorage<T>.Value(obj).

  2. Use expression trees to Create Func<object, uint>s that calls the Func<T, uint> (using a cast) and put those in your Dictionary<Type, Func<object, uint>>.
    EDIT: You don't need expression trees to do that; you can use a normal lambda expression which casts to T. I was thinking of the reverse case (generating a generic delegate from a non-generic one), which does require expression trees.


public class Registration
    {
        public static Registration Instance = new Registration();

        private Registration()
        {
        }

        private Dictionary<Type, object> Dictionary = new Dictionary<Type, object>();

        public void Register<T>(Func<T, uint> aFunc)
        {
            Dictionary[typeof(T)] = aFunc;
        }

        public uint GetId<T>(T aT)
        {
            var f = Dictionary[typeof(T)];
            var g = (Delegate)f;
            return (uint) g.DynamicInvoke(aT);
        }
    }


The problem is that each func has a diferent T type, and i cant do something like these:

private Dictionary<Type, Func<object, uint>> _typeMap;

I'm not sure why you say this. This works:

class Post
{
    public uint PostId { get; set; }
}

static public void RegisterType<T>(Func<T, uint> getUintFromT)
{
    Func<object, T> toT = (t => (T)t);

    Func<object, uint> getUintFromObject = 
        @object => getUintFromT(toT(@object));

    _typeMap.Add(typeof(T), getUintFromObject);
}

static public uint GetObjectId(object obj)
{
    return _typeMap[obj.GetType()](obj);
}

Usage:

class Program
{
    private static Dictionary<Type, Func<object, uint>> _typeMap 
        = new Dictionary<Type, Func<object, uint>>();

    static void Main(string[] args)
    {
        RegisterType<Post>(p => p.PostId);

        Post myPost = new Post();
        myPost.PostId = 4;

        var i = GetObjectId(myPost);

        Console.WriteLine(i);
        Console.ReadKey();

    }
}


@SLacks, following your advise i have changed my approach to:

private Dictionary<Type, Func<object, uint>> _typeMap;

public void RegisterType<T>(uint typeId, Func<T, uint> func)
{            
    _typeMap[typeof(T)] = (o) => func((T)o);
}

public uint GetObjectId(object obj)
{
    return _typeMap[obj.GetType()](obj);
}

thanks!


I cant change GetObjectId to GetObjectId<T> because i don´t known the type on runtime.

So, i have changed the dictionary definition to:

private Dictionary<Type, Delegate> _typeMap 

and then invoke it via Reflection:

public uint GetObjectId(object obj)
{
    uint id = 0;

    var objType = obj.GetType();

    // busco si el type está registrado
    if (_typeMap.Keys.Contains(objType))            
    {
        id = (uint) _typeMap[objType].Method.Invoke(obj, new object[] { obj } );                
    }

    return id;
}

Thank you all so much

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号