Question

Je travaille sur un problème dans lequel j'ai un certain nombre d'entités, dont chacune a une à plusieurs traductions tableau correspondant, qui spécifient les versions localisées des champs de l'entité. (Tout cela est schéma héritage que je suis d'ajouter une carte au-dessus de). Par exemple:

  • Événement
    • ID
  • EventTranslation
    • EventID
    • Langue
    • Titre
    • d'autres champs

Donc, si je devais rendre mes informations en grec, je voudrais joindre les deux tables et spécifiez Language = « grec » et ont toutes les bonnes choses.

Ce que je suis en train de faire est de construire sur la volée mixins qui intègrent directement les bonnes données en un seul objet et retour que le résultat des requêtes, donc comme:

var someEvent = session.CreateCriteria<Event>().SetMaxResults(1).UniqueResult<IEvent>();
Console.WriteLine(someEvent.Title);

Pour ce faire, je suis en train de mettre en place un intercepteur NHibernate pour créer mixins DynamicProxy. Sauf que cela ne fonctionne pas, et je ne sais pas pourquoi. Voici la mise en place, mieux que je pouvais le simplifier.

Voici l'événement:

class Event : IEventEntity {
   //ID and props here
   public IList Translations {get; set;}
}

IEvenEntity a également un getter et setter pour la liste. Il y a aussi une classe EventTranslation, ce qui est super simple et met en œuvre IEventTranslation de la manière la plus évidente possible.

La carte couramment pour l'événement:

class EventMap : ClassMap<Event>{
  //obvious ID and properties stuff here...
  HasMany<EventTranslation>(x => x.Translations);
}

fonctionne très bien sur son propre - je peux interroger pour les événements et accédez à leurs traductions. Je suis assez sûr que la mise en correspondance est bonne.

Je la forme de basé mes affaires intercepteurs sur un très cool Guide par Krzysztof Kozmic pour faire quelque chose un peu lié. Tout d'abord, j'ai créé un superinterface que je vais mettre en œuvre avec un proxy dynamique:

public interface IEvent : IEventEntity, IEventTranslation{}

Voici mon intercepteur NH. De toute évidence, je suis le piratage comme un fou:

public class EventInterceptor : NHibernate.EmptyInterceptor
{
    private readonly static ProxyGenerator gen = new ProxyGenerator();

    public override object Instantiate(string clazz, NHibernate.EntityMode entityMode, object id)
    {
           var mixin = gen.CreateClassProxy(typeof(object), new[] { typeof(IEvent) }, new DynInterceptor());
                    //would also need to set the identifier here
            return mixin;
    }
}

Où DynInterceptor est un intercepteur qui fait réellement le travail d'entrer dans le sac de relations, obtenir la bonne traduction, et le retour de la juste valeur. Les détails ne sont pas trop pertinent, car il ne sera jamais appelé.

Après avoir attaché à l'intercepteur NH, je vois qu'il est en cours d'exécution, et en fait NH obtient la distribution à droite de IEvent (à savoir le proxy est au moins en cours de création). Mais pour une raison quelconque, totalement plisse l'entité hydratant:

Unhandled Exception: NHibernate.PropertyAccessException: could not set a property value by reflection setter of Event.Translations ---> System.Reflection.TargetException: Object does not match target type.
   at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisib
ilityChecks)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invoke
Attr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, B
indingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
   at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, O
bject[] index)
   at NHibernate.Properties.BasicPropertyAccessor.BasicSetter.Set(Object target,
 Object value) in C:\thirdparty\NHibernate\src\NHibernate\Properties\BasicProper
tyAccessor.cs:line 304

Il me semble que cela ne fonctionne pas parce que NH utilise la réflexion pour définir la propriété, mais bien sûr, le type de cible est erroné parce que je troqué un IEvent pour l'événement. Yat-il un moyen de contourner cela?

En outre, dans la mesure où l'approche de base, est-il une meilleure façon de le faire dans le New Hampshire?

Était-ce utile?

La solution

OK, so for how complicated I made that question, it turns out to be pretty simple, and if I'd known enough, I could have asked the question as "how do I dynamically make an object implement another interface without losing its type?". The answer is to provide a target, as in

Type type = Type.GetType(clazz, false);
var mixin = (Event)gen.CreateClassProxy(type, new[] { typeof(IEvent) }, new DynInterceptor());

Autres conseils

I'm not sure, but I think you should use a filter in combination with an eventlistener to get the result you want. If you set a filter on your language table and use an eventlistener to enable the filter before the events you want to enable filtering you might get the desired behavior.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top