Good time, it became necessary to get the type of the child from its parent, this is due to the fact that I use EntityFramework and with the "Materialization" of data I hang on the event, the handler that accepts this entity

((IObjectContextAdapter) this).ObjectContext.ObjectMaterialized += (sender, e) => { DateTimeKind.Apply(e.Entity); }; 

and in his body, trying to get the corresponding item from the generic collection. For clarity

 abstract class BaseDateTimeDescriptor { } class DateTimeDescriptor<TEntity> : BaseDateTimeDescriptor { public DateTimeDescriptor(Func<TEntity, PropertyInfo> selector) { FieldInfo = selector; } public Func<TEntity, PropertyInfo> FieldInfo { get; set; } } class DateTimeConfigurator { static DateTimeConfigurator() { Descriptors = new Dictionary<Type, BaseDateTimeDescriptor>(); } //меня тут вынуждают создать BaseDateTimeDescriptor, т.к. я не могу просто так написать DateTimeDescriptor<TEntity> public static Dictionary<Type, BaseDateTimeDescriptor> Descriptors { get; set; } public static void Add<TEntity>(Func<TEntity, PropertyInfo> selector) { Descriptors.Add(typeof(TEntity), new DateTimeDescriptor<TEntity>(selector)); } } 

As you can see, I use a dictionary whose element values ​​are base classes. But I always, when calling the Add method from DateTimeConfigurator, create an instance of a successor. Already in the handler method itself, I get this collection

 public static void Apply<TEntity>(TEntity entity) { var descriptor = DateTimeConfigurator.Descriptors.Where(x => x.Key == entity.GetType()).First(); //тут я получаю первый попавшийся дескриптор из "словаря", который соответствует типу entity var fieldDescriptor = descriptor.Value as DateTimeDescriptor<TEntity>; //поскольку EntityFramework передась entity как object, то и будет попытка привестить к object, которая вернет Null var date = fieldDescriptor.FieldInfo.Invoke(entity); //И тут выкидывает nullrefexception } 

and try to bring the base class to the heir to get access to "FieldInfo", but due to the fact that TEntity is of type object, the cast is not correct (returns null). I have 2 questions about this. Is it possible to pass the correct type to the handler, and not the object? Or, in the handler itself, retrieve the entity type and pass it to the cast operator.

 var fieldDescriptor = descriptor.Value as DateTimeDescriptor<Каким-то образом верно определенный тип сущности> 
  • and what is the real type of descriptor.Value ? - Grundy
  • DateTimeDescriptor <TEntity> - simply good
  • In the DateTimeConfigurator class, there is an Add method that creates and adds an instance of a successorsimply good
  • No, the real one is the type at the time of execution, TEntity already defined TEntity , most likely the real TEntity does not coincide with that. to which the casting attempt is going, therefore as a result of Null - Grundy
  • If I write an explicit type, for example, var fieldDescriptor = descriptor.Value as DateTimeDescriptor <MyType> then everything will be fine, but the fact is that there are different types from the database (depending on the table with which I pull out) so you need a universal way - simply good

1 answer 1

Since a variable with the type object is passed to the generic method, inside the function TEntity there will be an Object, and

 DateTimeDescriptor<TEntity> 

Instead of the expected type will be

 DateTimeDescriptor<object> 

As a workaround, you can use reflection when calling.

Instead of this line

 DateTimeKind.Apply(e.Entity); 

Will be so

 typeof(DateTimeKind).GetMethod("Apply", System.Reflection.BindingFlags.Static | BindingFlags.Public) // берем публичный статический метод Apply .MakeGenericMethod(e.Entity.GetType()) // на его основе создаем generic меток с конкретным типом .Invoke(null, new[] { e.Entity }); // вызываем полученный метод