Mapping interface or abstract class component

纵饮孤独 提交于 2019-12-04 13:26:24

问题


Please consider the following simple use case:

public class Foo 
{ 
    public virtual int Id { get; protected set; } 
    public virtual IBar Bar { get; set; } 
} 

public interface IBar 
{ 
    string Text { get; set; } 
} 

public class Bar : IBar 
{ 
    public virtual string Text { get; set; } 
} 

And the fluent-nhibernate map class:

public class FooMap : ClassMap<Foo> 
{ 
    public FooMap() 
    { 
        Id(x => x.Id); 
        Component(x => x.Bar, m => 
        { 
            m.Map(x => x.Text); 
        }); 
    } 
} 

While running any query with configuration, I get the following exception:

NHibernate.InstantiationException: "Cannot instantiate abstract class or interface: NHMappingTest.IBar"

It seems that NHibernate tries to instantiate an IBar object instead of the Bar concrete class. How to let Fluent-NHibernate know which concrete class to instantiate when the property returns an interface or an abstract base class?

EDIT: Explicitly specify the type of component by writing Component<Bar> (as suggested by Sly) has no effect and causes the same exception to occur.

EDIT2: Thanks to vedklyv and Paul Batum: such a mapping should be soon is now possible.


回答1:


I haven't tried this myself but i saw an example in the fluent nh source where the lambda is cast to the concrete class:

public class FooMap : ClassMap<Foo> 
{ 
    public FooMap() 
    { 
        Id(x => x.Id); 
        Component(x => (Bar) x.Bar, m => 
        { 
            m.Map(x => x.Text); 
        }); 
    } 
}

EDIT: Obviously that's exactly the same result as Sly's suggestion so that did no good. I tested it against the trunk version of fluent nh and it didn't work. It does work though if you use a many-to-one mapping:

  public class FooMap : ClassMap<Foo>
  {
    public FooMap()
    {
      Id(x => x.Id);
      References<Bar>(x => x.Bar).Cascade.All();
    }
  }

  public class BarMap : ClassMap<Bar>
  {
    public BarMap()
    {
      Id(x => x.Id);
      Map(x => x.Text);
    }
  }

UPDATE

This was actually an easy fix. I have submitted a patch (link text) that makes Sly's solution to work.




回答2:


Maybe this?

public FooMap()
    {
        Id(x => x.Id);
        Component<Bar>(x => x.Bar, m =>
        {
            m.Map(x => x.Text);
        });
    }



回答3:


Here's a similar topic using the union-subclass approach, although the example does not use the fluent interface for the map:

Click for article...




回答4:


Have not used the fluent NHibernate yet but seems to me what you are trying to do is map to an IUserType which you haven't told hibernate how to deal with. here is a useful example for defined usertypes in fluent.

http://blog.jagregory.com/2009/01/11/fluent-nhibernate-auto-mapping-type-conventions/



来源:https://stackoverflow.com/questions/1548839/mapping-interface-or-abstract-class-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!