在不引用服务本身的情况下使用修饰的 WCF 实体 class

Use decorated WCF entity class without referencing service itself

我有一个服务,它产生了 class,比方说 OperationDescMyProject.Proxy 中。我想要我的 class,它包含 OperationDesc 的一些属性。所以我在 MyProject.Entity 中创建了一个 class OperationView 并从 OperationDesc.

派生了它
namespace MyProject.Proxy {

    public class OperationDesc {

        public long Id { get; set; }

        public DateTime Created { get; set; }
    }

}

namespace MyProject.Entity {

    using Proxy;

    public class OperationView : OperationDesc {

        public string DateString {
            get 
            {
                return Created.ToString();
            }
        }    
    }
}

namespace MyProject.Web {

    using Entity;

    public class HomeController : Controller {

        public ActionResult(){
            var operation = ... logic ...;
            operation.Id <--- require Proxy reference
        }

    }

}

现在我尝试在 MyProject.Web 中使用 OperationView,并参考 MyProject.Entity。但是我无法访问 OperationDesc 属性,除非我引用 Proxy 库,这是我不想做的。 你能建议我在这里需要使用的任何模式或方法吗? 主要目标是用一些额外的属性装饰服务 class,而不引用 Proxy 库。 Ofc 我可以将所有属性从 OperationDesc 复制到 OperationView 并使用 AutoMapper,但它看起来像反模式。谢谢

当您使用面向服务的体系结构时,假定服务器和客户端是完全不同的应用程序。因此,客户端不应该有关于您的服务实现的任何信息,包括您使用 c# 创建的模型 classes。客户端可能是 JavaScript 或 JAVA/Android 或 RoR 应用程序。因此,C# 创建的模型(classes)在客户端完全不可用。对于客户来说,重要的是您定义的协议。所以,假设你在服务器端(wcf 项目)有这个模型:

public class OperationDesc {

    public long Id { get; set; }

    public DateTime Created { get; set; }
}

客户需要知道的是这样的:

type OperationDesc {
    Id (Int64),
    Created (DateTime)
}

仅此而已。所以每个客户端都可能有自己的模型实现:

JavaScript:

function OperationDesc(){
    this.Id = 0;
    this.Created = new Date(); // or null or anything else
}

JAVA:

public class OperationDesc {
    private Long id;
    private Date created;

    public void setId(Long value) { this.id = value; }
    public Long getId() { return this.id; }

    public void setCreated(Date value) { this.created= value; }
    public Date getCreated() { return this.created; }
}

C#:

public class OperationDesc {

    public long Id { get; set; }

    public DateTime Created { get; set; }
}

现在,您已经定义了您的协议​​,您可以看到任何类型的客户端应用程序,都可以与您的服务进行通信。那么,在您的特定应用程序中,您需要额外的 属性 吗?好的,没问题:

public class OperationDesc {

    public long Id { get; set; }

    public DateTime Created { get; set; }

    public string DateString {
        get 
        {
            return Created.ToString();
        }
    }
}

(或者您可以创建一个纯 OperationDesc class 和一个

public class OperationView : OperationDesc {

    public string DateString {
        get 
        {
            return Created.ToString();
        }
    }    
}

正如您尝试对服务器端实体所做的那样。但是这一次,OperationDesc 不是服务器应用程序中的 class,而是客户端应用程序中的全新 class。

所以,不,在客户端创建 class 并复制所有属性并使用 AutoMapper 根本不是反模式。

但是:

如果您真的不关心 SOA 而只是想避免重复,您可以创建一个 class-library 项目并将所有模型放在那里(只是模型)并共享该库项目(包括服务和网络客户端)。我当然不建议这样做。