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();
Для справки. Я хочу сделать это, потому что «Key» будет аннотирован с атрибутом. Внешняя Framework определит это свойство и получит его тип из свойства PropertyType. Было бы здорово, если 'System.Int32' будет возвращен вместо' System.Object' –
. Интересный вопрос. Я не верю, что вы можете сделать это во время выполнения. Но, будучи объектом, вы можете хранить что-нибудь в нем, а затем просто выполнять кастинг времени исполнения. –
Невозможно, что вы хотите, но вы можете наследовать этот класс и создать новое свойство, которое отображает это свойство, и вы используете только новое свойство. –