Результаты отражения кэша (свойства класса) - PullRequest
7 голосов
/ 30 июля 2009

учитывая, что довольно статические данные не следует переоценивать, а вместо этого кэшировать, я подумал, возможно ли использовать Reflection для получения свойств класса один раз, а затем кэшировать их, чтобы я мог динамически оценивать свойства объекта и читать / присваивать значения , но не каждый раз, когда я делаю это Возможно ли это (пример кода?)?

Чтобы пояснить немного, допустим, у меня есть этот класс:

public class Cloud
{
     Boolean IsWhite;
}

и сейчас я пытаюсь создать метод, который позволяет мне делать что-то вроде этого (псевдокод):

Update(myCloudInstance, new {IsWhite, true});

Обновление теперь должно сначала проверить с кешем, знает ли он уже свойства Cloud (typeof (myCloudInstance)), а затем использовать кэшированную информацию, чтобы присвоить свойству «IsWhite» значение «true» вместо повторного выполнения Reflection.

Есть идеи, как это сделать?

Ответы [ 5 ]

8 голосов
/ 30 июля 2009

Непонятно точно что вы делаете, но кеширование, безусловно, может иметь значение с отражением.

В частности, если вы вызываете методы (или методы получения / установки свойств) и можете делать это безопасным с точки зрения типов способом, что касается вызывающего кода, это может сделать огромным разница если вы конвертируете MethodInfo в строго типизированный делегат один раз, а затем повторно его используете.

Если бы вы могли дать нам полный пример того, что вы пытаетесь сделать, это помогло бы нам придумать более конкретные идеи или даже код. Если вы просто собираетесь кешировать PropertyInfo, который может не иметь такого большого (или какого-либо) эффекта - вполне возможно, что обычные Type.GetProperty (и т. Д.) Методы уже довольно быстрые. Как и в случае с вопросами производительности, ключевым является измерение того, что вы на самом деле делаете. Внесите изменения и повторите измерения и т. Д.

2 голосов
/ 07 ноября 2011

Я создал хеш-таблицу для кэширования результатов отражения. В первый раз необходимо позвонить в GetProperties и сохранить результаты в hastable. В следующий раз сначала проверьте хеш-таблицу для списка объектов PropertyInfo. Если существует, используйте его. Если нет, вызовите GetProperties.

Я использую это для сопоставления устройства чтения данных со списком сущностей.

