价值注入:Dto到域模型(NHibernate)

时间:2011-01-24 14:31:45

标签: nhibernate dto automapping valueinjecter

我正在使用ValueInjecter将域模型中的属性映射到通过服务层提供的DTO。有问题的服务也接受更新...因此传入更新的DTO,然后将其注入域对象并保存。

    // Domain
    public class Member 
    {
      public Country Country { get; set; }
    }

    public class Country 
    {
      public string Code { get; set; }
      public string Name { get; set; }
    }

    //Dto
    public class MemberDto 
    {
       public string CountryCode { get; set; }
    }

    //Transformation Method attempt 1
    public Member InjectFromDto (MemberDto dto, Member source)
    {
       source = source.InjectFrom<UnflatLoopValueInjection>(dto);
       return source;
    }

现在所有上面的代码都是更新Property Member.Country.Code,这显然不是我需要它做的。

所以从文档来看,我认为我需要创建一个覆盖并得到它:

public class CountryLookup: UnflatLoopValueInjection<string, Country>
    {
        protected override Country SetValue(string sourcePropertyValue)
        {
            return countryService.LookupCode(sourcePropertyValue);
        }
    }


 //revised transformation call
 //Transformation Method attempt 2
    public Member InjectFromDto (MemberDto dto, Member source)
    {
       source = source.InjectFrom<UnflatLoopValueInjection>(dto)
                      .InjectFrom<CountryLookup>(dto);
       return source;
    }

我的问题是在调试过程中,CountryLookup永远不会被调用。

我能想到的可能原因:

  • Nhibernate Proxy类导致值injecter与Country类型不匹配?这没有意义,因为它在扁平化过程中起作用。
  • 也许由于某种原因,不讨人喜欢不会被解雇。即,Dto是CountryCode,Domain是Country.Code

我需要使用Dto上的CountryCode属性来调用countryService.LookupCode以返回在更新注入期间使用的正确对象。

3 个答案:

答案 0 :(得分:3)

不赞成就是这样做:

entity.Country.Code <- dto.CountryCode

你需要的是:

entity.Country <- dto.CountryCode

所以你的解决方案就是继承一个ExactValueInjection,你可以从CountryCode转到Country。

我建议您这样做与我在我的另一个项目的现场演示中所做的相同http://awesome.codeplex.com

我有这样的事情:

    public class Entity
    {
       public int Id{get;set;}
    }
    public class Member : Entity
    {
        public Country Country{get;set;}
    }
    public class MemberDto : DtoWithId
    {
        public int? Country {get;set;}
    }

并使用这些注射从实体到dto并返回

    public class NullIntToEntity : LoopValueInjection
        {
            protected override bool TypesMatch(Type sourceType, Type targetType)
            {
                return sourceType == typeof(int?) && targetType.IsSubclassOf(typeof(Entity));
            }

            protected override object SetValue(object sourcePropertyValue)
            {
                if (sourcePropertyValue == null) return null;
                var id = ((int?) sourcePropertyValue).Value;

                dynamic repo = IoC.Resolve(typeof(IRepo<>).MakeGenericType(TargetPropType));

                return repo.Get(id);
            }
        }
//(you also need to have a generic repository, notice IRepo<>)    
    public class EntityToNullInt : LoopValueInjection
        {
            protected override bool TypesMatch(Type sourceType, Type targetType)
            {
                return sourceType.IsSubclassOf(typeof (Entity)) && targetType == typeof (int?); 
            }

            protected override object SetValue(object o)
            {
                if (o == null) return null;
                return (o as Entity).Id;
            }
        }

这些注射不只是处理来自int吗?到国家/地区然后返回以及继承实体

的任何其他类型

答案 1 :(得分:3)

使用Omu的建议/参考,这是该问题的具体代码。

 public class CountryLookup : ExactValueInjection
    {
        private ICountryService countryservice;

        public CountryLookup(ICountryService countryService)
        {
           this.countryService = countryService; 
        }

        protected override bool TypesMatch(Type s, Type t)
        {
            return (s == typeof(string)) && (t == typeof (Country));

        }
        protected override Object SetValue(object v)
        {
            if (v == null) 
                return null;

            var country = countryService.LookupCode((string) v);
            return country;
        }

        public override string SourceName()
        {
            return "CountryCode";
        }

        public override string TargetName()
        {
            return "Country";
        }    
    }

public Member InjectFromDto (MemberDto dto, Member source)
{
   source = source.InjectFrom<UnflatLoopValueInjection>(dto)
                  .InjectFrom<CountryLookup>(dto);
   return source;
}

答案 2 :(得分:0)

框架是否调用了setter方法?在大多数DI框架中,标准是setMethod()中的小写's'。只是第一个想法的推荐。