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

发布于 2024-10-14 03:47:51 字数 1683 浏览 6 评论 0原文

我正在使用 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代理类导致值注入器不运行匹配国家/地区类型吗?但这没有意义,因为它在展平过程中起作用。
  • 也许由于某种原因,扁平化没有被触发。即 Dto 是 CountryCode,Domain 是 Country.Code

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

I am using ValueInjecter to map properties from a Domain model to a DTO served up via a Service Layer. The service in question also accepts updates... so an updated DTO is passed in and this is then injected to the domain object and saved.

    // 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;
    }

Now all this above code does is updates the Property Member.Country.Code which is obviously not what I need it to do.

So from the docs, I figured I needed to create an override and got this:

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;
    }

My problem is during debugging, CountryLookup never gets called.

Possible reasons I can think of:

  • Nhibernate Proxy classes causing value injecter to not match the Country type? Tho this doesnt make sense because it works during the flattening.
  • Perhaps the unflattening isn't firing for some reason. I.e Dto is CountryCode and Domain is Country.Code

I need to use the CountryCode property on the Dto to call a countryService.LookupCode to return the correct object to use during the update injection.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

够钟 2024-10-21 03:47:51

Unflattening 就是这样做:

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 的情况?到国家并返回,也可以继承实体的任何其他类型

unflattening would be to do this:

entity.Country.Code <- dto.CountryCode

what you need is:

entity.Country <- dto.CountryCode

so the solution for you would be to inherit an ExactValueInjection where you would go from CountryCode to Country.

what I recommend you to do is do the same that I did in the live demo of another project of mine http://awesome.codeplex.com

where I have something like this:

    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;}
    }

and use these injections to go from entity to dto and back

    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;
            }
        }

these injections will handle not just going from int? to Country and back but also any other type which inherits Entity

野味少女 2024-10-21 03:47:51

使用 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;
}

Using the suggestion/reference from Omu this was the specific code to the problem.

 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;
}
思念绕指尖 2024-10-21 03:47:51

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

Is a framework calling the setter method? In most DI frameworks, the standard is lowercase 's' in the setMethod(). Just a first-thought recommendation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文