ссылки на функции разных типов - PullRequest
7 голосов
/ 28 февраля 2011

У меня есть синглтон, который может зарегистрировать функцию для разрешения значения идентификатора для каждого типа:

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

, например:

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

, а затем я хочу разрешить идентификатордля объекта, подобного этому:

GetObjectId(myPost);

, где определение GetObjectId равно

public uint GetObjectId(object obj)

Вопрос в том, как я могу сохранить ссылку для каждой функции, чтобы вызывать ее в последнее время.Проблема в том, что у каждого функционала свой T-тип, и я не могу сделать что-то вроде этого:

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

Как можно решить?Деревья выражений?

С уважением, Иезекииль

Ответы [ 6 ]

2 голосов
/ 28 февраля 2011

Деревья выражений вам не нужны, чтобы делать это так, как вы предлагаете, просто нужно вложить функцию при регистрации.

public void RegisterType<T>(Func<T, uint> func){
             _typeMap.Add(typeof(T), obj=>func((T)obj));
}
2 голосов
/ 28 февраля 2011

У вас есть два варианта:

  1. Измените GetObjectId на общую функцию, которая принимает T.
    Затем вы можете сохранить Func<T, uint> s в общем статическом классе и вызвать их, написав FuncStorage<T>.Value(obj).

  2. Используйте деревья выражений для Создайте Func<object, uint> s, который вызывает Func<T, uint> (используя приведение) и поместите их в Dictionary<Type, Func<object, uint>>.
    EDIT : Вам не нужны деревья выражений для этого; Вы можете использовать нормальное лямбда-выражение, которое приводит к T. Я думал об обратном случае (генерации универсального делегата из неуниверсального), который требует деревьев выражений.

1 голос
/ 01 марта 2011

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

спасибо!

1 голос
/ 28 февраля 2011

Проблема в том, что каждый функционал имеет свой тип 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();

    }
}
1 голос
/ 28 февраля 2011
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);
        }
    }
0 голосов
/ 28 февраля 2011

Я не могу изменить 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;
}

Большое вам спасибо

...