【问题标题】:AutoMapper requires Get Accessor to Set. CS0154 The property or indexer 'Id' cannot be used in this context because it lacks the get accessorAutoMapper 需要 Get Accessor 来设置。 CS0154 无法在此上下文中使用属性或索引器“Id”,因为它缺少 get 访问器
【发布时间】:2017-07-05 17:46:09
【问题描述】:

我的ViewModel 类中的Id 属性可以设置,但由于setter 加密了值,所以无法设置。要获得该值,我必须使用 GetEncryptedId()GetDecryptedId()

视图模型

public ViewModel
{
    public int _id;
    public int Id { set { _id = Encrypt(value); }
    public Child ChildProperty {get; set; }
}

public Child
{
    public int Id {get; set;} 
    public string Name {get; set; }
}

这里的问题是,出于某种原因,Auto Mapper 需要一个 get 访问器,以便它可以设置一个值。

public ViewModelProfile()
{
    CreateMap<Model, ViewModel>().ForMember(vm => vm.Id, opt => opt.MapFrom(m => m.ChildProperty.Id))
}

这会抛出错误并说明:

CS0154 The property or indexer 'Id' cannot be used in this context because it lacks the get accessor.
  1. 为什么 Auto Mapper 需要“获取访问器”来设置值。
  2. 是否有强制设置而不获取的配置选项?

作为一种解决方法,我添加了一个Get { return -1; },但这远非理想。

【问题讨论】:

  • 我无法回答你的问题,但我提供这个是为了提供帮助:这违反了框架设计指南(Cwalina,Abrams)的第 5.2 节:“不要提供 set-只有属性。如果无法提供属性 getter,则将功能实现为方法。"
  • 重构 API 的建议仍然很有价值——只设置属性是个坏主意。使用显式方法设置值,或仅通过构造函数设置值。如果您绝对需要一个属性来满足其他 API 的需求,请为此提供一个适配器。或者只拥有EncryptedIDUnencryptedID 属性;设置一个更新两者。其中任何一个都比 O.Id = 5 在幕后做一些奇怪的加密要直观得多。
  • 谢谢@JeroenMostert 解决了这个问题。将您的 cmets 弹出到答案中,我会将其标记为答案。
  • @Amy,感谢您的提醒。如果使用方法,它会使映射成为一项单调的任务。我需要手动指定每次使用哪种方法。我会熟悉这些指南,因为我以前没有听说过。

标签: c# automapper


【解决方案1】:

这不是 AutoMapper 本身的限制,而是其 API 的结构方式。无法构造表达式树vm =&gt; vm.Id,因为您已经猜到了,这是对属性getter 的引用,这是不可能的,因为没有getter。传递表达式树作为引用成员的强类型方式是一种标准技术。到目前为止,AutoMapper 并不是唯一有此问题的东西。在这种情况下,AutoMapper 最终不会调用 getter 的事实并不重要。

幸运的是,ForMember 有一个覆盖,它接受成员名称作为字符串,并且使用它可以避免表达式树的问题:

CreateMap<Model, ViewModel>()
    .ForMember(nameof(ViewModel.Id), opt => opt.MapFrom(m => m.ChildProperty.Id))

【讨论】:

    【解决方案2】:

    我就是这样做的:

     //Mapper Class
    
     public partial class AutoMapperConfig
     {
      public static MapperConfiguration UserLoginTovmLogin = null;
    
      public static void Mappings()
        {
            UserLoginTovmLogin = new MapperConfiguration(cfg =>
            cfg.CreateMap<User_Login, VmLogin>()
            .ForMember(conf => conf.LoginId, dto => dto.MapFrom(src => src.Login_Id))
            .ForMember(conf => conf.Passsword, dto => dto.MapFrom(src => src.Passsword)));
        }
      }
       //In your Data login class
       VmLogin IAuthRepository.Login(string loginId)
        {
            VmLogin login = new VmLogin();
            var result = //Your Data Logic
            AutoMapperConfig.UserLoginTovmLogin.CreateMapper().Map(result, login);
            return login; 
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-15
      • 2019-07-05
      • 2022-12-13
      相关资源
      最近更新 更多