代码之家  ›  专栏  ›  技术社区  ›  Leo

这样使用接口是否正确,是否有更好的选择?

  •  1
  • Leo  · 技术社区  · 14 年前

    public interface IViewModel { }
    
    public interface IToViewModel<T> where T : IViewModel { }
    
    public static class MvcExtensions
    {
        public static T ToViewModel<T>(this IToViewModel<T> self)
            where T : IViewModel
        {
            var instance = Activator.CreateInstance<T>();
    
            //this line just copys the properties with the same name from one object to another
            self.Reflected().CopyMatchingPropertiesTo(instance /*destiny*/);
    
            return instance;
        }
    
    }
    

    我的意思是这样做:

    public partial class UserInfo : IToViewModel<UserInfoViewModel> { }
    
    public class UserInfoViewModel : IViewModel
    {
        [DisplayName("UserId")]
        public Guid UserId { get; set; }
    
        [DisplayName("User name")]
        public string Username { get; set; }
    
        [DisplayName("Email address")]
        public string Email { get; set; }
    }
    
    public ActionResult Index(string username)
    {
        UserInfo userInfo = UserInfoHelper.Load(username);
    
        UserInfoViewModel userInfoViewModel = userInfo.ToViewModel();            
    
        return View(userInfoViewModel);
    }
    

    好的,代码运行正常,np。

    但我的问题是接口的使用。。。

    我的目标是将EntityFramework对象转换为ViewModel,以便与ASP MVC视图一起使用 在不做大量参数传递的情况下,我在接口中找到了一种方式来说明每个对象是什么,它们执行什么。

    你们觉得怎么样? 有什么很酷的blogpost/doc/etc吗? 你知道怎样才能做得更好吗? 我现在该睡觉了吗?

    另外,.Net带来了很多新的做事方式。。。像linq,lambda,扩展方法,表达式树。。。有没有关于这些东西的“良好实践”的研究?

    我认为这是巨大的,让你的大脑在你解决问题的时候思考不同。。。我想看看人们是怎么想/怎么做的。

    1 回复  |  直到 14 年前
        1
  •  2
  •   Matthew Abbott    14 年前

    我想这可能是一个标记接口和功能接口的问题。我通常不喜欢标记接口,但我知道为什么你会这样使用它。

    我个人认为你应该有一个重载的构造函数:

    public class UserViewModel
    {
      // Constructor used in model binding.
      public UserViewModel() { }
    
      // Constructor used for mapping.
      public UserViewModel(UserEntity entity)
      {
    
      }
    }
    

    我有这个偏好,因为它清楚地定义了我需要的依赖。我知道你对任何类型的应用都失去了一些忠诚,但我认为它更干净。

    另一种选择是 AutoMapper

    Mapper.CreateMap<UserEntity, UserViewModel>();
    
    public static TTarget Map<TSource, TTarget>(this TSource instance)
    {
      return Mapper.Map<TSource, TTarget>(instance);
    }
    
    var user = DataContext.Users.Where(u => u.Username == "Matt").Single();
    return user.Map<UserViewModel>();
    

    现在,您必须提前创建一个特定的映射,但是您的扩展方法可以用于为其创建映射的任何类型。AutoMapper的默认行为是在匹配的属性之间进行映射,但是您也可以通过特定的方式和映射特定的属性。