引用不同类型的Func

时间:2011-02-28 14:17:52

标签: c# .net-3.5 lambda expression-trees

我有一个可以注册func来解析每种类型的id值的单例:

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

例如:

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

然后我想解析一个对象的id,如下所示:

GetObjectId(myPost);

其中GetObjectId定义为

public uint GetObjectId(object obj)

问题是,我如何为每个func存储一个引用以便最近调用它。 问题是每个func都有不同的T类型,我不能这样做:

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

如何解决?表达树?

问候 埃塞基耶尔

6 个答案:

答案 0 :(得分:2)

您有两种选择:

  1. GetObjectId更改为采用T的通用函数 然后,您可以store the Func<T, uint>s in a generic static class通过撰写FuncStorage<T>.Value(obj)来调用它们。

  2. 使用表达式树创建调用Func<object, uint>的{​​{1}}(使用强制转换)并将其放入Func<T, uint>
    编辑:您不需要表达式树来执行此操作;你可以使用一个普通的lambda表达式,它转换为Dictionary<Type, Func<object, uint>>。我正在考虑相反的情况(从非泛型代理生成泛型委托),这需要表达式树。

答案 1 :(得分:2)

你不需要像你建议的那样做表达树,只需要在注册时嵌套函数。

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

答案 2 :(得分:1)

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);
        }
    }

答案 3 :(得分:1)

  

问题是每个func都有一个   不同的T型,我不能这样做   像这样的东西:

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

我不确定你为什么这么说。这有效:

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);
}

用法:

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();

    }
}

答案 4 :(得分:1)

@SLacks,按照你的建议我改变了我的方法:

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);
}

谢谢!

答案 5 :(得分:0)

我无法将GetObjectId更改为GetObjectId<T>,因为我不知道运行时的类型。

所以,我已将字典定义更改为:

private Dictionary<Type, Delegate> _typeMap 

然后通过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;
}

非常感谢你