Моя реализация основана на: Защита по отражению в .Net , Ник Харрисон (http://www.simple -talk.com / dotnet / .net-framework / a-defense-of -reflection-in-.net/).

Итак, вот оно:

public class MapeadorDataReaderListaObjetos
{

    private Hashtable properties;

    private Hashtable Properties
    {
        get
        {
            if (properties == null)
                properties = new Hashtable();
            return properties;
        }
        set { properties = value; }
    }

    private void LoadProperties(object targetObject, Type targetType)
    {
        var flags = BindingFlags.DeclaredOnly| BindingFlags.Instance| BindingFlags.Public;

        if (properties == null)
        {
            List<PropertyInfo> propertyList = new List<PropertyInfo>();
            PropertyInfo[] objectProperties = targetType.GetProperties(flags);
            foreach (PropertyInfo currentProperty in objectProperties)
            {
                propertyList.Add(currentProperty);
            }
            properties = new Hashtable();
            properties[targetType.FullName] = propertyList;
        }

        if (properties[targetType.FullName] == null)
        {
            List<PropertyInfo> propertyList = new List<PropertyInfo>();
            PropertyInfo[] objectProperties = targetType.GetProperties(flags);
            foreach (PropertyInfo currentProperty in objectProperties)
            {
                propertyList.Add(currentProperty);
            }
            properties[targetType.FullName] = propertyList;
        }
    }

    public void MapearDataReaderListaObjetos <T> (IDataReader dr, List<T> lista) where T: new()
    {
        Type businessEntityType = typeof(T);
        List<T> entitys = new List<T>();
        T miObjeto = new T();
        LoadProperties(miObjeto, businessEntityType);
        List<PropertyInfo> sourcePoperties = Properties[businessEntityType.FullName] as List<PropertyInfo>;

        while (dr.Read())
        {
            T newObject = new T();
            for (int index = 0; index < dr.FieldCount; index++)
            {
                for (int _indice = 0; _indice < sourcePoperties.Count; _indice++)
                {
                    if (sourcePoperties[_indice].Name.ToUpper() == dr.GetName(index).ToUpper());
                    {
                        string _tipoProp = sourcePoperties[_indice].PropertyType.ToString();
                        PropertyInfo info = sourcePoperties[_indice] as PropertyInfo;
                        if ((info != null) && info.CanWrite)
                        {
                            info.SetValue(newObject, dr.GetValue(index), null);
                        }
                    }
                }
            }
            entitys.Add(newObject);
        }
        dr.Close();
        lista = entitys;
    }
}

Затем я вызываю его из моего уровня DataAcces, например:

public List <Entities.ENFactura> ListaxIdFactura (SqlTransaction Tr, Entities.ENFactura oBEFactura)
{

    SqlConnection Cn = new SqlConnection(); 
    Cn = _Connection.ConexionSEG();

    List<Entities.ENFactura> loBEFactura = new List<Entities.ENFactura>();

    using (Cn)
    {
        Cn.Open();
        SqlDataReader drd = (odaSQL.fSelDrd(Cn, Tr, "Pa_CC_Factura_Listar_x_IdProveedor", oBEFactura));
        if (drd != null)
        {
            if (drd.HasRows)
            {
                mapeador.MapearDataReaderListaObjetos <ENFactura>(drd, loBEFactura);
            }
        }
    }
    return (loBEFactura);
}

Таким образом, DAL получает устройство чтения данных, сопоставляет его со списком бизнес-объектов и возвращает его на уровень бизнес-логики.

У этого класса (MapeadorDataReaderListaObjetos) все еще есть некоторые проблемы, особенно по адресу:

info.SetValue(newObject, _valor, null);

newObject и _valor должны быть одного типа, иначе вы получите исключение (например, преобразование из System.Int64 в System.Int32, если ваше свойство сущности имеет тип Int32, а его соответствующее поле в таблице базы данных - bigint) .

Кроме того, если свойство объекта является другим объектом, это не будет работать, поскольку средства чтения данных не возвращают объекты объекта.

Очевидно, это можно улучшить.

Что касается рефлексии и делегатов, я нашел эту статью: рефлексия - медленно или быстро? Демонстрация с решениями, Абхишек Сур, в http://www.abhisheksur.com/2010/11/reflection-slow-or-faster-demonstration.html

Еще одна хорошая статья: «Уклоняйтесь от общих ловушек производительности для создания быстрых приложений», Джоэл Побар, по адресу http://msdn.microsoft.com/en-us/magazine/cc163759.aspx.

Надеюсь, это поможет.

2 голосов
/ 30 июля 2009

Стоимость отражения не должна быть такой большой, как вы думаете. В дополнение к делегатам (которые обсуждает Джон) вы также можете использовать такие вещи, как HyperDescriptor , чтобы минимизировать затраты на отражение без значительного изменения кода - вместо этого просто становится PropertyDescriptor:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(myCloudInstance);
// ideally cache props, but not essential

тогда

object val = props["IsWhite"].GetValue(myCloudInstance);

или, если вы используете его много, подумайте и о хранении PropertyDescriptor где-нибудь.

Однако ... как и Джон, я действительно не уверен на 100%, что вы пытаетесь сделать!

1 голос
/ 15 мая 2010

Я думаю, что лучший способ сделать это - получить метод получения или установки, преобразовать его в делегат и работать с делегатом, более быстрого способа нет:

PropertyInfo propertyInfoProperty1 = type.GetType().GetProperty("Property1");
Func<TYPE, string> get_Property1 = (Func<TYPE, string>)Delegate.CreateDelegate(typeof(Func<TYPE, string>), propertyInfoProperty1.GetGetMethod());

Затем вызовите метод получения:

string value = get_Property1(type);

Вы можете кэшировать делегатов.

0 голосов
/ 30 июля 2009

Динамическая сборка должна помочь с заботой о производительности отражения. Кто-то реализовал оценщики свойств с использованием динамической сборки здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...