2014-11-24 2 views
1

Давайте предположим, что у меня есть следующий класс:Изменения типа свойства, используя отражение

public class UniqueEntity { 
    public object Key { get; set; } 
} 

То, что я хочу, чтобы иметь возможность изменить тип Key, от System.Object до System.Int32, во время выполнения.

Я бы предположил, что единственный способ, которым это может быть выполнено (если он может), использовать отражение.

Тип недвижимости можно получить по собственному усмотрению PropertyType собственности: PropertyInfo (извините за недостаток).

typeof(UniqueEntity).GetProperty("Key").PropertyType; 

Проблема в том, что она доступна только для чтения. Я не могу установить значение PropertyType = typeof(int);.

Есть ли способ изменить тип недвижимости?

+0

Для справки. Я хочу сделать это, потому что «Key» будет аннотирован с атрибутом. Внешняя Framework определит это свойство и получит его тип из свойства PropertyType. Было бы здорово, если 'System.Int32' будет возвращен вместо' System.Object' –

+0

. Интересный вопрос. Я не верю, что вы можете сделать это во время выполнения. Но, будучи объектом, вы можете хранить что-нибудь в нем, а затем просто выполнять кастинг времени исполнения. –

+0

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

ответ

0

№ Тип любого члена класса, будь то значение поля, свойства или метода, а также типы любых параметров метода, определяется во время компиляции.

В вашем примере вы можете сохранить Int32 в продаже. Он будет «в коробке», и вы можете вернуть его обратно на Int32 по мере необходимости. Но тип имущества сам остался бы Object.

+0

Проблема заключается в том, что внешняя инфраструктура использует значение в PropertyType для выполнения своей работы. Это беспорядок, если его 'System.Object'. –

+0

@MatiCicero: можете ли вы не создавать разные классы, которые имеют разные типы для этого свойства? Можете ли вы использовать атрибуты для настройки поведения фреймворка? Есть ли в этой области перехватчики, позволяющие выполнять пользовательскую обработку? – siride

+0

@MatiCicero: извините. Конкретная проблема не изменяет правила языка. Похоже, вам придется создать объект «прокладки», который может выступать в качестве прокси-сервера между вашей внешней структурой и вашим внутренним типом сущности. –

0

Ok, так что ...

Основной вопрос заключается в том, что у меня был этот класс:

public class UniqueEntity { 
    [key] 
    public object Key { get; set; } 
} 

EntityFramework Но путает создание таблицы при обработке object ключей. Моя идея заключалась в том, что ключом может быть любой тип, заданный дочерним классом.

Я начал использовать дженерики:

public class UniqueEntity<T> where T : IComparable, IComparable<T> 
{ 
    [Key] 
    public T Key { get; set; } 
} 

Это хорошо работало в начале, но привело к серьезным проблемам дизайна позже при создании своих родовых репозиториев (Repository определение было бы как IRepository<T,E>, когда IRepository<E> будет достаточно.


Таким образом, EntityFramework использует значение свойства аннотированный с атрибутом Key, чтобы получить тип ключа хозяйствующего субъекта PropertyInfo. Если только я мог бы изменить этот тип независимо от того, кем он хотел (во время выполнения), и вообще избегать использования дженериков, было бы здорово.


Оказывается, вы не можете удалить свойство или изменить его тип buuuuuut .. Вы действительно можете создать новое фиктивное свойство с пользовательскими атрибутами, и удалить атрибут из исходной Key собственности !!

Для этого нам нужен CustomReflectionContext (System.Reflection.Контекст):

public class Modifier : CustomReflectionContext 
{ 
    private string propName; 
    private object propValue; 

    public Modifier(string propName, object propValue) 
    { 
     this.propName = propName; 
     this.propValue = propValue; 
    } 

    protected override IEnumerable<PropertyInfo> AddProperties(Type type) 
    { 
     Type newType = MapType(propValue.GetType().GetTypeInfo()); 
     return CreateProperty(newType, propName, o => propValue, (o, v) => propValue = v, 
            new Attribute[] { new KeyAttribute() }, new Attribute[] { }, new Attribute[] { }); 
    } 

    protected override IEnumerable<object> GetCustomAttributes(MemberInfo member, IEnumerable<object> declaredAttributes) 
    { 
     return new Attribute[] { }; 
    } 
} 

С помощью этого небольшого класса, мы можем создать свой собственный тип, чтобы дать EntityFramework, и с новой собственности, которая имеет теперь [Key] аннотацию:

var context = new Modifier("NewKey", 0); 
    var uniqueEntityType = context.MapType(typeof(UniqueEntity).GetTypeInfo()); 
    var keyType = uniqueEntityType.GetProperty("Key").PropertyType; 
    var keyAttrs = uniqueEntityType.GetProperty("Key").GetCustomAttributes(); 
    var newKeyType = uniqueEntityType.GetProperty("NewKey").PropertyType; 
    var newKeyAttrs = uniqueEntityType.GetProperty("NewKey").GetCustomAttributes(); 
    Console.WriteLine("Key Property. Type: {0}, Attribute: {1}", keyType, keyAttrs.FirstOrDefault()); 
    Console.WriteLine("NewKey Property. Type: {0}, Attribute: {1}", newKeyType, newKeyAttrs.FirstOrDefault()); 
    Console.ReadLine(); 

Proof Image

Смежные вопросы