I haven't found an answer to this issue yet (neither here nor on
stackoverflow), so I suppose this is just a shortcoming in the current
implementation of mapping by code. I've created a IUserType for
HashedPassword as a workaround for now. HashedPassword is a fairly simple,
immutable single-column type with value semantics, so the implementation of
the user type wasn't very difficult. At least I can now use the IPassword
abstraction and configure the actual type in the mapping.
I'd still really appreciate feedback on why this can't be mapped as a
component.
Best,
Andre
Am Montag, 11. Februar 2013 21:47:10 UTC+1 schrieb Andre:
>
> In a framework I have an abstraction of a password:
>
> public interface IPassword
> {
> bool Matches(string password);
> }
>
> with different implementation that define how the password is represented,
> for example:
>
> public class HashedPassword : IPassword
> {
> public virtual string Hash { get; set; }
> public virtual string Salt { get; set; }
>
> public bool Matches(string password){ return /*...*/; }
> }
>
> I want to use the abstraction of the password in an entity:
>
> public class Login
> {
> ...
> public virtual IPassword Password { get; set; }
> }
>
> Only one specific implementation of IPassword will be used in the
> application. I use an abstract factory to instantiate the proper
> implementation of IPassword at runtime.
>
> Now I need to define a mapping for Login. I'd like to map Password as a
> component. Using XML this can be done with:
>
> <class name="Login">
> ...
> <component name="Password" class="HashedPassword">
> <property name="Hash" not-null="true" length="32"/>
> <property name="Salt" not-null="true" length="32"/>
> </component>
> </class>
>
> When I use XML mapping this works perfectly fine. However, I can't make it
> work using mapping-by-code/conformist. Here's an attempt:
>
> public class LoginMapping : ClassMapping<Login>
> {
> public LoginMapping()
> {
> ...
> Component(x => x.Password, comp => {
> comp.Class<HashedPassword>();
> comp.Property("Salt", map => map.Length(32));
> comp.Property("Hash", map => map.Length(32));
> });
> }
> }
>
> If I try to compile the mapping from this I get the following exception:
>
> NHibernate.MappingException: Member not found. The member 'Salt' does not
> exists in type IPassword
>
> Another attempt:
> public class LoginMapping : ClassMapping<Login>
> {
> public LoginMapping()
> {
> Id(x => x.Id, map => map.Generator(Generators.HighLow));
> Property(x => x.UserName, map => map.Length(32));
> Component(x => x.Password, comp => {
> comp.Class<HashedPassword>();
> comp.Property(x => (x as HashedPassword).Salt, map =>
> map.Length(32));
> comp.Property(x => (x as HashedPassword).Hash, map =>
> map.Length(32));
> });
> }
> }
>
> Now there's no exception but *no* property of HashedPassword gets mapped
> at all, ie. the generated mapping for the component is:
>
> <component class="HashedPassword" name="Password" />
>
>
> How can I map this component? Or more generally, how can I map components
> that are exposed as interfaces instead of the concrete type. Do I have to
> resort to a IUserType? It works when using XML, so hopefully I can get it
> to work using mapping-by-code.
>
> I have searched the group but haven't found the information to solve this.
> Your input is very much appreciated!
>
> Regards,
> Andre
>
--
You received this message because you are subscribed to the Google Groups
"nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/nhusers?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.