0

I couldn't make interface mapping work, anyidea how to do this?

public class Event 
{
    public virtual int EventId { get; set; }
    public virtual string Name { get; set; }
    public virtual ENEventNodeType EventType { get; set; }
    public virtual IEventNode EventNode { get; set; }
}

public interface IEventNode {}

public enum ENEventNodeType : short
{
    [Description("Mission")]
    Mission = 1,
    [Description("Task")]
    Task = 2,
    [Description("Quiz")]
    Quiz = 3
}

public class Mission : IEventNode
{
    public virtual int MissionId { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Event> EventList { get; set; }   
}

public class Task : IEventNode
{
    public virtual int TaskId { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Event> EventList { get; set; }    
}

Why I am doing this: IEventNode could be 20+ different class and Event can have only one. so other 19+ fields will be always null. I was trying to set Id on same field and EventNodeType shows which class's id is in the field. alternatives welcomed

SOLUTION 1) AutoMappingOverride

public class EventMappingOverride : IAutoMappingOverride<Event>
{
    public void Override(AutoMapping<Event> mapping)
    {
        var any = mapping.ReferencesAny(x => x.EventNode)
            .EntityIdentifierColumn("EventNodeId")
            .EntityTypeColumn("EventType")
            .IdentityType<int>()
            .MetaType<int>();

        foreach (var eventNodeType in typeof(Event).Assembly.GetExportedTypes().Where(typeof(IEventNode).IsAssignableFrom))
        {
            if (!eventNodeType.IsInterface && !eventNodeType.IsAbstract)
                any.AddMetaValue(eventNodeType, eventNodeType.Name);
        }
    }
}
Mert
  • 6,432
  • 6
  • 32
  • 68
  • 2
    *Just a NOTE: I do not have experience with that at all. Honestly, I never used interface for mapped Domain Objects (POCOs). Maybe there is another similar view on that: http://stackoverflow.com/a/845714/1679310. The pont is: if `IEventList` is implemented by two or more different entities which are mapped to different tables... what should mean EventList.ID == 1 ? is it implementer A or B or C... I would suggest to avoid that approach* – Radim Köhler May 17 '15 at 17:56
  • @Radim Köhler any alternative solution? – Mert May 17 '15 at 18:04
  • My way *(just a hint)*. Extend the POCO objects with either `Mission Mission { get; set; }` or `Task Task { get; set; }` or both. Depends which columns do exist *(and do reference which tables)* in the `Event` table *(`MissionId` or `TaskId`)*. This way, we have clear mapping, what is behind which column *(C# reference equals foreigh keys)*. Then we can implement `inteface IHaveEventNode { IEventNode { get; } }` and return `Mission` or `Task`. What I effectively say - the DB has either Mission or Task reference. The same should be in mapping. Hope it helps a bit... while just a comment – Radim Köhler May 17 '15 at 18:17

1 Answers1

1
public class Event
{
    public virtual int EventId { get; set; }
    public virtual string Name { get; set; }
    public virtual IEventNode EventNode { get; set; }
}

public interface IEventNode { }

// example using FluentNHibernate Mapping
public class EventMap : ClassMap<Event>
{
    public EventMap()
    {
        Id(x => x.EventId);

        Map(x => x.Name);
        var any = ReferencesAny(x => x.EventNode)
            .EntityIdentifierColumn("eventNode_id")
            .EntityTypeColumn("EventType")
            .IdentityType<int>()
            .MetaType<int>();

        foreach (var eventNodeType in   typeof(Event).Assembly.GetExportedTypes().Where(typeof(IEventNode).IsAssignableFrom))
        {
            if (!eventNodeType.IsInterface && !eventNodeType.IsAbstract)
                any.AddMetaValue(eventNodeType, eventNodeType.Name);
        }
    }
}

then do

if (event.EventNode is Mission)
    Write("Hey its a mission");
...
Firo
  • 30,626
  • 4
  • 55
  • 94
  • this is looks pretty cool, how do I implement this on automapper? any convention example? – Mert May 18 '15 at 15:56
  • I did convert your code into AutoMappingOverride, and pasted at end of question as solution but still looking something general like a convention which will find Interfaces and handles proccess itself. – Mert May 18 '15 at 22:33
  • 1
    I am not sure if it is possible because Automapping has to automap the property as referenceany instead of reference to begin with. I'll investigate later – Firo May 19 '15 at 07:15
  • 1
    unfortunatly there is no sign that automapping supports ReferenceAny – Firo Jun 23 '15 at 06:40
  • thats sad, It d be such a useful tool. – Mert Jun 23 '15 at 07:17