How do I create a delegate for a .NET property?

后端 未结 6 1821
眼角桃花
眼角桃花 2020-12-02 23:21

I am trying to create a delegate (as a test) for:

Public Overridable ReadOnly Property PropertyName() As String

My intuitive attempt was de

6条回答
  •  一生所求
    2020-12-03 00:12

    I just create an helper with pretty good performance : http://thibaud60.blogspot.com/2010/10/fast-property-accessor-without-dynamic.html It don't use IL / Emit approach and it is very fast !

    Edit by oscilatingcretin 2015/10/23

    The source contains some casing issues and peculiar ="" that have to be removed. Before link rot sets in, I thought I'd post a cleaned-up version of the source for easy copy pasta, as well as an example of how to use it.

    Revised source

    using System;
    using System.Collections.Concurrent;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;
    
    namespace Tools.Reflection
    {
        public interface IPropertyAccessor
        {
            PropertyInfo PropertyInfo { get; }
            object GetValue(object source);
            void SetValue(object source, object value);
        }
    
        public static class PropertyInfoHelper
        {
            private static ConcurrentDictionary _cache =
                new ConcurrentDictionary();
    
            public static IPropertyAccessor GetAccessor(PropertyInfo propertyInfo)
            {
                IPropertyAccessor result = null;
                if (!_cache.TryGetValue(propertyInfo, out result))
                {
                    result = CreateAccessor(propertyInfo);
                    _cache.TryAdd(propertyInfo, result); ;
                }
                return result;
            }
    
            public static IPropertyAccessor CreateAccessor(PropertyInfo PropertyInfo)
            {
                var GenType = typeof(PropertyWrapper<,>)
                    .MakeGenericType(PropertyInfo.DeclaringType, PropertyInfo.PropertyType);
                return (IPropertyAccessor)Activator.CreateInstance(GenType, PropertyInfo);
            }
        }
    
        internal class PropertyWrapper : IPropertyAccessor where TObject : class
        {
            private Func Getter;
            private Action Setter;
    
            public PropertyWrapper(PropertyInfo PropertyInfo)
            {
                this.PropertyInfo = PropertyInfo;
    
                MethodInfo GetterInfo = PropertyInfo.GetGetMethod(true);
                MethodInfo SetterInfo = PropertyInfo.GetSetMethod(true);
    
                Getter = (Func)Delegate.CreateDelegate
                        (typeof(Func), GetterInfo);
                Setter = (Action)Delegate.CreateDelegate
                        (typeof(Action), SetterInfo);
            }
    
            object IPropertyAccessor.GetValue(object source)
            {
                return Getter(source as TObject);
            }
    
            void IPropertyAccessor.SetValue(object source, object value)
            {
                Setter(source as TObject, (TValue)value);
            }
    
            public PropertyInfo PropertyInfo { get; private set; }
        }
    }
    

    Use it like this:

    public class MyClass
    {
        public int Id { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    }
    
    MyClass e = new MyClass();
    IPropertyAccessor[] Accessors = e.GetType().GetProperties()
        .Select(pi => PropertyInfoHelper.CreateAccessor(pi)).ToArray();
    
    foreach (var Accessor in Accessors)
    {
        Type pt = Accessor.PropertyInfo.PropertyType;
        if (pt == typeof(string))
            Accessor.SetValue(e, Guid.NewGuid().ToString("n").Substring(0, 9));
        else if (pt == typeof(int))
            Accessor.SetValue(e, new Random().Next(0, int.MaxValue));
    
        Console.WriteLine(string.Format("{0}:{1}",
            Accessor.PropertyInfo.Name, Accessor.GetValue(e)));
    }
    

提交回复
热议问题